Expose audit service as public service and in freemarker.

Tests


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3683 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Andrew Hind
2006-09-04 19:12:55 +00:00
parent 6777f68fa5
commit e244f2c93c
19 changed files with 753 additions and 53 deletions

View File

@@ -16,6 +16,9 @@
*/ */
package org.alfresco.repo.audit; package org.alfresco.repo.audit;
import java.util.List;
import org.alfresco.service.cmr.audit.AuditInfo;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
@@ -48,5 +51,13 @@ public interface AuditComponent
*/ */
public void audit(String source, String description, NodeRef key, Object... args); public void audit(String source, String description, NodeRef key, Object... args);
/**
* Get the audit trail for a node.
*
* @param nodeRef
* @return
*/
public List<AuditInfo> getAuditTrail(NodeRef nodeRef);
} }

View File

@@ -21,12 +21,15 @@ import java.lang.reflect.Method;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Date; import java.util.Date;
import java.util.List;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.service.Auditable; import org.alfresco.service.Auditable;
import org.alfresco.service.NotAuditable; import org.alfresco.service.NotAuditable;
import org.alfresco.service.cmr.audit.AuditInfo;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -241,8 +244,7 @@ public class AuditComponentImpl implements AuditComponent
* @param returnObject * @param returnObject
* @return * @return
*/ */
private AuditMode postInvocation(AuditMode auditMode, AuditState auditInfo, MethodInvocation mi, private AuditMode postInvocation(AuditMode auditMode, AuditState auditInfo, MethodInvocation mi, Object returnObject)
Object returnObject)
{ {
if (returnObject == null) if (returnObject == null)
{ {
@@ -260,12 +262,27 @@ public class AuditComponentImpl implements AuditComponent
Auditable auditable = mi.getMethod().getAnnotation(Auditable.class); Auditable auditable = mi.getMethod().getAnnotation(Auditable.class);
if (auditable.key() == Auditable.Key.RETURN) if (auditable.key() == Auditable.Key.RETURN)
{ {
if ((returnObject != null) && (returnObject instanceof NodeRef)) if (returnObject != null)
{
if (returnObject instanceof NodeRef)
{ {
NodeRef key = (NodeRef) returnObject; NodeRef key = (NodeRef) returnObject;
auditInfo.setKeyStore(key.getStoreRef()); auditInfo.setKeyStore(key.getStoreRef());
auditInfo.setKeyGUID(key.getId()); auditInfo.setKeyGUID(key.getId());
} }
else if (returnObject instanceof StoreRef)
{
auditInfo.setKeyStore((StoreRef)returnObject);
}
}
}
// If the user name is not set, try and set it after the method call.
// This covers authentication when the user is only known after the call.
if (auditInfo.getUserIdentifier() == null)
{
auditInfo.setUserIdentifier(AuthenticationUtil.getCurrentUserName());
} }
return auditMode; return auditMode;
@@ -334,11 +351,18 @@ public class AuditComponentImpl implements AuditComponent
default: default:
break; break;
} }
if ((key != null) && (key instanceof NodeRef)) if (key != null)
{
if (key instanceof NodeRef)
{ {
auditInfo.setKeyStore(((NodeRef) key).getStoreRef()); auditInfo.setKeyStore(((NodeRef) key).getStoreRef());
auditInfo.setKeyGUID(((NodeRef) key).getId()); auditInfo.setKeyGUID(((NodeRef) key).getId());
} }
else if (key instanceof StoreRef)
{
auditInfo.setKeyStore((StoreRef) key);
}
}
auditInfo.setKeyPropertiesAfter(null); auditInfo.setKeyPropertiesAfter(null);
auditInfo.setKeyPropertiesBefore(null); auditInfo.setKeyPropertiesBefore(null);
auditInfo.setMessage(null); auditInfo.setMessage(null);
@@ -346,6 +370,9 @@ public class AuditComponentImpl implements AuditComponent
{ {
Serializable[] serArgs = new Serializable[mi.getArguments().length]; Serializable[] serArgs = new Serializable[mi.getArguments().length];
for (int i = 0; i < mi.getArguments().length; i++) for (int i = 0; i < mi.getArguments().length; i++)
{
if ((auditable.recordable() == null)
|| (auditable.recordable().length <= i) || auditable.recordable()[i])
{ {
if (mi.getArguments()[i] == null) if (mi.getArguments()[i] == null)
{ {
@@ -360,6 +387,11 @@ public class AuditComponentImpl implements AuditComponent
serArgs[i] = mi.getArguments()[i].toString(); serArgs[i] = mi.getArguments()[i].toString();
} }
} }
else
{
serArgs[i] = "********";
}
}
auditInfo.setMethodArguments(serArgs); auditInfo.setMethodArguments(serArgs);
} }
auditInfo.setPath(null); auditInfo.setPath(null);
@@ -407,8 +439,13 @@ public class AuditComponentImpl implements AuditComponent
} }
} }
private AuditMode onApplicationAudit(AuditMode auditMode, AuditState auditInfo, String source, public List<AuditInfo> getAuditTrail(NodeRef nodeRef)
String description, NodeRef key, Object... args) {
return auditDAO.getAuditTrail(nodeRef);
}
private AuditMode onApplicationAudit(AuditMode auditMode, AuditState auditInfo, String source, String description,
NodeRef key, Object... args)
{ {
AuditMode effectiveAuditMode = auditModel.beforeExecution(auditMode, source, description, key, args); AuditMode effectiveAuditMode = auditModel.beforeExecution(auditMode, source, description, key, args);

View File

@@ -16,6 +16,11 @@
*/ */
package org.alfresco.repo.audit; package org.alfresco.repo.audit;
import java.util.List;
import org.alfresco.service.cmr.audit.AuditInfo;
import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* The interface to persist audit information. * The interface to persist audit information.
* *
@@ -29,4 +34,12 @@ public interface AuditDAO
* @param auditInfo * @param auditInfo
*/ */
public void audit(AuditState auditInfo); public void audit(AuditState auditInfo);
/**
* Get the audit trail for a node.
*
* @param nodeRef
* @return
*/
public List<AuditInfo> getAuditTrail(NodeRef nodeRef);
} }

