diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/PageAuditLogDetails.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/PageAuditLogDetails.java index 6bbc614ac15..7866a70543c 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/PageAuditLogDetails.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/PageAuditLogDetails.java @@ -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() @@ -153,7 +152,7 @@ private void initAuditLogHistoryPanel(WebMarkupContainer eventPanel){ public Map getParameters() { Map parameters = new HashMap(); - parameters.put(TASK_IDENTIFIER_PARAMETER, recordModel.getObject().getTaskIdentifier()); + parameters.put(AuditEventRecordProvider.PARAMETER_TASK_IDENTIFIER, recordModel.getObject().getTaskIdentifier()); return parameters; } }; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/AuditLogViewerPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/AuditLogViewerPanel.java index e2edb572c6b..0b22e3c2a66 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/AuditLogViewerPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/AuditLogViewerPanel.java @@ -254,13 +254,10 @@ private void initParametersPanel(Form mainForm) { eventStageField.setOutputMarkupId(true); eventStage.add(eventStageField); - ListModel outcomeListModel = new ListModel( - Arrays.asList(OperationResultStatusType.values())); - PropertyModel outcomeModel = new PropertyModel( - getModel(), AuditSearchDto.F_OUTCOME); - DropDownChoicePanel outcome = new DropDownChoicePanel( - ID_OUTCOME, outcomeModel, outcomeListModel, - new EnumChoiceRenderer(), true); + ListModel outcomeListModel = new ListModel<>(Arrays.asList(OperationResultStatusType.values())); + PropertyModel outcomeModel = new PropertyModel<>(getModel(), AuditSearchDto.F_OUTCOME); + DropDownChoicePanel outcome = new DropDownChoicePanel<>(ID_OUTCOME, outcomeModel, + outcomeListModel, new EnumChoiceRenderer<>(), true); outcome.getBaseFormComponent().add(new EmptyOnChangeAjaxFormUpdatingBehavior()); outcome.getBaseFormComponent().add(new EmptyOnBlurAjaxFormUpdatingBehaviour()); outcome.setOutputMarkupId(true); @@ -287,17 +284,18 @@ private void initParametersPanel(Form mainForm) { List> allowedClasses = new ArrayList<>(); allowedClasses.add(UserType.class); - MultiValueChoosePanel chooseInitiatorPanel = new SingleValueChoosePanel( - ID_INITIATOR_NAME, allowedClasses, objectReferenceTransformer, - new PropertyModel(getModel(), AuditSearchDto.F_INITIATOR_NAME)); + MultiValueChoosePanel 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 chooseTargetOwnerPanel = new SingleValueChoosePanel( - ID_TARGET_OWNER_NAME_FIELD, allowedClasses, objectReferenceTransformer, new PropertyModel(getModel(), AuditSearchDto.F_TARGET_OWNER_NAME)); + MultiValueChoosePanel 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); @@ -396,20 +394,20 @@ public Map getParameters() { Map parameters = new HashMap(); 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 targetOids = new ArrayList<>(); if (isNotEmpty(search.getTargetNamesObjects())) { @@ -422,18 +420,18 @@ public Map 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) @@ -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> columns = initColumns(); BoxedTablePanel table = new BoxedTablePanel(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 diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/dto/AuditEventRecordProvider.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/dto/AuditEventRecordProvider.java index 549d41c9340..6e7117bb12a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/dto/AuditEventRecordProvider.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/dto/AuditEventRecordProvider.java @@ -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; @@ -49,8 +49,22 @@ public class AuditEventRecordProvider extends BaseSortableDataProvider { 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> model; private String auditEventQuery; @@ -63,7 +77,7 @@ public class AuditEventRecordProvider extends BaseSortableDataProvider()); + this(component, AUDIT_RECORDS_QUERY_CORE, new HashMap<>()); } public AuditEventRecordProvider(Component component, String auditEventQuery, Map parameters ){ @@ -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 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; diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestAudit.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestAudit.java index 820f8f23de3..345d7a56386 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestAudit.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestAudit.java @@ -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.*; @@ -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; @@ -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 params = new HashMap<>(); + params.put("outcome", OperationResultStatusType.UNKNOWN); + List 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(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceImpl.java index 833523c8b9b..08187995e55 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceImpl.java @@ -30,8 +30,10 @@ import javax.xml.datatype.XMLGregorianCalendar; import com.evolveum.midpoint.repo.sql.data.audit.*; +import com.evolveum.midpoint.repo.sql.data.common.enums.ROperationResultStatus; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; @@ -308,13 +310,15 @@ private List convertValues(List originValues) { return repoValues; } - private Object toRepoType(Object value){ + private Object toRepoType(Object value) { if (XMLGregorianCalendar.class.isAssignableFrom(value.getClass())) { return MiscUtil.asDate((XMLGregorianCalendar) value); } else if (value instanceof AuditEventType) { return RAuditEventType.toRepo((AuditEventType) value); } else if (value instanceof AuditEventStage) { return RAuditEventStage.toRepo((AuditEventStage) value); + } else if (value instanceof OperationResultStatusType) { + return ROperationResultStatus.toRepo((OperationResultStatusType) value); } return value; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/ROperationResultStatus.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/ROperationResultStatus.java index 613962620f0..dcf0a45b35e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/ROperationResultStatus.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/ROperationResultStatus.java @@ -49,4 +49,16 @@ public OperationResultStatus getStatus(){ public OperationResultStatusType getSchemaValue() { return status; } + + public static ROperationResultStatus toRepo(OperationResultStatusType jaxb) { + if (jaxb == null) { + return null; + } + for (ROperationResultStatus st : values()) { + if (jaxb == st.status) { + return st; + } + } + throw new IllegalArgumentException("Unknown operation result state '" + jaxb + "'."); + } }