mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
ALF-4106 (ALF-4103): AuditService REST API; Query
- Added path- and value-based queries - Added limits - .desc.xml documentation - Further unit tests git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22187 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -2,4 +2,6 @@
|
|||||||
audit.err.app.notProvided=Application name not supplied.
|
audit.err.app.notProvided=Application name not supplied.
|
||||||
audit.err.app.notFound=Application not found: {0}
|
audit.err.app.notFound=Application not found: {0}
|
||||||
audit.err.path.notProvided=No path was supplied after the application name.
|
audit.err.path.notProvided=No path was supplied after the application name.
|
||||||
audit.err.action.invalid=Parameter 'action' must be either 'enable' or 'disable'
|
audit.err.action.invalid=Parameter 'action' must be either 'enable' or 'disable'
|
||||||
|
audit.err.value.classNotFound='valueType' not recognised: {0}
|
||||||
|
audit.err.value.convertFailed=Unable to convert ''{0}'' to type ''{1}''
|
@@ -1,7 +1,46 @@
|
|||||||
<webscript>
|
<webscript>
|
||||||
<shortname>Alfresco Audit Service Query</shortname>
|
<shortname>Alfresco Audit Service Query</shortname>
|
||||||
<description>Get audit events</description>
|
<description>
|
||||||
<url>/api/audit/query/{application}?fromId={fromId}&toId={toId}&fromTime={fromTime}&toTime={toTime}&user={user}&forward={forward}&limit={limit}&verbose={verbose}&{k1}={v1}&{k2}={v2}</url>
|
<![CDATA[
|
||||||
|
Query to retrieve audit events.
|
||||||
|
|
||||||
|
JSON returned:
|
||||||
|
{
|
||||||
|
"count":2,
|
||||||
|
"entries":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id":49,
|
||||||
|
"application":AlfrescoRepository,
|
||||||
|
"user":testAuditAuthenticationService,
|
||||||
|
"time":"2010-09-01T14:02:08.454+01:00",
|
||||||
|
"values":
|
||||||
|
{
|
||||||
|
"\/repository\/login\/error\/user":"testAuditAuthenticationService"
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":51,
|
||||||
|
"application":AlfrescoRepository,
|
||||||
|
"user":null,
|
||||||
|
"time":"2010-09-01T15:26:07.571+01:00",
|
||||||
|
"values":
|
||||||
|
{
|
||||||
|
"\/repository\/login\/error\/user":"banana"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
To get the last entry ID:
|
||||||
|
/api/audit/query/{application}?forward=false&limit=1&verbose=false
|
||||||
|
|
||||||
|
Note: It is not possible to get a total result count without executing the query.
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
<url>/api/audit/query/{application}?fromId={fromId}&toId={toId}&fromTime={fromTime}&toTime={toTime}&user={user}&forward={forward}&limit={limit}&verbose={verbose}</url>
|
||||||
|
<url>/api/audit/query/{application}/{path}?value={value}&valueType={valueType}&fromId={fromId}&toId={toId}&fromTime={fromTime}&toTime={toTime}&user={user}&forward={forward}&limit={limit}&verbose={verbose}</url>
|
||||||
<format default="json" />
|
<format default="json" />
|
||||||
<authentication>admin</authentication>
|
<authentication>admin</authentication>
|
||||||
<transaction allow="readonly">required</transaction>
|
<transaction allow="readonly">required</transaction>
|
||||||
@@ -9,15 +48,60 @@
|
|||||||
<args>
|
<args>
|
||||||
<arg>
|
<arg>
|
||||||
<name>application</name>
|
<name>application</name>
|
||||||
<description>Name of the audit application (mandatory parameter)</description>
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Name of the audit application (mandatory).
|
||||||
|
e.g. /api/audit/query/AlfrescoRepository : AlfrescoRepository
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
</arg>
|
</arg>
|
||||||
<arg>
|
<arg>
|
||||||
<name>k1</name>
|
<name>path</name>
|
||||||
<description>First key to query for. If no value is provided, then the present of the key is enough.</description>
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Full value path to search against.
|
||||||
|
e.g. /api/audit/query/AlfrescoRepository/repository/login/error/user : /repository/login/error/user
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
</arg>
|
</arg>
|
||||||
<arg>
|
<arg>
|
||||||
<name>v1</name>
|
<name>value</name>
|
||||||
<description>First value to query for. If this is no provided, then the presence of the key is enough.</description>
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Optional value to search for. If no 'valueType' is specified, then the value will be treated as a String.
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
</arg>
|
||||||
|
<arg>
|
||||||
|
<name>valueType</name>
|
||||||
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Optional class name to convert the 'value' parameter.
|
||||||
|
e.g. valueType=java.lang.Long
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
</arg>
|
||||||
|
<arg>
|
||||||
|
<name>limit</name>
|
||||||
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Optionally limit the number of entries retrieved.
|
||||||
|
e.g. limit=100
|
||||||
|
The default, when unspecified, is 100. Using extreme values will result in memory issues
|
||||||
|
during the FreeMarker template conversion. It is possible to use the lower bound ID-based
|
||||||
|
queries ('fromId'), in conjunction with the 'limit' parameter, to page through results.
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
</arg>
|
||||||
|
<arg>
|
||||||
|
<name>verbose</name>
|
||||||
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Determine if entry 'values' should be returned.
|
||||||
|
e.g. verbose=true : pull back all entry values
|
||||||
|
e.g. verbose=false : ignore all entry values
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
</arg>
|
</arg>
|
||||||
</args>
|
</args>
|
||||||
|
|
||||||
|
@@ -1,20 +1,21 @@
|
|||||||
|
<#escape x as jsonUtils.encodeJSONString(x)>
|
||||||
{
|
{
|
||||||
|
"count":${count?c},
|
||||||
"entries":
|
"entries":
|
||||||
[
|
[
|
||||||
<#list entries as entry>
|
<#list entries as entry>
|
||||||
{
|
{
|
||||||
"id":${entry.id},
|
"id":${entry.id?c},
|
||||||
"application":${entry.application},
|
"application":${entry.application},
|
||||||
"user":<#if entry.user??>${entry.user}<#else>null</#if>,
|
"user":<#if entry.user??>${entry.user}<#else>null</#if>,
|
||||||
"time":${entry.time?c},
|
"time":"${xmldate(entry.time)}",
|
||||||
"values":
|
"values":
|
||||||
<#if entry.values??>
|
<#if entry.values??>
|
||||||
{
|
{
|
||||||
<#assign first=true>
|
<#assign first=true>
|
||||||
<#list entry.values?keys as k>
|
<#list entry.values?keys as k>
|
||||||
<#if entry.values[k]??>
|
<#if entry.values[k]??>
|
||||||
<#if !first>,<#else><#assign first=false></#if>"${k}":
|
<#if !first>,<#else><#assign first=false></#if>"${k}":<#assign value = entry.values[k]>"${value}"
|
||||||
<#assign value = entry.values[k]>"${value}"
|
|
||||||
</#if>
|
</#if>
|
||||||
</#list>
|
</#list>
|
||||||
}
|
}
|
||||||
@@ -23,3 +24,4 @@
|
|||||||
</#list>
|
</#list>
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
</#escape>
|
@@ -38,6 +38,8 @@ public abstract class AbstractAuditWebScript extends DeclarativeWebScript
|
|||||||
public static final String PARAM_APPLICATION = "application";
|
public static final String PARAM_APPLICATION = "application";
|
||||||
public static final String PARAM_PATH="path";
|
public static final String PARAM_PATH="path";
|
||||||
public static final String PARAM_ENABLED = "enabled";
|
public static final String PARAM_ENABLED = "enabled";
|
||||||
|
public static final String PARAM_VALUE = "value";
|
||||||
|
public static final String PARAM_VALUE_TYPE = "valueType";
|
||||||
public static final String PARAM_FROM_TIME = "fromTime";
|
public static final String PARAM_FROM_TIME = "fromTime";
|
||||||
public static final String PARAM_TO_TIME = "toTime";
|
public static final String PARAM_TO_TIME = "toTime";
|
||||||
public static final String PARAM_FROM_ID = "fromId";
|
public static final String PARAM_FROM_ID = "fromId";
|
||||||
@@ -62,12 +64,13 @@ public abstract class AbstractAuditWebScript extends DeclarativeWebScript
|
|||||||
public static final String JSON_KEY_PATH = "path";
|
public static final String JSON_KEY_PATH = "path";
|
||||||
public static final String JSON_KEY_CLEARED = "cleared";
|
public static final String JSON_KEY_CLEARED = "cleared";
|
||||||
|
|
||||||
|
public static final String JSON_KEY_ENTRY_COUNT = "count";
|
||||||
public static final String JSON_KEY_ENTRIES = "entries";
|
public static final String JSON_KEY_ENTRIES = "entries";
|
||||||
public static final String JSON_QUERY_KEY_ID = "id";
|
public static final String JSON_KEY_ENTRY_ID = "id";
|
||||||
public static final String JSON_QUERY_KEY_APPLICATION = "application";
|
public static final String JSON_KEY_ENTRY_APPLICATION = "application";
|
||||||
public static final String JSON_QUERY_KEY_USER = "user";
|
public static final String JSON_KEY_ENTRY_USER = "user";
|
||||||
public static final String JSON_QUERY_KEY_TIME = "time";
|
public static final String JSON_KEY_ENTRY_TIME = "time";
|
||||||
public static final String JSON_QUERY_KEY_VALUES = "values";
|
public static final String JSON_KEY_ENTRY_VALUES = "values";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logger that can be used by subclasses.
|
* Logger that can be used by subclasses.
|
||||||
@@ -139,6 +142,19 @@ public abstract class AbstractAuditWebScript extends DeclarativeWebScript
|
|||||||
return Boolean.parseBoolean(enableStr);
|
return Boolean.parseBoolean(enableStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String getParamValue(WebScriptRequest req)
|
||||||
|
{
|
||||||
|
return req.getParameter(PARAM_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getParamValueType(WebScriptRequest req)
|
||||||
|
{
|
||||||
|
return req.getParameter(PARAM_VALUE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #DEFAULT_FROM_TIME
|
||||||
|
*/
|
||||||
protected Long getParamFromTime(WebScriptRequest req)
|
protected Long getParamFromTime(WebScriptRequest req)
|
||||||
{
|
{
|
||||||
String paramStr = req.getParameter(PARAM_FROM_TIME);
|
String paramStr = req.getParameter(PARAM_FROM_TIME);
|
||||||
@@ -152,6 +168,9 @@ public abstract class AbstractAuditWebScript extends DeclarativeWebScript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #DEFAULT_TO_TIME
|
||||||
|
*/
|
||||||
protected Long getParamToTime(WebScriptRequest req)
|
protected Long getParamToTime(WebScriptRequest req)
|
||||||
{
|
{
|
||||||
String paramStr = req.getParameter(PARAM_TO_TIME);
|
String paramStr = req.getParameter(PARAM_TO_TIME);
|
||||||
@@ -165,6 +184,9 @@ public abstract class AbstractAuditWebScript extends DeclarativeWebScript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #DEFAULT_FROM_ID
|
||||||
|
*/
|
||||||
protected Long getParamFromId(WebScriptRequest req)
|
protected Long getParamFromId(WebScriptRequest req)
|
||||||
{
|
{
|
||||||
String paramStr = req.getParameter(PARAM_FROM_ID);
|
String paramStr = req.getParameter(PARAM_FROM_ID);
|
||||||
@@ -178,6 +200,9 @@ public abstract class AbstractAuditWebScript extends DeclarativeWebScript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #DEFAULT_TO_ID
|
||||||
|
*/
|
||||||
protected Long getParamToId(WebScriptRequest req)
|
protected Long getParamToId(WebScriptRequest req)
|
||||||
{
|
{
|
||||||
String paramStr = req.getParameter(PARAM_TO_ID);
|
String paramStr = req.getParameter(PARAM_TO_ID);
|
||||||
@@ -191,11 +216,17 @@ public abstract class AbstractAuditWebScript extends DeclarativeWebScript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #DEFAULT_USER
|
||||||
|
*/
|
||||||
protected String getParamUser(WebScriptRequest req)
|
protected String getParamUser(WebScriptRequest req)
|
||||||
{
|
{
|
||||||
return req.getParameter(PARAM_USER);
|
return req.getParameter(PARAM_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #DEFAULT_FORWARD
|
||||||
|
*/
|
||||||
protected boolean getParamForward(WebScriptRequest req)
|
protected boolean getParamForward(WebScriptRequest req)
|
||||||
{
|
{
|
||||||
String paramStr = req.getParameter(PARAM_FORWARD);
|
String paramStr = req.getParameter(PARAM_FORWARD);
|
||||||
@@ -206,6 +237,9 @@ public abstract class AbstractAuditWebScript extends DeclarativeWebScript
|
|||||||
return Boolean.parseBoolean(paramStr);
|
return Boolean.parseBoolean(paramStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #DEFAULT_LIMIT
|
||||||
|
*/
|
||||||
protected int getParamLimit(WebScriptRequest req)
|
protected int getParamLimit(WebScriptRequest req)
|
||||||
{
|
{
|
||||||
String paramStr = req.getParameter(PARAM_LIMIT);
|
String paramStr = req.getParameter(PARAM_LIMIT);
|
||||||
@@ -219,6 +253,9 @@ public abstract class AbstractAuditWebScript extends DeclarativeWebScript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #DEFAULT_VERBOSE
|
||||||
|
*/
|
||||||
protected boolean getParamVerbose(WebScriptRequest req)
|
protected boolean getParamVerbose(WebScriptRequest req)
|
||||||
{
|
{
|
||||||
String paramStr = req.getParameter(PARAM_VERBOSE);
|
String paramStr = req.getParameter(PARAM_VERBOSE);
|
||||||
|
@@ -20,6 +20,7 @@ package org.alfresco.repo.web.scripts.audit;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -27,6 +28,7 @@ import java.util.Map;
|
|||||||
import org.alfresco.service.cmr.audit.AuditQueryParameters;
|
import org.alfresco.service.cmr.audit.AuditQueryParameters;
|
||||||
import org.alfresco.service.cmr.audit.AuditService.AuditApplication;
|
import org.alfresco.service.cmr.audit.AuditService.AuditApplication;
|
||||||
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
|
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
|
||||||
|
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||||
import org.springframework.extensions.webscripts.Cache;
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
import org.springframework.extensions.webscripts.Status;
|
import org.springframework.extensions.webscripts.Status;
|
||||||
import org.springframework.extensions.webscripts.WebScriptException;
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
@@ -44,6 +46,10 @@ public class AuditQueryGet extends AbstractAuditWebScript
|
|||||||
final Map<String, Object> model = new HashMap<String, Object>(7);
|
final Map<String, Object> model = new HashMap<String, Object>(7);
|
||||||
|
|
||||||
String appName = getParamAppName(req);
|
String appName = getParamAppName(req);
|
||||||
|
String path = getParamPath(req);
|
||||||
|
|
||||||
|
Serializable value = getParamValue(req);
|
||||||
|
String valueType = getParamValueType(req);
|
||||||
Long fromTime = getParamFromTime(req);
|
Long fromTime = getParamFromTime(req);
|
||||||
Long toTime = getParamToTime(req);
|
Long toTime = getParamToTime(req);
|
||||||
Long fromId = getParamFromId(req);
|
Long fromId = getParamFromId(req);
|
||||||
@@ -63,6 +69,25 @@ public class AuditQueryGet extends AbstractAuditWebScript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transform the value to the correct type
|
||||||
|
if (value != null && valueType != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Class<? extends Serializable> clazz = (Class<? extends Serializable>) Class.forName(valueType);
|
||||||
|
value = DefaultTypeConverter.INSTANCE.convert(clazz, value);
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException e)
|
||||||
|
{
|
||||||
|
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "audit.err.value.classNotFound", valueType);
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "audit.err.value.convertFailed", value, valueType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Execute the query
|
// Execute the query
|
||||||
AuditQueryParameters params = new AuditQueryParameters();
|
AuditQueryParameters params = new AuditQueryParameters();
|
||||||
params.setApplicationName(appName);
|
params.setApplicationName(appName);
|
||||||
@@ -72,6 +97,10 @@ public class AuditQueryGet extends AbstractAuditWebScript
|
|||||||
params.setToId(toId);
|
params.setToId(toId);
|
||||||
params.setUser(user);
|
params.setUser(user);
|
||||||
params.setForward(forward);
|
params.setForward(forward);
|
||||||
|
if (path != null || value != null)
|
||||||
|
{
|
||||||
|
params.addSearchKey(path, value);
|
||||||
|
}
|
||||||
|
|
||||||
final List<Map<String, Object>> entries = new ArrayList<Map<String,Object>>(limit);
|
final List<Map<String, Object>> entries = new ArrayList<Map<String,Object>>(limit);
|
||||||
AuditQueryCallback callback = new AuditQueryCallback()
|
AuditQueryCallback callback = new AuditQueryCallback()
|
||||||
@@ -97,16 +126,16 @@ public class AuditQueryGet extends AbstractAuditWebScript
|
|||||||
Map<String, Serializable> values)
|
Map<String, Serializable> values)
|
||||||
{
|
{
|
||||||
Map<String, Object> entry = new HashMap<String, Object>(11);
|
Map<String, Object> entry = new HashMap<String, Object>(11);
|
||||||
entry.put(JSON_QUERY_KEY_ID, entryId);
|
entry.put(JSON_KEY_ENTRY_ID, entryId);
|
||||||
entry.put(JSON_QUERY_KEY_APPLICATION, applicationName);
|
entry.put(JSON_KEY_ENTRY_APPLICATION, applicationName);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
entry.put(JSON_QUERY_KEY_USER, user);
|
entry.put(JSON_KEY_ENTRY_USER, user);
|
||||||
}
|
}
|
||||||
entry.put(JSON_QUERY_KEY_TIME, new Long(time));
|
entry.put(JSON_KEY_ENTRY_TIME, new Date(time));
|
||||||
if (values != null)
|
if (values != null)
|
||||||
{
|
{
|
||||||
entry.put(JSON_QUERY_KEY_VALUES, values);
|
entry.put(JSON_KEY_ENTRY_VALUES, values);
|
||||||
}
|
}
|
||||||
entries.add(entry);
|
entries.add(entry);
|
||||||
|
|
||||||
@@ -116,6 +145,7 @@ public class AuditQueryGet extends AbstractAuditWebScript
|
|||||||
|
|
||||||
auditService.auditQuery(callback, params, limit);
|
auditService.auditQuery(callback, params, limit);
|
||||||
|
|
||||||
|
model.put(JSON_KEY_ENTRY_COUNT, entries.size());
|
||||||
model.put(JSON_KEY_ENTRIES, entries);
|
model.put(JSON_KEY_ENTRIES, entries);
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.web.scripts.audit;
|
package org.alfresco.repo.web.scripts.audit;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
@@ -31,6 +32,7 @@ import org.alfresco.service.cmr.security.AuthenticationService;
|
|||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.extensions.surf.util.ISO8601DateFormat;
|
||||||
import org.springframework.extensions.webscripts.Status;
|
import org.springframework.extensions.webscripts.Status;
|
||||||
import org.springframework.extensions.webscripts.TestWebScriptServer;
|
import org.springframework.extensions.webscripts.TestWebScriptServer;
|
||||||
import org.springframework.extensions.webscripts.TestWebScriptServer.Response;
|
import org.springframework.extensions.webscripts.TestWebScriptServer.Response;
|
||||||
@@ -212,7 +214,7 @@ public class AuditWebScriptTest extends BaseWebScriptTest
|
|||||||
/**
|
/**
|
||||||
* Perform a failed login attempt
|
* Perform a failed login attempt
|
||||||
*/
|
*/
|
||||||
private void loginWithFailure() throws Exception
|
private void loginWithFailure(final String username) throws Exception
|
||||||
{
|
{
|
||||||
// Force a failed login
|
// Force a failed login
|
||||||
RunAsWork<Void> failureWork = new RunAsWork<Void>()
|
RunAsWork<Void> failureWork = new RunAsWork<Void>()
|
||||||
@@ -222,7 +224,7 @@ public class AuditWebScriptTest extends BaseWebScriptTest
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
authenticationService.authenticate("domino", "crud".toCharArray());
|
authenticationService.authenticate(username, "crud".toCharArray());
|
||||||
fail("Failed to force authentication failure");
|
fail("Failed to force authentication failure");
|
||||||
}
|
}
|
||||||
catch (AuthenticationException e)
|
catch (AuthenticationException e)
|
||||||
@@ -240,7 +242,7 @@ public class AuditWebScriptTest extends BaseWebScriptTest
|
|||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
long future = Long.MAX_VALUE;
|
long future = Long.MAX_VALUE;
|
||||||
|
|
||||||
loginWithFailure();
|
loginWithFailure(getName());
|
||||||
|
|
||||||
// Delete audit entries that could not have happened
|
// Delete audit entries that could not have happened
|
||||||
String url = "/api/audit/clear/" + APP_REPO_NAME + "?fromTime=" + future;
|
String url = "/api/audit/clear/" + APP_REPO_NAME + "?fromTime=" + future;
|
||||||
@@ -249,15 +251,24 @@ public class AuditWebScriptTest extends BaseWebScriptTest
|
|||||||
JSONObject json = new JSONObject(response.getContentAsString());
|
JSONObject json = new JSONObject(response.getContentAsString());
|
||||||
int cleared = json.getInt(AbstractAuditWebScript.JSON_KEY_CLEARED);
|
int cleared = json.getInt(AbstractAuditWebScript.JSON_KEY_CLEARED);
|
||||||
assertEquals("Could not have cleared more than 0", 0, cleared);
|
assertEquals("Could not have cleared more than 0", 0, cleared);
|
||||||
|
|
||||||
|
// Delete the entry (at least)
|
||||||
url = "/api/audit/clear/" + APP_REPO_NAME + "?fromTime=" + now + "&toTime=" + future;
|
url = "/api/audit/clear/" + APP_REPO_NAME + "?fromTime=" + now + "&toTime=" + future;
|
||||||
req = new TestWebScriptServer.PostRequest(url, "", MimetypeMap.MIMETYPE_JSON);
|
req = new TestWebScriptServer.PostRequest(url, "", MimetypeMap.MIMETYPE_JSON);
|
||||||
response = sendRequest(req, Status.STATUS_OK, admin);
|
response = sendRequest(req, Status.STATUS_OK, admin);
|
||||||
json = new JSONObject(response.getContentAsString());
|
json = new JSONObject(response.getContentAsString());
|
||||||
cleared = json.getInt(AbstractAuditWebScript.JSON_KEY_CLEARED);
|
cleared = json.getInt(AbstractAuditWebScript.JSON_KEY_CLEARED);
|
||||||
assertTrue("Should have cleared at least 1 entry", cleared > 0);
|
assertTrue("Should have cleared at least 1 entry", cleared > 0);
|
||||||
|
|
||||||
|
// Delete all entries
|
||||||
|
url = "/api/audit/clear/" + APP_REPO_NAME;;
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public void testQueryAuditRepo() throws Exception
|
public void testQueryAuditRepo() throws Exception
|
||||||
{
|
{
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
@@ -266,14 +277,98 @@ public class AuditWebScriptTest extends BaseWebScriptTest
|
|||||||
auditService.setAuditEnabled(true);
|
auditService.setAuditEnabled(true);
|
||||||
auditService.enableAudit(APP_REPO_NAME, APP_REPO_PATH);
|
auditService.enableAudit(APP_REPO_NAME, APP_REPO_PATH);
|
||||||
|
|
||||||
loginWithFailure();
|
loginWithFailure(getName());
|
||||||
|
|
||||||
// Delete audit entries that could not have happened
|
// Query for audit entries that could not have happened
|
||||||
String url = "/api/audit/query/" + APP_REPO_NAME + "?fromTime=" + now + "&verbose=true";
|
String url = "/api/audit/query/" + APP_REPO_NAME + "?fromTime=" + now + "&verbose=true";
|
||||||
TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url);
|
TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url);
|
||||||
Response response = sendRequest(req, Status.STATUS_OK, admin);
|
Response response = sendRequest(req, Status.STATUS_OK, admin);
|
||||||
JSONObject json = new JSONObject(response.getContentAsString());
|
JSONObject json = new JSONObject(response.getContentAsString());
|
||||||
|
Long entryCount = json.getLong(AbstractAuditWebScript.JSON_KEY_ENTRY_COUNT);
|
||||||
JSONArray jsonEntries = json.getJSONArray(AbstractAuditWebScript.JSON_KEY_ENTRIES);
|
JSONArray jsonEntries = json.getJSONArray(AbstractAuditWebScript.JSON_KEY_ENTRIES);
|
||||||
assertTrue("Expected at least one entry", jsonEntries.length() > 0);
|
assertTrue("Expected at least one entry", jsonEntries.length() > 0);
|
||||||
|
assertEquals("Entry count and physical count don't match", new Long(jsonEntries.length()), entryCount);
|
||||||
|
JSONObject jsonEntry = jsonEntries.getJSONObject(0);
|
||||||
|
Long entryId = jsonEntry.getLong(AbstractAuditWebScript.JSON_KEY_ENTRY_ID);
|
||||||
|
assertNotNull("No entry ID", entryId);
|
||||||
|
String entryTimeStr = jsonEntry.getString(AbstractAuditWebScript.JSON_KEY_ENTRY_TIME);
|
||||||
|
assertNotNull("No entry time String", entryTimeStr);
|
||||||
|
Date entryTime = ISO8601DateFormat.parse((String)entryTimeStr); // Check conversion
|
||||||
|
JSONObject jsonValues = jsonEntry.getJSONObject(AbstractAuditWebScript.JSON_KEY_ENTRY_VALUES);
|
||||||
|
String entryUsername = jsonValues.getString("/repository/login/error/user");
|
||||||
|
assertEquals("Didn't find the login-failure-user", getName(), entryUsername);
|
||||||
|
|
||||||
|
// Query using well-known ID
|
||||||
|
Long fromEntryId = entryId; // Search is inclusive on the 'from' side
|
||||||
|
Long toEntryId = entryId.longValue() + 1L; // Search is exclusive on the 'to' side
|
||||||
|
url = "/api/audit/query/" + APP_REPO_NAME + "?fromId=" + fromEntryId + "&toId=" + toEntryId;
|
||||||
|
req = new TestWebScriptServer.GetRequest(url);
|
||||||
|
response = sendRequest(req, Status.STATUS_OK, admin);
|
||||||
|
json = new JSONObject(response.getContentAsString());
|
||||||
|
jsonEntries = json.getJSONArray(AbstractAuditWebScript.JSON_KEY_ENTRIES);
|
||||||
|
assertEquals("Incorrect number of search results", 1, jsonEntries.length());
|
||||||
|
|
||||||
|
// Query using a non-existent entry path
|
||||||
|
url = "/api/audit/query/" + APP_REPO_NAME + "/repository/login/error/userXXX" + "?verbose=true";
|
||||||
|
req = new TestWebScriptServer.GetRequest(url);
|
||||||
|
response = sendRequest(req, Status.STATUS_OK, admin);
|
||||||
|
json = new JSONObject(response.getContentAsString());
|
||||||
|
jsonEntries = json.getJSONArray(AbstractAuditWebScript.JSON_KEY_ENTRIES);
|
||||||
|
assertTrue("Should not have found anything", jsonEntries.length() == 0);
|
||||||
|
|
||||||
|
// Query using a good entry path
|
||||||
|
url = "/api/audit/query/" + APP_REPO_NAME + "/repository/login/error/user" + "?verbose=true";
|
||||||
|
req = new TestWebScriptServer.GetRequest(url);
|
||||||
|
response = sendRequest(req, Status.STATUS_OK, admin);
|
||||||
|
json = new JSONObject(response.getContentAsString());
|
||||||
|
jsonEntries = json.getJSONArray(AbstractAuditWebScript.JSON_KEY_ENTRIES);
|
||||||
|
assertTrue("Should have found entries", jsonEntries.length() > 0);
|
||||||
|
|
||||||
|
// Now login with failure using a GUID and ensure that we can find it
|
||||||
|
String missingUser = new Long(System.currentTimeMillis()).toString();
|
||||||
|
|
||||||
|
// Query for event that has not happened
|
||||||
|
url = "/api/audit/query/" + APP_REPO_NAME + "/repository/login/error/user" + "?value=" + missingUser;
|
||||||
|
req = new TestWebScriptServer.GetRequest(url);
|
||||||
|
response = sendRequest(req, Status.STATUS_OK, admin);
|
||||||
|
json = new JSONObject(response.getContentAsString());
|
||||||
|
jsonEntries = json.getJSONArray(AbstractAuditWebScript.JSON_KEY_ENTRIES);
|
||||||
|
assertEquals("Incorrect number of search results", 0, jsonEntries.length());
|
||||||
|
|
||||||
|
loginWithFailure(missingUser);
|
||||||
|
|
||||||
|
// Query for event that has happened once
|
||||||
|
url = "/api/audit/query/" + APP_REPO_NAME + "/repository/login/error/user" + "?value=" + missingUser;
|
||||||
|
req = new TestWebScriptServer.GetRequest(url);
|
||||||
|
response = sendRequest(req, Status.STATUS_OK, admin);
|
||||||
|
json = new JSONObject(response.getContentAsString());
|
||||||
|
jsonEntries = json.getJSONArray(AbstractAuditWebScript.JSON_KEY_ENTRIES);
|
||||||
|
assertEquals("Incorrect number of search results", 1, jsonEntries.length());
|
||||||
|
|
||||||
|
// Query for event, but casting the value to the incorrect type
|
||||||
|
url = "/api/audit/query/" + APP_REPO_NAME + "/repository/login/error/user" + "?value=" + missingUser + "&valueType=java.lang.Long";
|
||||||
|
req = new TestWebScriptServer.GetRequest(url);
|
||||||
|
response = sendRequest(req, Status.STATUS_OK, admin);
|
||||||
|
json = new JSONObject(response.getContentAsString());
|
||||||
|
jsonEntries = json.getJSONArray(AbstractAuditWebScript.JSON_KEY_ENTRIES);
|
||||||
|
assertEquals("Incorrect number of search results", 0, jsonEntries.length());
|
||||||
|
|
||||||
|
// Test what happens when the target data needs encoding
|
||||||
|
String oddUser = "%$£\\\"\'";
|
||||||
|
loginWithFailure(oddUser);
|
||||||
|
|
||||||
|
// Query for the event limiting to one by count and descending (i.e. get last)
|
||||||
|
url = "/api/audit/query/" + APP_REPO_NAME + "?forward=false&limit=1&verbose=true";
|
||||||
|
req = new TestWebScriptServer.GetRequest(url);
|
||||||
|
response = sendRequest(req, Status.STATUS_OK, admin);
|
||||||
|
json = new JSONObject(response.getContentAsString());
|
||||||
|
jsonEntries = json.getJSONArray(AbstractAuditWebScript.JSON_KEY_ENTRIES);
|
||||||
|
assertEquals("Incorrect number of search results", 1, jsonEntries.length());
|
||||||
|
jsonEntry = jsonEntries.getJSONObject(0);
|
||||||
|
entryId = jsonEntry.getLong(AbstractAuditWebScript.JSON_KEY_ENTRY_ID);
|
||||||
|
assertNotNull("No entry ID", entryId);
|
||||||
|
jsonValues = jsonEntry.getJSONObject(AbstractAuditWebScript.JSON_KEY_ENTRY_VALUES);
|
||||||
|
entryUsername = jsonValues.getString("/repository/login/error/user");
|
||||||
|
assertEquals("Didn't find the login-failure-user", oddUser, entryUsername);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user