View File

@@ -68,6 +68,11 @@ public class AuditServiceImpl implements AuditService
auditComponent.audit(source, description, key, args); auditComponent.audit(source, description, key, args);
} }
public List<AuditInfo> getAuditTrail(NodeRef nodeRef)
{
return auditComponent.getAuditTrail(nodeRef);
}
public static void main(String[] args) throws Exception public static void main(String[] args) throws Exception
{ {
@@ -82,17 +87,25 @@ public class AuditServiceImpl implements AuditService
try try
{ {
NodeRef nodeRef = new NodeRef(new StoreRef("test", "audit"), "id");
as.audit("AuditedApp", "First"); as.audit("AuditedApp", "First");
as.audit("AuditedApp", "Second", new NodeRef(new StoreRef("test", "audit"), "id")); System.out.println("Audit entries for node "+as.getAuditTrail(nodeRef).size());
as.audit("AuditedApp", "Second", nodeRef);
System.out.println("Audit entries for node "+as.getAuditTrail(nodeRef).size());
as.audit("AuditedApp", "Third", new Object[] { "one", "two", "three" }); as.audit("AuditedApp", "Third", new Object[] { "one", "two", "three" });
as.audit("AuditedApp", "Fourth", new NodeRef(new StoreRef("test", "audit"), "id"), new Object[] { "one", System.out.println("Audit entries for node "+as.getAuditTrail(nodeRef).size());
as.audit("AuditedApp", "Fourth",nodeRef, new Object[] { "one",
"two", "three" }); "two", "three" });
System.out.println("Audit entries for node "+as.getAuditTrail(nodeRef).size());
as.audit("UnAuditedApp", "First"); as.audit("UnAuditedApp", "First");
as.audit("UnAuditedApp", "Second", new NodeRef(new StoreRef("test", "audit"), "id")); System.out.println("Audit entries for node "+as.getAuditTrail(nodeRef).size());
as.audit("UnAuditedApp", "Second", nodeRef);
System.out.println("Audit entries for node "+as.getAuditTrail(nodeRef).size());
as.audit("UnAuditedApp", "Third", new Object[] { "one", "two", "three" }); as.audit("UnAuditedApp", "Third", new Object[] { "one", "two", "three" });
as.audit("UnAuditedApp", "Fourth", new NodeRef(new StoreRef("test", "audit"), "id"), new Object[] { "one", System.out.println("Audit entries for node "+as.getAuditTrail(nodeRef).size());
as.audit("UnAuditedApp", "Fourth", nodeRef, new Object[] { "one",
"two", "three" }); "two", "three" });
System.out.println("Audit entries for node "+as.getAuditTrail(nodeRef).size());
} }
finally finally
{ {
@@ -101,10 +114,4 @@ public class AuditServiceImpl implements AuditService
tx.commit(); tx.commit();
} }
public List<AuditInfo> getAuditTrail(NodeRef nodeRef)
{
// TODO Auto-generated method stub
return null;
}
} }

