Merged V3.4-BUG-FIX to HEAD

29755: ALF-6742 Javascript error using the manager permissions action in the docLib on a folder that uses no inherit permissions
      Dmitry change: Modify permissions.js to store permissions that are not supported in separate array during _showDialog()
                     method invocation. Then add them into params that are going to setPermissions() method.
      Error no longer takes place and dialog appears as expected. 
   29756: UI coding standards for r29755
   29757: ALF-9908 Improvement to log output for high level audit to make it more readable to developers
   29767: ALF-9351 No exception with invalid permission definitions
      - DTD/Schema validation added
      - Corrected permissionDefinitions.xml (contained extra -->) so failed validation


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29802 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2011-08-16 17:17:02 +00:00
parent 9f67fd6ded
commit 5d7e3e52be
5 changed files with 144 additions and 20 deletions

View File

@@ -406,49 +406,49 @@
<!-- Permissions specific to avm website folder -->
<!-- ========================================== -->
<permissionSet type="wcm:avmfolder" expose="selected"> -->
<permissionSet type="wcm:avmfolder" expose="selected">
<permissionGroup name="ContentManager" extends="true" expose="true" />
<permissionGroup name="ContentPublisher" extends="true" expose="true" />
<permissionGroup name="ContentContributor" extends="true" expose="true" />
<permissionGroup name="ContentReviewer" extends="true" expose="true" />
</permissionSet>
<permissionSet type="wcm:avmplainfolder" expose="selected"> -->
<permissionSet type="wcm:avmplainfolder" expose="selected">
<permissionGroup name="ContentManager" extends="true" expose="true" />
<permissionGroup name="ContentPublisher" extends="true" expose="true" />
<permissionGroup name="ContentContributor" extends="true" expose="true" />
<permissionGroup name="ContentReviewer" extends="true" expose="true" />
</permissionSet>
<permissionSet type="wcm:avmlayeredfolder" expose="selected"> -->
<permissionSet type="wcm:avmlayeredfolder" expose="selected">
<permissionGroup name="ContentManager" extends="true" expose="true" />
<permissionGroup name="ContentPublisher" extends="true" expose="true" />
<permissionGroup name="ContentContributor" extends="true" expose="true" />
<permissionGroup name="ContentReviewer" extends="true" expose="true" />
</permissionSet>
<permissionSet type="wcm:avmcontent" expose="selected"> -->
<permissionSet type="wcm:avmcontent" expose="selected">
<permissionGroup name="ContentManager" extends="true" expose="true" />
<permissionGroup name="ContentPublisher" extends="true" expose="true" />
<permissionGroup name="ContentContributor" extends="true" expose="true" />
<permissionGroup name="ContentReviewer" extends="true" expose="true" />
</permissionSet>
<permissionSet type="wcm:avmplaincontent" expose="selected"> -->
<permissionSet type="wcm:avmplaincontent" expose="selected">
<permissionGroup name="ContentManager" extends="true" expose="true" />
<permissionGroup name="ContentPublisher" extends="true" expose="true" />
<permissionGroup name="ContentContributor" extends="true" expose="true" />
<permissionGroup name="ContentReviewer" extends="true" expose="true" />
</permissionSet>
<permissionSet type="wcm:avmlayeredcontent" expose="selected"> -->
<permissionSet type="wcm:avmlayeredcontent" expose="selected">
<permissionGroup name="ContentManager" extends="true" expose="true" />
<permissionGroup name="ContentPublisher" extends="true" expose="true" />
<permissionGroup name="ContentContributor" extends="true" expose="true" />
<permissionGroup name="ContentReviewer" extends="true" expose="true" />
</permissionSet>
<permissionSet type="wca:webfolder" expose="selected"> -->
<permissionSet type="wca:webfolder" expose="selected">
<permissionGroup name="ContentManager" extends="true" expose="true" />
<permissionGroup name="ContentPublisher" extends="true" expose="true" />
<permissionGroup name="ContentContributor" extends="true" expose="true" />

