diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/audit/clear.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/audit/clear.post.desc.xml
new file mode 100644
index 0000000000..e6e9c1de37
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/audit/clear.post.desc.xml
@@ -0,0 +1,27 @@
+
+ Alfresco Audit Service Clear
+ Delete audit entries for a given application and time range
+ /api/audit/clear/{application}?fromTime={fromTime}&toTime={toTime}
+
+ admin
+ required
+ internal
+
+
+ application
+ Name of the audit application (mandatory)
+
+
+ fromTime
+ Time, in milliseconds, of the oldest audit entry to delete (omit to assume oldest)
+
+
+ toTime
+ Time, in milleseconds, of the youngest audit entry to delete (omit to assume current time)
+
+
+
+
+
+
+
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/audit/clear.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/audit/clear.post.json.ftl
new file mode 100644
index 0000000000..7c5ee644c4
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/audit/clear.post.json.ftl
@@ -0,0 +1,3 @@
+{
+ "cleared" : ${cleared}
+}
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/audit/control.properties b/config/alfresco/templates/webscripts/org/alfresco/repository/audit/control.properties
index 2d6356d41b..d81c76d834 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/audit/control.properties
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/audit/control.properties
@@ -1,4 +1,5 @@
# Audit Control Web Script I18N
+audit.err.app.notProvided=Application name not supplied.
audit.err.app.notFound=Application not found: {0}
audit.err.path.notProvided=No path was supplied after the application name.
audit.err.action.invalid=Parameter 'action' must be either 'enable' or 'disable'
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/audit/query.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/audit/query.get.desc.xml
new file mode 100644
index 0000000000..7955d406b7
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/audit/query.get.desc.xml
@@ -0,0 +1,27 @@
+
+ Alfresco Audit Service Query
+ Get audit events
+ /api/audit/query/{application}?{k1}={v1},{k2}={v2}
+
+ admin
+ required
+ internal
+
+
+ application
+ Name of the audit application (mandatory parameter)
+
+
+ k1
+ First key to query for. If no value is provided, then the present of the key is enough.
+
+
+ v1
+ First value to query for. If this is no provided, then the presence of the key is enough.
+
+
+
+
+
+
+
diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml
index 0fd4c5e568..b98321d7dd 100644
--- a/config/alfresco/web-scripts-application-context.xml
+++ b/config/alfresco/web-scripts-application-context.xml
@@ -28,6 +28,13 @@
+
+
+
+
+
@@ -859,11 +866,10 @@
parent="abstractAuditWebScript">
-
-
-
+
+
diff --git a/source/java/org/alfresco/repo/web/scripts/audit/AbstractAuditWebScript.java b/source/java/org/alfresco/repo/web/scripts/audit/AbstractAuditWebScript.java
index 926e4bdb3a..af90c99def 100644
--- a/source/java/org/alfresco/repo/web/scripts/audit/AbstractAuditWebScript.java
+++ b/source/java/org/alfresco/repo/web/scripts/audit/AbstractAuditWebScript.java
@@ -38,11 +38,14 @@ public abstract class AbstractAuditWebScript extends DeclarativeWebScript
public static final String PARAM_APPLICATION = "application";
public static final String PARAM_PATH="path";
public static final String PARAM_ENABLED = "enabled";
+ public static final String PARAM_FROM_TIME = "fromTime";
+ public static final String PARAM_TO_TIME = "toTime";
public static final String JSON_KEY_ENABLED = "enabled";
public static final String JSON_KEY_APPLICATIONS = "applications";
public static final String JSON_KEY_NAME = "name";
public static final String JSON_KEY_PATH = "path";
+ public static final String JSON_KEY_CLEARED = "cleared";
/**
* Logger that can be used by subclasses.
@@ -113,4 +116,30 @@ public abstract class AbstractAuditWebScript extends DeclarativeWebScript
String enableStr = req.getParameter(PARAM_ENABLED);
return Boolean.parseBoolean(enableStr);
}
+
+ protected Long getFromTime(WebScriptRequest req)
+ {
+ String timeStr = req.getParameter(PARAM_FROM_TIME);
+ try
+ {
+ return Long.parseLong(timeStr);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+ protected Long getToTime(WebScriptRequest req)
+ {
+ String timeStr = req.getParameter(PARAM_TO_TIME);
+ try
+ {
+ return Long.parseLong(timeStr);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
}
diff --git a/source/java/org/alfresco/repo/web/scripts/audit/AuditClearPost.java b/source/java/org/alfresco/repo/web/scripts/audit/AuditClearPost.java
new file mode 100644
index 0000000000..78d64fcda4
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/audit/AuditClearPost.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2005-2010 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.audit;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.alfresco.service.cmr.audit.AuditService.AuditApplication;
+import org.springframework.extensions.webscripts.Cache;
+import org.springframework.extensions.webscripts.Status;
+import org.springframework.extensions.webscripts.WebScriptException;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+
+/**
+ * @author Derek Hulley
+ * @since 3.4
+ */
+public class AuditClearPost extends AbstractAuditWebScript
+{
+ @Override
+ protected Map executeImpl(WebScriptRequest req, Status status, Cache cache)
+ {
+ Map model = new HashMap(7);
+
+ String appName = getAppName(req);
+ if (appName == null)
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST, "audit.err.app.notProvided");
+ }
+ AuditApplication app = auditService.getAuditApplications().get(appName);
+ if (app == null)
+ {
+ throw new WebScriptException(Status.STATUS_NOT_FOUND, "audit.err.app.notFound", appName);
+ }
+ // Get from/to times
+ Long fromTime = getFromTime(req); // might be null
+ Long toTime = getToTime(req); // might be null
+
+ // Clear
+ int cleared = auditService.clearAudit(appName, fromTime, toTime);
+
+ model.put(JSON_KEY_CLEARED, cleared);
+
+ // Done
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
+ }
+ return model;
+ }
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/web/scripts/audit/AuditControlGet.java b/source/java/org/alfresco/repo/web/scripts/audit/AuditControlGet.java
index c2cf5adf6c..ca99404c94 100644
--- a/source/java/org/alfresco/repo/web/scripts/audit/AuditControlGet.java
+++ b/source/java/org/alfresco/repo/web/scripts/audit/AuditControlGet.java
@@ -55,7 +55,7 @@ public class AuditControlGet extends AbstractAuditWebScript
AuditApplication app = appsByName.get(appName);
if (app == null)
{
- throw new WebScriptException(Status.STATUS_NOT_FOUND, "audit.err.app.notFound", app);
+ throw new WebScriptException(Status.STATUS_NOT_FOUND, "audit.err.app.notFound", appName);
}
// Discard all the other applications
appsByName = Collections.singletonMap(appName, app);
diff --git a/source/java/org/alfresco/repo/web/scripts/audit/AuditWebScriptTest.java b/source/java/org/alfresco/repo/web/scripts/audit/AuditWebScriptTest.java
index 40c2430960..f76212de55 100644
--- a/source/java/org/alfresco/repo/web/scripts/audit/AuditWebScriptTest.java
+++ b/source/java/org/alfresco/repo/web/scripts/audit/AuditWebScriptTest.java
@@ -21,10 +21,13 @@ package org.alfresco.repo.web.scripts.audit;
import java.util.Map;
import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.web.scripts.BaseWebScriptTest;
import org.alfresco.service.cmr.audit.AuditService;
import org.alfresco.service.cmr.audit.AuditService.AuditApplication;
+import org.alfresco.service.cmr.security.AuthenticationService;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.context.ApplicationContext;
@@ -42,6 +45,7 @@ public class AuditWebScriptTest extends BaseWebScriptTest
{
private ApplicationContext ctx;
private AuditService auditService;
+ private AuthenticationService authenticationService;
private String admin;
private boolean globallyEnabled;
@@ -50,6 +54,7 @@ public class AuditWebScriptTest extends BaseWebScriptTest
{
super.setUp();
ctx = getServer().getApplicationContext();
+ authenticationService = (AuthenticationService) ctx.getBean("AuthenticationService");
auditService = (AuditService) ctx.getBean("AuditService");
admin = AuthenticationUtil.getAdminUserName();
@@ -205,4 +210,67 @@ public class AuditWebScriptTest extends BaseWebScriptTest
}
}
}
+
+ public void testClearAuditRepo() throws Exception
+ {
+ long now = System.currentTimeMillis();
+ long future = Long.MAX_VALUE;
+
+
+ boolean wasRepoEnabled = auditService.isAuditEnabled(APP_REPO_NAME, APP_REPO_PATH);
+ boolean wasEnabled = auditService.isAuditEnabled();
+ // We need to set this back after the test
+ try
+ {
+ auditService.setAuditEnabled(true);
+ auditService.enableAudit(APP_REPO_NAME, APP_REPO_PATH);
+
+ // Force a failed login
+ RunAsWork failureWork = new RunAsWork()
+ {
+ @Override
+ public Void doWork() throws Exception
+ {
+ try
+ {
+ authenticationService.authenticate("domino", "crud".toCharArray());
+ fail("Failed to force authentication failure");
+ }
+ catch (AuthenticationException e)
+ {
+ // Expected
+ }
+ return null;
+ }
+ };
+ AuthenticationUtil.runAs(failureWork, AuthenticationUtil.getSystemUserName());
+
+ // Delete audit entries that could not have happened
+ String url = "/api/audit/clear/" + APP_REPO_NAME + "?fromTime=" + future;
+ TestWebScriptServer.PostRequest req = new TestWebScriptServer.PostRequest(url, "", MimetypeMap.MIMETYPE_JSON);
+ Response response = sendRequest(req, Status.STATUS_OK, admin);
+ JSONObject json = new JSONObject(response.getContentAsString());
+ int cleared = json.getInt(AbstractAuditWebScript.JSON_KEY_CLEARED);
+ assertEquals("Could not have cleared more than 0", 0, cleared);
+
+ url = "/api/audit/clear/" + APP_REPO_NAME + "?fromTime=" + now + "&toTime=" + future;
+ req = new TestWebScriptServer.PostRequest(url, "", MimetypeMap.MIMETYPE_JSON);
+ response = sendRequest(req, Status.STATUS_OK, admin);
+ json = new JSONObject(response.getContentAsString());
+ cleared = json.getInt(AbstractAuditWebScript.JSON_KEY_CLEARED);
+ assertTrue("Should have cleared at least 1 entry", cleared > 0);
+ }
+ finally
+ {
+ if (wasRepoEnabled)
+ {
+ auditService.enableAudit(APP_REPO_NAME, APP_REPO_PATH);
+ }
+ else
+ {
+ auditService.disableAudit(APP_REPO_NAME, APP_REPO_PATH);
+ }
+ auditService.setAuditEnabled(wasEnabled);
+ }
+ }
}