mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Added AuditService.clearAudit(List<Long>)
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22980 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -135,14 +135,20 @@
|
||||
delete
|
||||
from
|
||||
alf_audit_entry
|
||||
where
|
||||
<dynamic prepend="where">
|
||||
<isNotNull property="auditFromTime" prepend="and">
|
||||
audit_app_id = #auditApplicationId#
|
||||
<isNotNull property="auditFromTime">
|
||||
<![CDATA[and audit_time >= #auditFromTime#]]>
|
||||
</isNotNull>
|
||||
<isNotNull property="auditFromTime">
|
||||
<![CDATA[and audit_time < #auditToTime#]]>
|
||||
<isNotNull property="auditFromTime" prepend="and">
|
||||
<![CDATA[audit_time >= #auditFromTime#]]>
|
||||
</isNotNull>
|
||||
<isNotNull property="auditFromTime" prepend="and">
|
||||
<![CDATA[audit_time < #auditToTime#]]>
|
||||
</isNotNull>
|
||||
<isNotNull property="auditEntryIds" prepend="and">
|
||||
id in <iterate property="auditEntryIds" open="(" close=")" conjunction=", ">#auditEntryIds[]#</iterate>
|
||||
</isNotNull>
|
||||
</dynamic>
|
||||
</delete>
|
||||
|
||||
<sql id="select_AuditEntriesWhereSnippet">
|
||||
|
@@ -19,6 +19,7 @@
|
||||
package org.alfresco.repo.audit;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.audit.model.AuditApplication;
|
||||
@@ -89,6 +90,14 @@ public interface AuditComponent
|
||||
*/
|
||||
int deleteAuditEntries(String applicationName, Long fromTime, Long toTime);
|
||||
|
||||
/**
|
||||
* Delete a discrete list of audit entries based on ID
|
||||
*
|
||||
* @param auditEntryIds the audit entry IDs to delete
|
||||
* @return Returns the number of entries deleted
|
||||
*/
|
||||
int deleteAuditEntries(List<Long> auditEntryIds);
|
||||
|
||||
/**
|
||||
* Check if an audit path is enabled. The path will be disabled if it or any higher
|
||||
* path has been explicitly disabled. Any disabled path will not be processed when
|
||||
|
@@ -146,6 +146,21 @@ public class AuditComponentImpl implements AuditComponent
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 3.2
|
||||
*/
|
||||
@Override
|
||||
public int deleteAuditEntries(List<Long> auditEntryIds)
|
||||
{
|
||||
// Shortcut, if necessary
|
||||
if (auditEntryIds.size() == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return auditDAO.deleteAuditEntries(auditEntryIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param application the audit application object
|
||||
* @return Returns a copy of the set of disabled paths associated with the application
|
||||
|
@@ -523,7 +523,7 @@ public class AuditComponentTest extends TestCase
|
||||
auditModelRegistry.registerModel(testModelUrl);
|
||||
auditModelRegistry.loadAuditModels();
|
||||
|
||||
final List<Map<String, Serializable>> results = new ArrayList<Map<String,Serializable>>();
|
||||
final List<Long> results = new ArrayList<Long>(5);
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
AuditQueryCallback auditQueryCallback = new AuditQueryCallback()
|
||||
{
|
||||
@@ -539,7 +539,7 @@ public class AuditComponentTest extends TestCase
|
||||
long time,
|
||||
Map<String, Serializable> values)
|
||||
{
|
||||
results.add(values);
|
||||
results.add(entryId);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(
|
||||
@@ -615,11 +615,28 @@ public class AuditComponentTest extends TestCase
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
try
|
||||
{
|
||||
authenticationService.authenticate("banana", "****".toCharArray());
|
||||
fail("Invalid authentication attempt should fail");
|
||||
}
|
||||
catch (AuthenticationException e)
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
results.clear();
|
||||
sb.delete(0, sb.length());
|
||||
queryAuditLog(auditQueryCallback, params, -1);
|
||||
logger.debug(sb.toString());
|
||||
assertFalse("Did not get any audit results after failed login", results.isEmpty());
|
||||
assertEquals("Incorrect number of audit entries after failed login", 2, results.size());
|
||||
|
||||
// Check that we can delete explicit entries
|
||||
deleteAuditEntries(results);
|
||||
results.clear();
|
||||
sb.delete(0, sb.length());
|
||||
queryAuditLog(auditQueryCallback, params, -1);
|
||||
logger.debug(sb.toString());
|
||||
assertEquals("Explicit audit entries were not deleted", 0, results.size());
|
||||
}
|
||||
|
||||
public void testAuditQuery_MaxId() throws Exception
|
||||
@@ -677,6 +694,23 @@ public class AuditComponentTest extends TestCase
|
||||
AuthenticationUtil.runAs(work, AuthenticationUtil.getAdminRoleName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clearn the audit log as 'admin'
|
||||
*/
|
||||
private void deleteAuditEntries(final List<Long> auditEntryIds)
|
||||
{
|
||||
RunAsWork<Void> work = new RunAsWork<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork() throws Exception
|
||||
{
|
||||
auditService.clearAudit(auditEntryIds);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
AuthenticationUtil.runAs(work, AuthenticationUtil.getAdminRoleName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clearn the audit log as 'admin'
|
||||
*/
|
||||
|
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
package org.alfresco.repo.audit;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
@@ -133,6 +133,16 @@ public class AuditServiceImpl implements AuditService
|
||||
return auditComponent.deleteAuditEntries(applicationName, fromTime, toTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 3.4
|
||||
*/
|
||||
@Override
|
||||
public int clearAudit(List<Long> auditEntryIds)
|
||||
{
|
||||
return auditComponent.deleteAuditEntries(auditEntryIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 3.3
|
||||
|
@@ -22,11 +22,13 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
@@ -41,6 +43,7 @@ import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
|
||||
/**
|
||||
@@ -306,7 +309,39 @@ public abstract class AbstractAuditDAOImpl implements AuditDAO
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
public int deleteAuditEntries(List<Long> auditEntryIds)
|
||||
{
|
||||
// Ensure that we don't have duplicates
|
||||
Set<Long> ids = new TreeSet<Long>(auditEntryIds);
|
||||
int shouldDelete = ids.size();
|
||||
|
||||
int deleted = 0;
|
||||
List<Long> batch = new ArrayList<Long>(shouldDelete > 512 ? 512 : shouldDelete);
|
||||
for (Long id : ids)
|
||||
{
|
||||
batch.add(id);
|
||||
if (batch.size() >= 512)
|
||||
{
|
||||
deleted += deleteAuditEntriesImpl(batch);
|
||||
batch.clear();
|
||||
}
|
||||
}
|
||||
// Process remaining
|
||||
if (batch.size() > 0)
|
||||
{
|
||||
deleted += deleteAuditEntriesImpl(batch);
|
||||
}
|
||||
// Check concurrency
|
||||
if (deleted != shouldDelete)
|
||||
{
|
||||
throw new ConcurrencyFailureException(
|
||||
"Deleted " + deleted + " audit entries out of a set of " + shouldDelete + " unique IDs.");
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
protected abstract AuditEntryEntity createAuditEntry(Long applicationId, long time, Long usernameId, Long valuesId);
|
||||
protected abstract int deleteAuditEntriesImpl(List<Long> auditEntryIds);
|
||||
|
||||
/*
|
||||
* Searches
|
||||
|
@@ -20,6 +20,7 @@ package org.alfresco.repo.domain.audit;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -166,6 +167,17 @@ public interface AuditDAO
|
||||
*/
|
||||
int deleteAuditEntries(Long applicationId, Long from, Long to);
|
||||
|
||||
/**
|
||||
* Delete a discrete list of audit entries. Duplicate entries are collapsed
|
||||
* and the number of entries deleted will match the count of unique IDs in
|
||||
* the list; otherwise a concurrency condition has occured and an exception
|
||||
* will be generated.
|
||||
*
|
||||
* @param auditEntryIds the IDs of all audit entries to delete
|
||||
* @return Returns the number of entries deleted
|
||||
*/
|
||||
int deleteAuditEntries(List<Long> auditEntryIds);
|
||||
|
||||
/**
|
||||
* Create a new audit entry with the given map of values.
|
||||
*
|
||||
|
@@ -19,6 +19,7 @@
|
||||
package org.alfresco.repo.domain.audit;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Deletion parameters for <b>alf_audit_entry</b> table.
|
||||
@@ -31,6 +32,7 @@ public class AuditDeleteParameters
|
||||
private Long auditApplicationId;
|
||||
private Long auditFromTime;
|
||||
private Long auditToTime;
|
||||
private List<Long> auditEntryIds;
|
||||
|
||||
public AuditDeleteParameters()
|
||||
{
|
||||
@@ -44,6 +46,7 @@ public class AuditDeleteParameters
|
||||
.append("[ auditApplicationId=").append(auditApplicationId)
|
||||
.append(", auditFromTime").append(auditFromTime == null ? null : new Date(auditFromTime))
|
||||
.append(", auditToTime").append(auditToTime == null ? null : new Date(auditToTime))
|
||||
.append(", auditEntryIds").append(auditEntryIds == null ? null : auditEntryIds.size())
|
||||
.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -77,4 +80,14 @@ public class AuditDeleteParameters
|
||||
{
|
||||
this.auditToTime = auditToTime;
|
||||
}
|
||||
|
||||
public List<Long> getAuditEntryIds()
|
||||
{
|
||||
return auditEntryIds;
|
||||
}
|
||||
|
||||
public void setAuditEntryIds(List<Long> auditEntryIds)
|
||||
{
|
||||
this.auditEntryIds = auditEntryIds;
|
||||
}
|
||||
}
|
||||
|
@@ -170,6 +170,14 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
|
||||
return template.delete(DELETE_ENTRIES, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int deleteAuditEntriesImpl(List<Long> auditEntryIds)
|
||||
{
|
||||
AuditDeleteParameters params = new AuditDeleteParameters();
|
||||
params.setAuditEntryIds(auditEntryIds);
|
||||
return template.delete(DELETE_ENTRIES, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuditEntryEntity createAuditEntry(Long applicationId, long time, Long usernameId, Long valuesId)
|
||||
{
|
||||
|
@@ -19,6 +19,7 @@
|
||||
package org.alfresco.service.cmr.audit;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.PublicService;
|
||||
@@ -145,6 +146,19 @@ public interface AuditService
|
||||
*/
|
||||
int clearAudit(String applicationName, Long fromTime, Long toTime);
|
||||
|
||||
/**
|
||||
* Delete a discrete list of audit entries.
|
||||
* <p/>
|
||||
* This method should not be called <i>while</i> processing
|
||||
* {@link #auditQuery(AuditQueryCallback, AuditQueryParameters, int) query results}.
|
||||
*
|
||||
* @param auditEntryIds the IDs of all audit entries to delete
|
||||
* @return Returns the number of audit entries deleted
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
int clearAudit(List<Long> auditEntryIds);
|
||||
|
||||
/**
|
||||
* The interface that will be used to give query results to the calling code.
|
||||
*
|
||||
|
Reference in New Issue
Block a user