Skip to content

Commit

Permalink
Fixed MID-3903: No filtering for events of unknown outcome
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Dec 2, 2017
1 parent ca14223 commit bbf6a8b
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 74 deletions.
Expand Up @@ -89,7 +89,6 @@ public class PageAuditLogDetails extends PageBase {
private static final String ID_HISTORY_PANEL = "historyPanel";

private static final String ID_BUTTON_BACK = "back";
private static final String TASK_IDENTIFIER_PARAMETER = "taskIdentifier";
private static final int TASK_EVENTS_TABLE_SIZE = 10;

private static final String OPERATION_RESOLVE_REFERENCE_NAME = PageAuditLogDetails.class.getSimpleName()
Expand Down Expand Up @@ -153,7 +152,7 @@ private void initAuditLogHistoryPanel(WebMarkupContainer eventPanel){

public Map<String, Object> getParameters() {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put(TASK_IDENTIFIER_PARAMETER, recordModel.getObject().getTaskIdentifier());
parameters.put(AuditEventRecordProvider.PARAMETER_TASK_IDENTIFIER, recordModel.getObject().getTaskIdentifier());
return parameters;
}
};
Expand Down
Expand Up @@ -254,13 +254,10 @@ private void initParametersPanel(Form mainForm) {
eventStageField.setOutputMarkupId(true);
eventStage.add(eventStageField);

ListModel<OperationResultStatusType> outcomeListModel = new ListModel<OperationResultStatusType>(
Arrays.asList(OperationResultStatusType.values()));
PropertyModel<OperationResultStatusType> outcomeModel = new PropertyModel<OperationResultStatusType>(
getModel(), AuditSearchDto.F_OUTCOME);
DropDownChoicePanel<OperationResultStatusType> outcome = new DropDownChoicePanel<OperationResultStatusType>(
ID_OUTCOME, outcomeModel, outcomeListModel,
new EnumChoiceRenderer<OperationResultStatusType>(), true);
ListModel<OperationResultStatusType> outcomeListModel = new ListModel<>(Arrays.asList(OperationResultStatusType.values()));
PropertyModel<OperationResultStatusType> outcomeModel = new PropertyModel<>(getModel(), AuditSearchDto.F_OUTCOME);
DropDownChoicePanel<OperationResultStatusType> outcome = new DropDownChoicePanel<>(ID_OUTCOME, outcomeModel,
outcomeListModel, new EnumChoiceRenderer<>(), true);
outcome.getBaseFormComponent().add(new EmptyOnChangeAjaxFormUpdatingBehavior());
outcome.getBaseFormComponent().add(new EmptyOnBlurAjaxFormUpdatingBehaviour());
outcome.setOutputMarkupId(true);
Expand All @@ -287,17 +284,18 @@ private void initParametersPanel(Form mainForm) {

List<Class<? extends ObjectType>> allowedClasses = new ArrayList<>();
allowedClasses.add(UserType.class);
MultiValueChoosePanel<ObjectType> chooseInitiatorPanel = new SingleValueChoosePanel<ObjectReferenceType, ObjectType>(
ID_INITIATOR_NAME, allowedClasses, objectReferenceTransformer,
new PropertyModel<ObjectReferenceType>(getModel(), AuditSearchDto.F_INITIATOR_NAME));
MultiValueChoosePanel<ObjectType> chooseInitiatorPanel = new SingleValueChoosePanel<>(
ID_INITIATOR_NAME, allowedClasses, objectReferenceTransformer,
new PropertyModel<>(getModel(), AuditSearchDto.F_INITIATOR_NAME));
parametersPanel.add(chooseInitiatorPanel);

WebMarkupContainer targetOwnerName = new WebMarkupContainer(ID_TARGET_OWNER_NAME);
targetOwnerName.add(visibilityByKey(visibilityMap, TARGET_OWNER_LABEL_VISIBILITY));
parametersPanel.add(targetOwnerName);

MultiValueChoosePanel<ObjectType> chooseTargetOwnerPanel = new SingleValueChoosePanel<ObjectReferenceType, ObjectType>(
ID_TARGET_OWNER_NAME_FIELD, allowedClasses, objectReferenceTransformer, new PropertyModel<ObjectReferenceType>(getModel(), AuditSearchDto.F_TARGET_OWNER_NAME));
MultiValueChoosePanel<ObjectType> chooseTargetOwnerPanel = new SingleValueChoosePanel<>(
ID_TARGET_OWNER_NAME_FIELD, allowedClasses, objectReferenceTransformer,
new PropertyModel<>(getModel(), AuditSearchDto.F_TARGET_OWNER_NAME));

chooseTargetOwnerPanel.add(visibilityByKey(visibilityMap, TARGET_OWNER_FIELD_VISIBILITY));
targetOwnerName.add(chooseTargetOwnerPanel);
Expand Down Expand Up @@ -396,20 +394,20 @@ public Map<String, Object> getParameters() {
Map<String, Object> parameters = new HashMap<String, Object>();

AuditSearchDto search = AuditLogViewerPanel.this.getModelObject();
parameters.put("from", search.getFrom());
parameters.put("to", search.getTo());
parameters.put(AuditEventRecordProvider.PARAMETER_FROM, search.getFrom());
parameters.put(AuditEventRecordProvider.PARAMETER_TO, search.getTo());

if (search.getChannel() != null) {
parameters.put("channel", QNameUtil.qNameToUri(search.getChannel()));
parameters.put(AuditEventRecordProvider.PARAMETER_CHANNEL, QNameUtil.qNameToUri(search.getChannel()));
}
parameters.put("hostIdentifier", search.getHostIdentifier());
parameters.put(AuditEventRecordProvider.PARAMETER_HOST_IDENTIFIER, search.getHostIdentifier());

if (search.getInitiatorName() != null) {
parameters.put("initiatorName", search.getInitiatorName().getOid());
parameters.put(AuditEventRecordProvider.PARAMETER_INITIATOR_NAME, search.getInitiatorName().getOid());
}

if (search.getTargetOwnerName() != null) {
parameters.put("targetOwnerName", search.getTargetOwnerName().getOid());
parameters.put(AuditEventRecordProvider.PARAMETER_TARGET_OWNER_NAME, search.getTargetOwnerName().getOid());
}
List<String> targetOids = new ArrayList<>();
if (isNotEmpty(search.getTargetNamesObjects())) {
Expand All @@ -422,18 +420,18 @@ public Map<String, Object> getParameters() {
.map(ObjectReferenceType::getOid)
.collect(toList()));
}
if( ! targetOids.isEmpty()) {
parameters.put("targetNames", targetOids);
if (!targetOids.isEmpty()) {
parameters.put(AuditEventRecordProvider.PARAMETER_TARGET_NAMES, targetOids);
}
if (search.getChangedItem().toItemPath() != null) {
ItemPath itemPath = search.getChangedItem().toItemPath();
parameters.put("changedItem", CanonicalItemPath.create(itemPath).asString());
parameters.put(AuditEventRecordProvider.PARAMETER_CHANGED_ITEM, CanonicalItemPath.create(itemPath).asString());
}
parameters.put("eventType", search.getEventType());
parameters.put("eventStage", search.getEventStage());
parameters.put("outcome", search.getOutcome());
if(isNotEmpty(search.getvalueRefTargetNames())) {
parameters.put(AuditEventRecordProvider.VALUE_REF_TARGET_NAMES_KEY,
parameters.put(AuditEventRecordProvider.PARAMETER_EVENT_TYPE, search.getEventType());
parameters.put(AuditEventRecordProvider.PARAMETER_EVENT_STAGE, search.getEventStage());
parameters.put(AuditEventRecordProvider.PARAMETER_OUTCOME, search.getOutcome());
if (isNotEmpty(search.getvalueRefTargetNames())) {
parameters.put(AuditEventRecordProvider.PARAMETER_VALUE_REF_TARGET_NAMES,
search.getvalueRefTargetNames().stream()
.map(ObjectType::getName)
.map(PolyStringType::getOrig)
Expand All @@ -452,12 +450,12 @@ protected void saveCurrentPage(long from, long count) {
};
UserProfileStorage userProfile = pageBase.getSessionStorage().getUserProfile();
int pageSize = DEFAULT_PAGE_SIZE;
if (userProfile.getTables().containsKey(UserProfileStorage.TableId.PAGE_AUDIT_LOG_VIEWER)){
if (userProfile.getTables().containsKey(UserProfileStorage.TableId.PAGE_AUDIT_LOG_VIEWER)) {
pageSize = userProfile.getPagingSize(UserProfileStorage.TableId.PAGE_AUDIT_LOG_VIEWER);
}
List<IColumn<AuditEventRecordType, String>> columns = initColumns();
BoxedTablePanel<AuditEventRecordType> table = new BoxedTablePanel<AuditEventRecordType>(ID_TABLE, provider, columns,
UserProfileStorage.TableId.PAGE_AUDIT_LOG_VIEWER, pageSize){
UserProfileStorage.TableId.PAGE_AUDIT_LOG_VIEWER, pageSize) {
private static final long serialVersionUID = 1L;

@Override
Expand Down
Expand Up @@ -22,13 +22,13 @@
import java.util.List;
import java.util.Map;

import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.Component;
import org.apache.wicket.model.IModel;

import com.evolveum.midpoint.audit.api.AuditEventRecord;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
Expand All @@ -49,8 +49,22 @@
public class AuditEventRecordProvider extends BaseSortableDataProvider<AuditEventRecordType> {
private static final long serialVersionUID = 1L;

public static final String VALUE_REF_TARGET_NAMES_KEY = "valueRefTargetNames";
private static final Trace LOGGER = TraceManager.getTrace(BaseSortableDataProvider.class);

public static final String PARAMETER_VALUE_REF_TARGET_NAMES = "valueRefTargetNames";
public static final String PARAMETER_CHANGED_ITEM = "changedItem";
public static final String PARAMETER_FROM = "from";
public static final String PARAMETER_TO = "to";
public static final String PARAMETER_EVENT_TYPE = "eventType";
public static final String PARAMETER_EVENT_STAGE = "eventStage";
public static final String PARAMETER_OUTCOME = "outcome";
public static final String PARAMETER_INITIATOR_NAME = "initiatorName";
public static final String PARAMETER_CHANNEL = "channel";
public static final String PARAMETER_HOST_IDENTIFIER = "hostIdentifier";
public static final String PARAMETER_TARGET_OWNER_NAME = "targetOwnerName";
public static final String PARAMETER_TARGET_NAMES = "targetNames";
public static final String PARAMETER_TASK_IDENTIFIER = "taskIdentifier";

private IModel<List<AuditEventRecordType>> model;

private String auditEventQuery;
Expand All @@ -63,7 +77,7 @@ public class AuditEventRecordProvider extends BaseSortableDataProvider<AuditEven
private static final String SET_MAX_RESULTS_PARAMETER = "setMaxResults";

public AuditEventRecordProvider(Component component){
this(component, AUDIT_RECORDS_QUERY_CORE, new HashMap<String, Object>());
this(component, AUDIT_RECORDS_QUERY_CORE, new HashMap<>());
}

public AuditEventRecordProvider(Component component, String auditEventQuery, Map<String, Object> parameters ){
Expand Down Expand Up @@ -166,98 +180,102 @@ public void setAuditEventQuery(String auditEventQuery) {

private String generateFullQuery(String query, boolean orderBy, boolean isCount){
parameters = getParameters();
String valueRefFrom = constraintsValueRef(parameters) ? " left outer join aer.referenceValues as rv " : "";
if (parameters.get("changedItem") != null) {
String valueRefFromClause = constraintsValueRef(parameters) ? " left outer join aer.referenceValues as rv " : "";
if (parameters.get(PARAMETER_CHANGED_ITEM) != null) {
if (isCount) {
query = "select count(*) from RAuditEventRecord as aer right join aer.changedItems as item " + valueRefFrom + " where 1=1 and ";
query = "select count(*) from RAuditEventRecord as aer right join aer.changedItems as item " + valueRefFromClause + " where 1=1 and ";
} else {
query = "from RAuditEventRecord as aer right join aer.changedItems as item " + valueRefFrom + " where 1=1 and ";
query = "from RAuditEventRecord as aer right join aer.changedItems as item " + valueRefFromClause + " where 1=1 and ";
}
// query += "INNER JOIN aer.changedItems as item on item.record_id = aer.id WHERE 1=1 and "
// + "(item.changedItemPath = :changedItem) and ";
query += "(item.changedItemPath = :changedItem) and ";

} else {
parameters.remove("changedItem");
// query += "where 1=1 and ";
parameters.remove(PARAMETER_CHANGED_ITEM);
}

if (parameters.get("from") != null) {
if (parameters.get(PARAMETER_FROM) != null) {
query += "(aer.timestamp >= :from) and ";
} else {
parameters.remove("from");
parameters.remove(PARAMETER_FROM);
}
if (parameters.get("to") != null) {
if (parameters.get(PARAMETER_TO) != null) {
query += "(aer.timestamp <= :to) and ";
} else {
parameters.remove("to");
parameters.remove(PARAMETER_TO);
}
if (parameters.get("eventType") != null) {
if (parameters.get(PARAMETER_EVENT_TYPE) != null) {
query += "(aer.eventType = :eventType) and ";
} else {
parameters.remove("eventType");
parameters.remove(PARAMETER_EVENT_TYPE);
}
if (parameters.get("eventStage") != null) {
if (parameters.get(PARAMETER_EVENT_STAGE) != null) {
query += "(aer.eventStage = :eventStage) and ";
} else {
parameters.remove("eventStage");
parameters.remove(PARAMETER_EVENT_STAGE);
}
if (parameters.get("outcome") != null) {
query += "(aer.outcome = :outcome) and ";
Object outcomeValue = parameters.get(PARAMETER_OUTCOME);
if (outcomeValue != null) {
if (outcomeValue != OperationResultStatusType.UNKNOWN) {
query += "(aer.outcome = :outcome) and ";
} else {
// this is a bit questionable; but let us do it in this way to ensure compliance with GUI (null is shown as UNKNOWN)
// see MID-3903
query += "(aer.outcome = :outcome or aer.outcome is null) and ";
}
} else {
parameters.remove("outcome");
parameters.remove(PARAMETER_OUTCOME);
}
if (parameters.get("initiatorName") != null) {
if (parameters.get(PARAMETER_INITIATOR_NAME) != null) {
query += "(aer.initiatorOid = :initiatorName) and ";
} else {
parameters.remove("initiatorName");
parameters.remove(PARAMETER_INITIATOR_NAME);
}
if (parameters.get("channel") != null) {
if (parameters.get(PARAMETER_CHANNEL) != null) {
query += "(aer.channel = :channel) and ";
} else {
parameters.remove("channel");
parameters.remove(PARAMETER_CHANNEL);
}
if (parameters.get("hostIdentifier") != null) {
if (parameters.get(PARAMETER_HOST_IDENTIFIER) != null) {
query += "(aer.hostIdentifier = :hostIdentifier) and ";
} else {
parameters.remove("hostIdentifier");
parameters.remove(PARAMETER_HOST_IDENTIFIER);
}
if (parameters.get("targetOwnerName") != null) {
if (parameters.get(PARAMETER_TARGET_OWNER_NAME) != null) {
query += "(aer.targetOwnerOid = :targetOwnerName) and ";
} else {
parameters.remove("targetOwnerName");
parameters.remove(PARAMETER_TARGET_OWNER_NAME);
}
if (parameters.get("targetNames") != null) {
if (parameters.get(PARAMETER_TARGET_NAMES) != null) {
query += "(aer.targetOid in ( :targetNames )) and ";
} else {
parameters.remove("targetNames");
parameters.remove(PARAMETER_TARGET_NAMES);
}
if (parameters.get("taskIdentifier") != null) {
if (parameters.get(PARAMETER_TASK_IDENTIFIER) != null) {
query += "(aer.taskIdentifier = :taskIdentifier) and ";
} else {
parameters.remove("taskIdentifier");
parameters.remove(PARAMETER_TASK_IDENTIFIER);
}
if (valueRefTargetIsNotEmpty(parameters.get(VALUE_REF_TARGET_NAMES_KEY))) {
if (valueRefTargetIsNotEmpty(parameters.get(PARAMETER_VALUE_REF_TARGET_NAMES))) {
query += "(rv.targetName.orig in ( :valueRefTargetNames )) and ";
} else {
parameters.remove(VALUE_REF_TARGET_NAMES_KEY);
parameters.remove(PARAMETER_VALUE_REF_TARGET_NAMES);
}

query = query.substring(0, query.length()-5); // remove trailing " and "
if (orderBy){
query += AUDIT_RECORDS_ORDER_BY;
if (orderBy) {
query += AUDIT_RECORDS_ORDER_BY;
}
return query;
}

private boolean constraintsValueRef(Map<String, Object> parameters2) {
return valueRefTargetIsNotEmpty(parameters2.get(VALUE_REF_TARGET_NAMES_KEY));
return valueRefTargetIsNotEmpty(parameters2.get(PARAMETER_VALUE_REF_TARGET_NAMES));
}

private boolean valueRefTargetIsNotEmpty(Object valueRefTargetNamesParam) {
if(valueRefTargetNamesParam instanceof String) {
if (valueRefTargetNamesParam instanceof String) {
return StringUtils.isNotBlank((String)valueRefTargetNamesParam);
} else if(valueRefTargetNamesParam instanceof Collection){
} else if (valueRefTargetNamesParam instanceof Collection) {
return CollectionUtils.isNotEmpty((Collection)valueRefTargetNamesParam);
} else {
return valueRefTargetNamesParam != null;
Expand Down
Expand Up @@ -15,10 +15,8 @@
*/
package com.evolveum.midpoint.model.intest;

import static com.evolveum.midpoint.test.IntegrationTestTools.display;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.fail;

import java.io.File;
import java.util.*;
Expand All @@ -34,6 +32,7 @@
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.prism.xml.XmlTypeConverter;
import com.evolveum.midpoint.schema.ObjectDeltaOperation;
import com.evolveum.midpoint.schema.result.OperationResultStatus;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
Expand Down Expand Up @@ -533,6 +532,34 @@ public void test254ReconstructHermanHermit() throws Exception {
assertAssignments(hermanReconstructed, 2);
}

@Test
public void test300QueryUnknown() throws Exception {
final String TEST_NAME = "test300QueryUnknown";
displayTestTitle(TEST_NAME);

Task task = createTask(TEST_NAME);
OperationResult result = task.getResult();

// WHEN
displayWhen(TEST_NAME);

AuditEventRecord record = new AuditEventRecord(AuditEventType.SYNCHRONIZATION, AuditEventStage.EXECUTION);
record.setOutcome(OperationResultStatus.UNKNOWN);
modelAuditService.audit(record, task, result);

HashMap<String, Object> params = new HashMap<>();
params.put("outcome", OperationResultStatusType.UNKNOWN);
List<AuditEventRecord> records = modelAuditService.listRecords("from RAuditEventRecord as aer where aer.outcome = :outcome", params, task, result);

// THEN
displayThen(TEST_NAME);
display("records", records);
assertEquals("Wrong # of records", 1, records.size());

// THEN
assertSuccess(result);
}

private String assertObjectAuditRecords(String oid, int expectedNumberOfRecords) throws SecurityViolationException, SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException {
Task task = createTask("assertObjectAuditRecords");
OperationResult result = task.getResult();
Expand Down

0 comments on commit bbf6a8b

Please sign in to comment.