View File

@@ -22,6 +22,9 @@
<property name="model">
<value>alfresco/model/permissionDefinitions.xml</value>
</property>
<property name="dtdSchema">
<value>alfresco/model/permissionSchema.dtd</value>
</property>
<property name="nodeService">
<ref bean="nodeService" />
</property>

View File

@@ -152,6 +152,14 @@ import org.springframework.beans.factory.InitializingBean;
* /alfresco-access/transaction/sub-action/00/move/from/type=cm:folder
* /alfresco-access/transaction/sub-action/01/action=readContent
* </pre>
* The trace output from this class may be useful to developers as it logs method
* calls grouped by transaction. The debug output is of the audit records written
* and full inbound audit data. However for developers trace will provide a more
* readable form. Setting the following dev-log4j.properties:
* <pre>
* log4j.appender.File.Threshold=trace
* log4j.logger.org.alfresco.repo.audit.access.AccessAuditor=trace
* </pre>
*
* @author Alan Davis
*/
@@ -434,22 +442,49 @@ public class AccessAuditor implements InitializingBean,
{
if (logger.isDebugEnabled())
{
StringBuilder sb = new StringBuilder("\n\tAudit data:");
// Trace is used by a developer to produce a cut down log output that is simpler
// to read (no audit data section or summary keys)
boolean devOutput = logger.isTraceEnabled();
StringBuilder sb = new StringBuilder();
StringBuilder subActions = new StringBuilder("");
if (!devOutput)
{
sb.append("\n\tAudit data:");
for (String key : new TreeSet<String>(recordedAuditMap.keySet()))
{
sb.append("\n\t\t").append(key).append('=');
appendAuditMapValue(sb, recordedAuditMap.get(key));
}
sb.append('\n');
sb.append("\n\tInbound audit values: ");
sb.append("\n\n\tInbound audit values: ");
}
for (String key : new TreeSet<String>(auditMap.keySet()))
{
sb.append("\n\t\t").append(rootPath).append('/').append(key).append('=');
appendAuditMapValue(sb, auditMap.get(key));
if (!devOutput || !NodeChange.SUMMARY_KEYS.contains(key))
{
StringBuilder output = (key.startsWith(NodeChange.SUB_ACTION_PREFIX))
? subActions : sb;
output.append("\n\t\t").append(rootPath).append('/').append(key).append('=');
appendAuditMapValue(output, auditMap.get(key));
}
}
if (subActions.length() > 0)
{
sb.append("\n\t\t--- sub actions ---");
sb.append(subActions.toString());
}
if (devOutput)
{
logger.trace(sb.toString());
}
else
{
logger.debug(sb.toString());
}
}
return true;
}
return false;

View File