View File

@@ -0,0 +1,291 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.audit;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.audit.model.AuditEntry;
import org.alfresco.repo.audit.model.TrueFalseUnset;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.MutableAuthenticationDao;
import org.alfresco.repo.security.permissions.PermissionServiceSPI;
import org.alfresco.repo.security.permissions.impl.ModelDAO;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.audit.AuditInfo;
import org.alfresco.service.cmr.audit.AuditService;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.BaseSpringTest;
public class AuditServiceTest extends BaseSpringTest
{
private NodeService nodeService;
private DictionaryService dictionaryService;
private PermissionServiceSPI permissionService;
private NamespacePrefixResolver namespacePrefixResolver;
private AuthenticationService authenticationService;
private AuthenticationComponent authenticationComponent;
private ServiceRegistry serviceRegistry;
private ModelDAO permissionModelDAO;
private PersonService personService;
private AuthorityService authorityService;
private MutableAuthenticationDao authenticationDAO;
private NodeRef rootNodeRef;
private NodeRef systemNodeRef;
private AuditService auditService;
private AuditEntry auditEntry;
private NodeRef typesNodeRef;
private QName children;
private QName system;
private QName container;
private QName types;
public AuditServiceTest()
{
super();
}
protected void onSetUpInTransaction() throws Exception
{
nodeService = (NodeService) applicationContext.getBean("nodeService");
dictionaryService = (DictionaryService) applicationContext.getBean(ServiceRegistry.DICTIONARY_SERVICE
.getLocalName());
permissionService = (PermissionServiceSPI) applicationContext.getBean("permissionService");
namespacePrefixResolver = (NamespacePrefixResolver) applicationContext
.getBean(ServiceRegistry.NAMESPACE_SERVICE.getLocalName());
authenticationService = (AuthenticationService) applicationContext.getBean("authenticationService");
authenticationComponent = (AuthenticationComponent) applicationContext.getBean("authenticationComponent");
serviceRegistry = (ServiceRegistry) applicationContext.getBean(ServiceRegistry.SERVICE_REGISTRY);
permissionModelDAO = (ModelDAO) applicationContext.getBean("permissionsModelDAO");
personService = (PersonService) applicationContext.getBean("personService");
authorityService = (AuthorityService) applicationContext.getBean("authorityService");
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("alfDaoImpl");
auditService = (AuditService) applicationContext.getBean("AuditService");
auditEntry = (AuditEntry) applicationContext.getBean("auditModel");
StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.nanoTime());
rootNodeRef = nodeService.getRootNode(storeRef);
children = ContentModel.ASSOC_CHILDREN;
system = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "system");
container = ContentModel.TYPE_CONTAINER;
types = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "people");
systemNodeRef = nodeService.createNode(rootNodeRef, children, system, container).getChildRef();
typesNodeRef = nodeService.createNode(systemNodeRef, children, types, container).getChildRef();
Map<QName, Serializable> props = createPersonProperties("andy");
nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, props).getChildRef();
props = createPersonProperties("lemur");
nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, props).getChildRef();
// create an authentication object e.g. the user
if (authenticationDAO.userExists("andy"))
{
authenticationService.deleteAuthentication("andy");
}
authenticationService.createAuthentication("andy", "andy".toCharArray());
if (authenticationDAO.userExists("lemur"))
{
authenticationService.deleteAuthentication("lemur");
}
authenticationService.createAuthentication("lemur", "lemur".toCharArray());
if (authenticationDAO.userExists("admin"))
{
authenticationService.deleteAuthentication("admin");
}
authenticationService.createAuthentication("admin", "admin".toCharArray());
authenticationComponent.clearCurrentSecurityContext();
}
public void testApplicationAudit()
{
AuthenticationUtil.setSystemUserAsCurrentUser();
try
{
NodeRef nodeRef = new NodeRef(new StoreRef("test", "audit"), "id");
int start = auditService.getAuditTrail(nodeRef).size();
int increment = auditEntry.getEnabled() == TrueFalseUnset.TRUE ? 1 : 0;
auditService.audit("AuditedApp", "First");
assertEquals(start, auditService.getAuditTrail(nodeRef).size());
auditService.audit("AuditedApp", "Second", nodeRef);
assertEquals(start + (1 * increment), auditService.getAuditTrail(nodeRef).size());
auditService.audit("AuditedApp", "Third", new Object[] { "one", "two", "three" });
assertEquals(start + (1 * increment), auditService.getAuditTrail(nodeRef).size());
auditService.audit("AuditedApp", "Fourth", nodeRef, new Object[] { "one", "two", "three" });
assertEquals(start + (2 * increment), auditService.getAuditTrail(nodeRef).size());
auditService.audit("UnAuditedApp", "First");
assertEquals(start + (2 * increment), auditService.getAuditTrail(nodeRef).size());
auditService.audit("UnAuditedApp", "Second", nodeRef);
assertEquals(start + (3 * increment), auditService.getAuditTrail(nodeRef).size());
auditService.audit("UnAuditedApp", "Third", new Object[] { "one", "two", "three" });
assertEquals(start + (3 * increment), auditService.getAuditTrail(nodeRef).size());
auditService.audit("UnAuditedApp", "Fourth", nodeRef, new Object[] { "one", "two", "three" });
assertEquals(start + (4 * increment), auditService.getAuditTrail(nodeRef).size());
}
finally
{
AuthenticationUtil.clearCurrentSecurityContext();
}
}
public void testNodeServiceAudit()
{
AuthenticationUtil.setSystemUserAsCurrentUser();
try
{
int start = auditService.getAuditTrail(typesNodeRef).size();
int increment = auditEntry.getEnabled() == TrueFalseUnset.TRUE ? 1 : 0;
// Create
Map<QName, Serializable> props = createPersonProperties("woof");
NodeRef created = serviceRegistry.getNodeService().createNode(typesNodeRef, children,
ContentModel.TYPE_PERSON, container, props).getChildRef();
assertEquals(start + (1 * increment), auditService.getAuditTrail(typesNodeRef).size());
List<AuditInfo> list = auditService.getAuditTrail(typesNodeRef);
assertEquals(0, auditService.getAuditTrail(created).size());
// Update
serviceRegistry.getNodeService().setProperty(created, ContentModel.PROP_FIRSTNAME, "New First Name");
assertEquals((1 * increment), auditService.getAuditTrail(created).size());
// Update
serviceRegistry.getNodeService().setProperty(created, ContentModel.PROP_FIRSTNAME, "Next First Name");
assertEquals((2 * increment), auditService.getAuditTrail(created).size());
// Delete
serviceRegistry.getNodeService().deleteNode(created);
assertEquals((3 * increment), auditService.getAuditTrail(created).size());
list = auditService.getAuditTrail(created);
assertNotNull(list);
}
finally
{
AuthenticationUtil.clearCurrentSecurityContext();
}
}
public void xtestCreateStore()
{
AuthenticationUtil.setSystemUserAsCurrentUser();
try
{
serviceRegistry.getNodeService()
.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_Audit_" + System.nanoTime());
// Should have a query to support this - check direct in the DB
}
finally
{
AuthenticationUtil.clearCurrentSecurityContext();
}
setComplete();
}
public void xtestAuthenticartionDoesNotReportPasswords()
{
// Should have a query to support this - check direct in the DB
AuthenticationUtil.setSystemUserAsCurrentUser();
try
{
serviceRegistry.getAuthenticationService().createAuthentication("cabbage", "cabbage".toCharArray());
serviceRegistry.getAuthenticationService().updateAuthentication("cabbage", "cabbage".toCharArray(),
"red".toCharArray());
}
finally
{
AuthenticationUtil.clearCurrentSecurityContext();
}
try
{
serviceRegistry.getAuthenticationService().authenticate("cabbage", "red".toCharArray());
}
finally
{
serviceRegistry.getAuthenticationService().clearCurrentSecurityContext();
}
setComplete();
}
public void xtestAuthenticartionFailure()
{
// Should have a query to support this - check direct in the DB
AuthenticationUtil.setSystemUserAsCurrentUser();
serviceRegistry.getAuthenticationService().createAuthentication("woof", "cabbage".toCharArray());
serviceRegistry.getAuthenticationService().authenticate("woof", "red".toCharArray());
}
public void testThereIsAnAuditService()
{
assertNotNull(serviceRegistry.getAuditService());
}
private Map<QName, Serializable> createPersonProperties(String userName)
{
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
properties.put(ContentModel.PROP_USERNAME, userName);
return properties;
}
}

