diff --git a/config/alfresco/audit-services-context.xml b/config/alfresco/audit-services-context.xml
index 6e9618fdc3..7d5bbdc953 100644
--- a/config/alfresco/audit-services-context.xml
+++ b/config/alfresco/audit-services-context.xml
@@ -30,6 +30,7 @@
+
@@ -37,6 +38,14 @@
+
+
+
+
+ ${audit.filter.alfresco-access.transaction.user}
+
+
+
diff --git a/source/java/org/alfresco/repo/audit/AuditComponent.java b/source/java/org/alfresco/repo/audit/AuditComponent.java
index cee7afd3ef..ea9966c9c5 100644
--- a/source/java/org/alfresco/repo/audit/AuditComponent.java
+++ b/source/java/org/alfresco/repo/audit/AuditComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2010 Alfresco Software Limited.
+ * Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -53,6 +53,13 @@ public interface AuditComponent
*/
public void setAuditEnabled(boolean enable);
+ /**
+ * @param userAuditFilter
+ *
+ * @since 4.2
+ */
+ public void setUserAuditFilter(UserAuditFilter userAuditFilter);
+
/**
* Get all registered audit applications, whether active or not.
*
diff --git a/source/java/org/alfresco/repo/audit/AuditComponentImpl.java b/source/java/org/alfresco/repo/audit/AuditComponentImpl.java
index 23aa538ecb..57404fd1f5 100644
--- a/source/java/org/alfresco/repo/audit/AuditComponentImpl.java
+++ b/source/java/org/alfresco/repo/audit/AuditComponentImpl.java
@@ -75,6 +75,7 @@ public class AuditComponentImpl implements AuditComponent
private AuditDAO auditDAO;
private TransactionService transactionService;
private AuditFilter auditFilter;
+ private UserAuditFilter userAuditFilter;
/**
* Default constructor
@@ -126,6 +127,11 @@ public class AuditComponentImpl implements AuditComponent
this.auditFilter = auditFilter;
}
+ public void setUserAuditFilter(UserAuditFilter userAuditFilter)
+ {
+ this.userAuditFilter = userAuditFilter;
+ }
+
/**
* {@inheritDoc}
* @since 3.2
@@ -499,7 +505,8 @@ public class AuditComponentImpl implements AuditComponent
ParameterCheck.mandatory("rootPath", rootPath);
AuditApplication.checkPathFormat(rootPath);
- if (values == null || values.isEmpty() || !areAuditValuesRequired() || !auditFilter.accept(rootPath, values))
+ String username = AuthenticationUtil.getFullyAuthenticatedUser();
+ if (values == null || values.isEmpty() || !areAuditValuesRequired() || !userAuditFilter.acceptUser(username) || !auditFilter.accept(rootPath, values))
{
return Collections.emptyMap();
}
diff --git a/source/java/org/alfresco/repo/audit/UserAuditFilter.java b/source/java/org/alfresco/repo/audit/UserAuditFilter.java
new file mode 100644
index 0000000000..a88b0aacee
--- /dev/null
+++ b/source/java/org/alfresco/repo/audit/UserAuditFilter.java
@@ -0,0 +1,109 @@
+/*
+ * 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.audit;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.util.Pair;
+import org.alfresco.util.PropertyCheck;
+import org.springframework.beans.factory.InitializingBean;
+
+public class UserAuditFilter implements InitializingBean
+{
+ private static final char NOT = '~';
+ private static final String REG_EXP_SEPARATOR = ";";
+ private static final char ESCAPE = '\\';
+ private static final String ESCAPED_NOT = ""+ESCAPE+NOT;
+
+ private String userFilterPattern;
+ private List> listOfPairValue = new ArrayList>();
+
+ /**
+ * Default constructor
+ */
+ public UserAuditFilter()
+ {
+ }
+
+ /*
+ * Set user audit pattern. For example "audit.filter.alfresco-access.transaction.user=~user1;user2;.*"
+ *
+ * @param userFilterPattern 'userFilterPattern' is String type. The value of 'userFilterPattern' couldn't empty
+ * or have 0 length value. An expression that starts with a '~' indicates that any
+ * matching value should be rejected. Each regular expression in the list is separated
+ * by a semicolon (';').
+ */
+ public void setUserFilterPattern(String userFilterPattern)
+ {
+ this.userFilterPattern = userFilterPattern;
+ }
+
+ public void afterPropertiesSet()
+ {
+ parseProperties();
+ }
+
+ private void parseProperties()
+ {
+ String userPropertyValue = userFilterPattern;
+ if (!PropertyCheck.isValidPropertyString(userPropertyValue))
+ {
+ return;
+ }
+
+ String[] arrValues = userPropertyValue.split(REG_EXP_SEPARATOR);
+ for (String prop : arrValues)
+ {
+ boolean includeExp = prop.charAt(0) != NOT;
+
+ if (!includeExp || prop.startsWith(ESCAPED_NOT))
+ {
+ prop = prop.substring(1);
+ }
+ try
+ {
+ listOfPairValue.add(new Pair(includeExp, Pattern.compile(prop)));
+ }
+ catch (PatternSyntaxException ex)
+ {
+ throw new AlfrescoRuntimeException("The 'audit.filter.alfresco-access.transaction.user' property parse exception; see property 'audit.filter.alfresco-access.transaction.user'.", ex);
+ }
+ }
+ }
+
+ public boolean acceptUser(String value)
+ {
+ if (value == null)
+ {
+ value = "null";
+ }
+ for (Pair val : listOfPairValue)
+ {
+ if (val.getSecond().matcher(value).matches())
+ {
+ return val.getFirst();
+ }
+ }
+ return true;
+ }
+}
diff --git a/source/test-java/org/alfresco/repo/audit/AuditComponentTest.java b/source/test-java/org/alfresco/repo/audit/AuditComponentTest.java
index df770ce81a..bbf99f2ca0 100644
--- a/source/test-java/org/alfresco/repo/audit/AuditComponentTest.java
+++ b/source/test-java/org/alfresco/repo/audit/AuditComponentTest.java
@@ -932,8 +932,6 @@ public class AuditComponentTest extends TestCase
AuthenticationUtil.runAs(testRunAs, "SomeOtherUser");
}
-
-
/**
* Clearn the audit log as 'admin'
*/
diff --git a/source/test-java/org/alfresco/repo/audit/AuditTestSuite.java b/source/test-java/org/alfresco/repo/audit/AuditTestSuite.java
index 8b7383e4e5..06f0285185 100644
--- a/source/test-java/org/alfresco/repo/audit/AuditTestSuite.java
+++ b/source/test-java/org/alfresco/repo/audit/AuditTestSuite.java
@@ -40,6 +40,7 @@ public class AuditTestSuite extends TestSuite
suite.addTestSuite(AuditableAspectTest.class);
suite.addTestSuite(AuditBootstrapTest.class);
suite.addTestSuite(AuditComponentTest.class);
+ suite.addTestSuite(UserAuditFilterTest.class);
suite.addTest(new JUnit4TestAdapter(PropertyAuditFilterTest.class));
suite.addTest(new JUnit4TestAdapter(AccessAuditorTest.class));
diff --git a/source/test-java/org/alfresco/repo/audit/UserAuditFilterTest.java b/source/test-java/org/alfresco/repo/audit/UserAuditFilterTest.java
new file mode 100644
index 0000000000..8cd3660d4d
--- /dev/null
+++ b/source/test-java/org/alfresco/repo/audit/UserAuditFilterTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.audit;
+
+import java.io.Serializable;
+import java.net.URL;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.repo.audit.model.AuditModelRegistryImpl;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.transaction.TransactionService;
+import org.alfresco.util.ApplicationContextHelper;
+import org.springframework.context.ApplicationContext;
+import org.springframework.util.ResourceUtils;
+
+/**
+ * Tests user filter.
+ *
+ * @see UserAuditFilter
+ *
+ * @author Vasily Olhin
+ * @since 4.2
+ */
+public class UserAuditFilterTest extends TestCase
+{
+ private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
+
+ private AuditModelRegistryImpl auditModelRegistry;
+ private AuditComponent auditComponent;
+ private ServiceRegistry serviceRegistry;
+ private TransactionService transactionService;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ auditModelRegistry = (AuditModelRegistryImpl) ctx.getBean("auditModel.modelRegistry");
+ auditComponent = (AuditComponent) ctx.getBean("auditComponent");
+ serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
+ transactionService = serviceRegistry.getTransactionService();
+
+ // Register the test model
+ URL testModelUrl = ResourceUtils.getURL("classpath:alfresco/testaudit/alfresco-audit-test.xml");
+ auditModelRegistry.registerModel(testModelUrl);
+ auditModelRegistry.loadAuditModels();
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ AuthenticationUtil.clearCurrentSecurityContext();
+ // Throw away the reconfigured registry state
+ auditModelRegistry.destroy();
+ }
+
+ public void testUserFilter()
+ {
+ Map userArr = new HashMap();
+ userArr.put(false, "user1");
+ userArr.put(true, "user2");
+ userArr.put(true, "bob");
+ UserAuditFilter userAuditFilter = new UserAuditFilter();
+ userAuditFilter.setUserFilterPattern("~user1;user2;.*");
+ userAuditFilter.afterPropertiesSet();
+ auditComponent.setUserAuditFilter(userAuditFilter);
+
+ final RetryingTransactionCallback