@@ -22,6 +22,7 @@ import static org.alfresco.repo.audit.model.AuditApplication.AUDIT_PATH_SEPARATO
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -89,7 +90,7 @@ import org.alfresco.service.namespace.QName;
private static final String PROPERTIES = "properties";
private static final String ASPECTS = "aspects";
private static final String VERSION_PROPERTIES = "version-properties";
private static final String SUB_ACTION = "sub-action";
public static final String SUB_ACTION = "sub-action";
private static final String DELETE_NODE = "deleteNode";
private static final String CREATE_NODE = "createNode";
@@ -110,6 +111,19 @@ import org.alfresco.service.namespace.QName;
private static final Pattern INVALID_PATH_COMP_CHAR_PATTERN =
Pattern.compile(AuditApplication.AUDIT_INVALID_PATH_COMP_CHAR_REGEX);
public static Collection<String> SUMMARY_KEYS = new ArrayList<String>();
static
{
SUMMARY_KEYS.add(buildPath(PROPERTIES, ADD));
SUMMARY_KEYS.add(buildPath(PROPERTIES, DELETE));
SUMMARY_KEYS.add(buildPath(PROPERTIES, FROM));
SUMMARY_KEYS.add(buildPath(PROPERTIES, TO));
SUMMARY_KEYS.add(buildPath(ASPECTS, ADD));
SUMMARY_KEYS.add(buildPath(ASPECTS, DELETE));
}
public static final String SUB_ACTION_PREFIX = SUB_ACTION + AUDIT_PATH_SEPARATOR;
private final NodeInfoFactory nodeInfoFactory;
private final NamespaceService namespaceService;
private NodeInfo nodeInfo;
@@ -749,7 +763,7 @@ import org.alfresco.service.namespace.QName;
* @param components String.. components of the path.
* @return a component path of the supplied values.
*/
private String buildPath(String... components)
private static String buildPath(String... components)
{
StringBuilder sb = new StringBuilder();
for (String component: components)

View File

@@ -18,8 +18,11 @@
*/
package org.alfresco.repo.security.permissions.impl.model;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
@@ -50,11 +53,15 @@ import org.alfresco.service.namespace.DynamicNamespacePrefixResolver;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.alfresco.util.TempFileProvider;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentType;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.tree.DefaultDocumentType;
import org.springframework.util.FileCopyUtils;
/**
* The implementation of the model DAO Reads and stores the top level model information Encapsulates access to this
@@ -93,6 +100,8 @@ public class PermissionModel implements ModelDAO
// Instance variables
private String model;
private String dtdSchema;
private boolean validate = true;
/*
* (non-Javadoc)
@@ -1142,6 +1151,26 @@ public class PermissionModel implements ModelDAO
this.model = model;
}
/**
* Set the dtd schema that is used to validate permission model
*
* @param dtdSchema
*/
public void setDtdSchema(String dtdSchema)
{
this.dtdSchema = dtdSchema;
}
/**
* Indicates whether model should be validated on initialization against specified dtd
*
* @param validate
*/
public void setValidate(boolean validate)
{
this.validate = validate;
}
/**
* Set the dictionary service
*
@@ -1261,6 +1290,7 @@ public class PermissionModel implements ModelDAO
private Document createDocument(String model)
{
InputStream is = this.getClass().getClassLoader().getResourceAsStream(model);
URL dtdSchemaUrl = this.getClass().getClassLoader().getResource(dtdSchema);
if (is == null)
{
throw new PermissionModelException("File not found: " + model);
@@ -1268,21 +1298,63 @@ public class PermissionModel implements ModelDAO
SAXReader reader = new SAXReader();
try
{
if (validate)
{
if (dtdSchemaUrl != null)
{
is = processModelDocType(is, dtdSchemaUrl.toString());
reader.setValidation(true);
}
else
{
throw new PermissionModelException("Couldn't obtain DTD schema to validate permission model.");
}
}
Document document = reader.read(is);
is.close();
return document;
}
catch (DocumentException e)
{
throw new PermissionModelException("Failed to create permission model document ", e);
throw new PermissionModelException("Failed to create permission model document: " + model, e);
}
catch (IOException e)
{
throw new PermissionModelException("Failed to close permission model document ", e);
throw new PermissionModelException("Failed to close permission model document: " + model, e);
}
}
/*
* Replace or add correct DOCTYPE to the xml to allow validation against dtd
*/
private InputStream processModelDocType(InputStream is, String dtdSchemaUrl) throws DocumentException, IOException
{
SAXReader reader = new SAXReader();
// read document without validation
Document doc = reader.read(is);
DocumentType docType = doc.getDocType();
if (docType != null)
{
// replace DOCTYPE setting the full path to the xsd
docType.setSystemID(dtdSchemaUrl);
}
else
{
// add the DOCTYPE
docType = new DefaultDocumentType(doc.getRootElement().getName(), dtdSchemaUrl);
doc.setDocType(docType);
}
File tempFile = TempFileProvider.createTempFile("permissionModel-", ".tmp");
// copy the modified permission model to the temp file
FileCopyUtils.copy(doc.asXML().getBytes(), tempFile);
return new FileInputStream(tempFile);
}
/**
* Set the default access status
*