View File

@@ -155,4 +155,18 @@
audit_store.method = :method audit_store.method = :method
</query> </query>
<query name="audit.GetAuditTrailForNode">
select
audit_fact
from
org.alfresco.repo.audit.hibernate.AuditFactImpl as audit_fact
where
audit_fact.storeProtocol = :protocol and
audit_fact.storeId = :store_id and
audit_fact.nodeUUID = :node_id
order by
audit_fact.date asc
</query>
</hibernate-mapping> </hibernate-mapping>

View File

@@ -87,10 +87,10 @@ public class AuditConfigImpl implements AuditConfig, InitializingBean
/** /**
* Helper method to get the latest audit config * Helper method to get the latest audit config
*/ */
public static AuditConfigImpl getLatestConfig(Session session) public static AuditConfig getLatestConfig(Session session)
{ {
Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_LAST_AUDIT_CONFIG); Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_LAST_AUDIT_CONFIG);
return (AuditConfigImpl) query.uniqueResult(); return (AuditConfig) query.uniqueResult();
} }
@Override @Override

View File

@@ -280,10 +280,10 @@ public class AuditDateImpl implements AuditDate
/** /**
* Helper method to get the latest audit date * Helper method to get the latest audit date
*/ */
public static AuditDateImpl getLatestDate(Session session) public static AuditDate getLatestDate(Session session)
{ {
Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_LAST_AUDIT_DATE); Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_LAST_AUDIT_DATE);
return (AuditDateImpl) query.uniqueResult(); return (AuditDate) query.uniqueResult();
} }
} }

View File

@@ -17,6 +17,11 @@
package org.alfresco.repo.audit.hibernate; package org.alfresco.repo.audit.hibernate;
import java.util.Date; import java.util.Date;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
import org.hibernate.Query;
import org.hibernate.Session;
/** /**
* An Audit fact Rely on standard equals and hash code as they should all be unique. * An Audit fact Rely on standard equals and hash code as they should all be unique.
@@ -575,4 +580,16 @@ public class AuditFactImpl implements AuditFact
this.userId = userId; this.userId = userId;
} }
/**
* Helper method to get all the audit entries for a node.
*/
@SuppressWarnings("unchecked")
public static List<AuditFact> getAuditTrail(Session session, NodeRef nodeRef)
{
Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_AUDIT_TRAIL);
query.setParameter(HibernateAuditDAO.QUERY_AUDIT_PROTOCOL, nodeRef.getStoreRef().getProtocol());
query.setParameter(HibernateAuditDAO.QUERY_AUDIT_STORE_ID, nodeRef.getStoreRef().getIdentifier());
query.setParameter(HibernateAuditDAO.QUERY_AUDIT_NODE_ID, nodeRef.getId());
return (List<AuditFact>) query.list();
}
} }

View File

@@ -0,0 +1,224 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.audit.hibernate;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import org.alfresco.service.cmr.audit.AuditInfo;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName;
public class AuditInfoImpl implements AuditInfo
{
private String auditApplication;
private String auditMethod;
private String auditService;
private String clientAddress;
private Date date;
private boolean fail;
private boolean filtered;
private String hostAddress;
private String keyGUID;
private Map<QName, Serializable> keyPropertiesAfter;
private Map<QName, Serializable> keyPropertiesBefore;
private StoreRef keyStore;
private String message;
private Serializable[] methodArguments;
private String[] methodArgumentsAsStrings;
private String path;
private Serializable returnObject;
private String returnObjectAsString;
private String sessionId;
private Throwable throwable;
private String throwableAsString;
private String txId;
private String userIdentifier;
public AuditInfoImpl(AuditFact auditFact)
{
super();
this.auditApplication = auditFact.getAuditSource().getApplication();
this.auditMethod = auditFact.getAuditSource().getMethod();
this.auditService = auditFact.getAuditSource().getService();
this.clientAddress = auditFact.getClientInetAddress();
this.date = auditFact.getDate();
this.fail = auditFact.isFail();
this.filtered = auditFact.isFiltered();
this.hostAddress= auditFact.getHostInetAddress();
this.keyGUID = auditFact.getNodeUUID();
this.keyPropertiesAfter = null;
this.keyPropertiesBefore = null;
this.keyStore = new StoreRef(auditFact.getStoreProtocol(), auditFact.getStoreId());
this.message = auditFact.getMessage();
this.methodArguments = null;
this.methodArgumentsAsStrings = new String[5];
this.methodArgumentsAsStrings[0] = auditFact.getArg1();
this.methodArgumentsAsStrings[1] = auditFact.getArg2();
this.methodArgumentsAsStrings[2] = auditFact.getArg3();
this.methodArgumentsAsStrings[3] = auditFact.getArg4();
this.methodArgumentsAsStrings[4] = auditFact.getArg5();
this.path = auditFact.getPath();
this.returnObject = null;
this.returnObjectAsString = auditFact.getReturnValue();
this.sessionId = auditFact.getSessionId();
this.throwable = null;
this.throwableAsString = auditFact.getException();
this.txId = auditFact.getTransactionId();
this.userIdentifier = auditFact.getUserId();
}
public String getAuditApplication()
{
return auditApplication;
}
public String getAuditMethod()
{
return auditMethod;
}
public String getAuditService()
{
return auditService;
}
public String getClientAddress()
{
return clientAddress;
}
public Date getDate()
{
return date;
}
public boolean isFail()
{
return fail;
}
public boolean isFiltered()
{
return filtered;
}
public String getHostAddress()
{
return hostAddress;
}
public String getKeyGUID()
{
return keyGUID;
}
public Map<QName, Serializable> getKeyPropertiesAfter()
{
return keyPropertiesAfter;
}
public Map<QName, Serializable> getKeyPropertiesBefore()
{
return keyPropertiesBefore;
}
public StoreRef getKeyStore()
{
return keyStore;
}
public String getMessage()
{
return message;
}
public Serializable[] getMethodArguments()
{
return methodArguments;
}
public String[] getMethodArgumentsAsStrings()
{
return methodArgumentsAsStrings;
}
public String getPath()
{
return path;
}
public Serializable getReturnObject()
{
return returnObject;
}
public String getReturnObjectAsString()
{
return returnObjectAsString;
}
public String getSessionId()
{
return sessionId;
}
public Throwable getThrowable()
{
return throwable;
}
public String getThrowableAsString()
{
return throwableAsString;
}
public String getTxId()
{
return txId;
}
public String getUserIdentifier()
{
return userIdentifier;
}
}

View File

@@ -26,4 +26,10 @@ public interface AuditSource
public String getService(); public String getService();
void setApplication(String auditApplication);
void setService(String auditService);
void setMethod(String auditMethod);
} }

View File

@@ -87,21 +87,21 @@ public class AuditSourceImpl implements AuditSource
this.service = service; this.service = service;
} }
public static AuditSourceImpl getApplicationSource(Session session, String application) public static AuditSource getApplicationSource(Session session, String application)
{ {
Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE); Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE);
query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_APP, application); query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_APP, application);
return (AuditSourceImpl) query.uniqueResult(); return (AuditSource) query.uniqueResult();
} }
public static AuditSourceImpl getApplicationSource(Session session, String application, String service, public static AuditSource getApplicationSource(Session session, String application, String service,
String method) String method)
{ {
Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_AUDIT_METHOD_SOURCE); Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_AUDIT_METHOD_SOURCE);
query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_APP, application); query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_APP, application);
query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_SER, service); query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_SER, service);
query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_MET, method); query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_MET, method);
return (AuditSourceImpl) query.uniqueResult(); return (AuditSource) query.uniqueResult();
} }
@Override @Override

View File

@@ -20,21 +20,28 @@ import java.io.BufferedInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.audit.AuditConfiguration; import org.alfresco.repo.audit.AuditConfiguration;
import org.alfresco.repo.audit.AuditDAO; import org.alfresco.repo.audit.AuditDAO;
import org.alfresco.repo.audit.AuditException;
import org.alfresco.repo.audit.AuditState; import org.alfresco.repo.audit.AuditState;
import org.alfresco.repo.content.AbstractContentStore; import org.alfresco.repo.content.AbstractContentStore;
import org.alfresco.repo.content.ContentStore; import org.alfresco.repo.content.ContentStore;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.TransactionalDao; import org.alfresco.repo.transaction.TransactionalDao;
import org.alfresco.service.cmr.audit.AuditInfo;
import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.datatype.Duration; import org.alfresco.service.cmr.repository.datatype.Duration;
import org.alfresco.util.EqualsHelper; import org.alfresco.util.EqualsHelper;
import org.alfresco.util.GUID; import org.alfresco.util.GUID;
@@ -63,6 +70,14 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
public static final String QUERY_AUDIT_APP_SOURCE_MET = "method"; public static final String QUERY_AUDIT_APP_SOURCE_MET = "method";
public static final String QUERY_AUDIT_TRAIL = "audit.GetAuditTrailForNode";
public static final String QUERY_AUDIT_PROTOCOL = "protocol";
public static final String QUERY_AUDIT_STORE_ID = "store_id";
public static final String QUERY_AUDIT_NODE_ID = "node_id";
/** a uuid identifying this unique instance */ /** a uuid identifying this unique instance */
private String uuid; private String uuid;
@@ -93,15 +108,35 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
} }
public void audit(AuditState auditInfo) public void audit(AuditState auditInfo)
{
if(AuthenticationUtil.getCurrentUserName() == null)
{
AuthenticationUtil.setSystemUserAsCurrentUser();
try
{
audit0(auditInfo);
}
finally
{
AuthenticationUtil.clearCurrentSecurityContext();
}
}
else
{
audit0(auditInfo);
}
}
private void audit0(AuditState auditInfo)
{ {
// Find/Build the configuraton entry // Find/Build the configuraton entry
AuditConfigImpl auditConfig = getAuditConfig(auditInfo); AuditConfig auditConfig = getAuditConfig(auditInfo);
// Find/Build any dates // Find/Build any dates
AuditDateImpl auditDate = getAuditDate(auditInfo); AuditDate auditDate = getAuditDate(auditInfo);
// Find/Build the source // Find/Build the source
AuditSourceImpl auditSource = getAuditSource(auditInfo); AuditSource auditSource = getAuditSource(auditInfo);
// Build the new audit fact information // Build the new audit fact information
AuditFactImpl auditFact = new AuditFactImpl(); AuditFactImpl auditFact = new AuditFactImpl();
@@ -170,9 +205,9 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
} }
} }
private AuditSourceImpl getAuditSource(AuditState auditInfo) private AuditSource getAuditSource(AuditState auditInfo)
{ {
AuditSourceImpl auditSourceImpl; AuditSource auditSourceImpl;
SourceKey sourceKey = new SourceKey(auditInfo.getAuditApplication(), auditInfo.getAuditService(), auditInfo.getAuditMethod()); SourceKey sourceKey = new SourceKey(auditInfo.getAuditApplication(), auditInfo.getAuditService(), auditInfo.getAuditMethod());
if(sourceIds.get() == null) if(sourceIds.get() == null)
@@ -182,7 +217,7 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
Long id = sourceIds.get().get(sourceKey); Long id = sourceIds.get().get(sourceKey);
if(id != null) if(id != null)
{ {
auditSourceImpl = (AuditSourceImpl) getSession().get(AuditSourceImpl.class, id.longValue()); auditSourceImpl = (AuditSource) getSession().get(AuditSourceImpl.class, id.longValue());
if(auditSourceImpl != null) if(auditSourceImpl != null)
{ {
return auditSourceImpl; return auditSourceImpl;
@@ -218,7 +253,7 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
return auditSourceImpl; return auditSourceImpl;
} }
private AuditDateImpl getAuditDate(AuditState auditInfo) private AuditDate getAuditDate(AuditState auditInfo)
{ {
Calendar cal = GregorianCalendar.getInstance(); Calendar cal = GregorianCalendar.getInstance();
cal.setTime(auditInfo.getDate()); cal.setTime(auditInfo.getDate());
@@ -228,7 +263,7 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.HOUR_OF_DAY, 0);
Date required = cal.getTime(); Date required = cal.getTime();
AuditDateImpl auditDate; AuditDate auditDate;
if (auditDateImplId.get() == null) if (auditDateImplId.get() == null)
{ {
auditDate = AuditDateImpl.getLatestDate(getSession()); auditDate = AuditDateImpl.getLatestDate(getSession());
@@ -242,7 +277,7 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
} }
else else
{ {
auditDate = (AuditDateImpl) getSession().get(AuditDateImpl.class, auditDateImplId.get().longValue()); auditDate = (AuditDate) getSession().get(AuditDateImpl.class, auditDateImplId.get().longValue());
if ((auditDate == null) || (!required.equals(auditDate.getDate()))) if ((auditDate == null) || (!required.equals(auditDate.getDate())))
{ {
auditDate = AuditDateImpl.getLatestDate(getSession()); auditDate = AuditDateImpl.getLatestDate(getSession());
@@ -265,9 +300,9 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
return auditDate; return auditDate;
} }
private AuditConfigImpl getAuditConfig(AuditState auditInfo) private AuditConfig getAuditConfig(AuditState auditInfo)
{ {
AuditConfigImpl auditConfig; AuditConfig auditConfig;
if ((auditConfiguration.get() == null) || (auditConfiguration.get() != auditInfo.getAuditConfiguration())) if ((auditConfiguration.get() == null) || (auditConfiguration.get() != auditInfo.getAuditConfiguration()))
{ {
auditConfig = AuditConfigImpl.getLatestConfig(getSession()); auditConfig = AuditConfigImpl.getLatestConfig(getSession());
@@ -313,7 +348,7 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
} }
else else
{ {
auditConfig = (AuditConfigImpl) getSession() auditConfig = (AuditConfig) getSession()
.get(AuditConfigImpl.class, auditConfigImplId.get().longValue()); .get(AuditConfigImpl.class, auditConfigImplId.get().longValue());
if (auditConfig == null) if (auditConfig == null)
{ {
@@ -436,4 +471,23 @@ public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO,
return hash; return hash;
} }
} }
public List<AuditInfo> getAuditTrail(NodeRef nodeRef)
{
if(nodeRef == null)
{
return Collections.<AuditInfo>emptyList();
}
List<? extends AuditFact> internalTrail = AuditFactImpl.getAuditTrail(getSession(), nodeRef);
ArrayList<AuditInfo> answer = new ArrayList<AuditInfo>(internalTrail.size());
for(AuditFact auditFact : internalTrail)
{
AuditInfo info = new AuditInfoImpl(auditFact);
answer.add(info);
}
return answer;
}
} }

View File

@@ -117,7 +117,7 @@ public abstract class AbstractAuditEntry
return auditMode; return auditMode;
} }
/* package */TrueFalseUnset getEnabled() public TrueFalseUnset getEnabled()
{ {
return enabled; return enabled;
} }

View File

@@ -25,6 +25,7 @@ import java.util.Map;
import org.alfresco.service.ServiceDescriptor; import org.alfresco.service.ServiceDescriptor;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.audit.AuditService;
import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.lock.LockService; import org.alfresco.service.cmr.lock.LockService;
@@ -322,4 +323,12 @@ public class ServiceDescriptorRegistry
{ {
return (WorkflowService)getService(WORKFLOW_SERVICE); return (WorkflowService)getService(WORKFLOW_SERVICE);
} }
/* (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getWorkflowService()
*/
public AuditService getAuditService()
{
return (AuditService)getService(AUDIT_SERVICE);
}
} }

View File

@@ -19,6 +19,7 @@ package org.alfresco.service;
import java.util.Collection; import java.util.Collection;
import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.audit.AuditService;
import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.lock.LockService; import org.alfresco.service.cmr.lock.LockService;
@@ -84,6 +85,7 @@ public interface ServiceRegistry
static final QName FILE_FOLDER_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "FileFolderService"); static final QName FILE_FOLDER_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "FileFolderService");
static final QName SCRIPT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ScriptService"); static final QName SCRIPT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ScriptService");
static final QName WORKFLOW_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "WorkflowService"); static final QName WORKFLOW_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "WorkflowService");
static final QName AUDIT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AuditService");
/** /**
* Get the list of services provided by the Repository * Get the list of services provided by the Repository
@@ -263,4 +265,10 @@ public interface ServiceRegistry
*/ */
@NotAuditable @NotAuditable
WorkflowService getWorkflowService(); WorkflowService getWorkflowService();
/**
* @return the audit service (or null if one is not provided)
*/
@NotAuditable
AuditService getAuditService();
} }

View File

@@ -57,7 +57,7 @@ public interface AuditInfo
* *
* @return - the client address - may be null. * @return - the client address - may be null.
*/ */
public InetAddress getClientAddress(); public String getClientAddress();
/** /**
* The timestamp for the audit entry. * The timestamp for the audit entry.
@@ -85,7 +85,7 @@ public interface AuditInfo
* *
* @return * @return
*/ */
public InetAddress getHostAddress(); public String getHostAddress();
/** /**
* Get the ID of the key node. * Get the ID of the key node.

View File

@@ -54,7 +54,7 @@ public interface NodeService
* @return Returns a reference to the store * @return Returns a reference to the store
* @throws StoreExistsException * @throws StoreExistsException
*/ */
@Auditable(parameters = {"protocol", "identifier"}) @Auditable(key = Auditable.Key.RETURN, parameters = {"protocol", "identifier"})
public StoreRef createStore(String protocol, String identifier) throws StoreExistsException; public StoreRef createStore(String protocol, String identifier) throws StoreExistsException;
/** /**

View File

@@ -34,6 +34,7 @@ import org.alfresco.repo.template.NodeSearchResultsMap;
import org.alfresco.repo.template.SavedSearchResultsMap; import org.alfresco.repo.template.SavedSearchResultsMap;
import org.alfresco.repo.template.XPathResultsMap; import org.alfresco.repo.template.XPathResultsMap;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.audit.AuditInfo;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.lock.LockStatus; import org.alfresco.service.cmr.lock.LockStatus;
import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.AccessPermission;
@@ -660,6 +661,14 @@ public final class TemplateNode implements Serializable
} }
// Audit API
public List<AuditInfo> getAuditTrail()
{
return this.services.getAuditService().getAuditTrail(this.nodeRef);
}
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
// Misc helpers // Misc helpers