diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestNotifications.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestNotifications.java index 705a73d1a3d..d75b8d004fb 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestNotifications.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestNotifications.java @@ -23,6 +23,7 @@ import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.ReferenceDelta; +import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.internals.InternalCounters; @@ -365,7 +366,7 @@ public void test131ModifyUserJackAssignAccount() throws Exception { } @Test - public void test135ModifyUserJackAssignRole() throws Exception { + public void test140ModifyUserJackAssignRole() throws Exception { final String TEST_NAME = "test135ModifyUserJackAssignRole"; TestUtil.displayTestTitle(this, TEST_NAME); @@ -415,7 +416,127 @@ public void test135ModifyUserJackAssignRole() throws Exception { + "\n" + "Channel: "; assertEquals("Wrong message body", expected, dummyTransport.getMessages("dummy:simpleUserNotifier").get(0).getBody()); + } + + @Test + public void test150ModifyUserJackModifyAssignment() throws Exception { + final String TEST_NAME = "test150ModifyUserJackModifyAssignment"; + TestUtil.displayTestTitle(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestNotifications.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + preTestCleanup(AssignmentPolicyEnforcementType.FULL); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + PrismObject jack = getUser(USER_JACK_OID); + AssignmentType assignment = findAssignmentByTargetRequired(jack, ROLE_SUPERUSER_OID); + Long id = assignment.getId(); + executeChanges( + DeltaBuilder.deltaFor(UserType.class, prismContext) + .item(UserType.F_ASSIGNMENT, id, AssignmentType.F_DESCRIPTION) + .replace("hi") + .asObjectDeltaCast(jack.getOid()), null, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess("executeChanges result", result); + PrismObject jackAfter = getUser(USER_JACK_OID); + display("User after change execution", jackAfter); + assertUserJack(jackAfter); + + // Check notifications + display("Notifications", dummyTransport); + + notificationManager.setDisabled(true); + checkDummyTransportMessages("accountPasswordNotifier", 0); + checkDummyTransportMessages("userPasswordNotifier", 0); + checkDummyTransportMessages("simpleAccountNotifier-SUCCESS", 0); + checkDummyTransportMessages("simpleAccountNotifier-FAILURE", 0); + checkDummyTransportMessages("simpleAccountNotifier-ADD-SUCCESS", 0); + checkDummyTransportMessages("simpleAccountNotifier-DELETE-SUCCESS", 0); + checkDummyTransportMessages("simpleUserNotifier", 1); + checkDummyTransportMessages("simpleUserNotifier-ADD", 0); + + assertSteadyResources(); + + String expected = "Notification about user-related operation (status: SUCCESS)\n" + + "\n" + + "User: Jack Sparrow (jack, oid c0c010c0-d34d-b33f-f00d-111111111111)\n" + + "\n" + + "The user record was modified. Modified attributes are:\n" + + " - Assignment["+id+"]/Description:\n" + + " - REPLACE: hi\n" + + "\n" + + "Notes:\n" + + " - Assignment["+id+"]:\n" + + " - Description: hi\n" + + " - Target: Superuser (role) [default]\n" + + "\n" + + "Channel: "; + assertEquals("Wrong message body", expected, dummyTransport.getMessages("dummy:simpleUserNotifier").get(0).getBody()); + } + + @Test + public void test160ModifyUserJackDeleteAssignment() throws Exception { + final String TEST_NAME = "test160ModifyUserJackDeleteAssignment"; + TestUtil.displayTestTitle(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestNotifications.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + preTestCleanup(AssignmentPolicyEnforcementType.FULL); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + PrismObject jack = getUser(USER_JACK_OID); + AssignmentType assignment = findAssignmentByTargetRequired(jack, ROLE_SUPERUSER_OID); + Long id = assignment.getId(); + executeChanges( + DeltaBuilder.deltaFor(UserType.class, prismContext) + .item(UserType.F_ASSIGNMENT) + .delete(new AssignmentType(prismContext).id(id)) + .asObjectDeltaCast(jack.getOid()), null, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess("executeChanges result", result); + + PrismObject jackAfter = getUser(USER_JACK_OID); + display("User after change execution", jackAfter); + assertUserJack(jackAfter); + + // Check notifications + display("Notifications", dummyTransport); + + notificationManager.setDisabled(true); + checkDummyTransportMessages("accountPasswordNotifier", 0); + checkDummyTransportMessages("userPasswordNotifier", 0); + checkDummyTransportMessages("simpleAccountNotifier-SUCCESS", 0); + checkDummyTransportMessages("simpleAccountNotifier-FAILURE", 0); + checkDummyTransportMessages("simpleAccountNotifier-ADD-SUCCESS", 0); + checkDummyTransportMessages("simpleAccountNotifier-DELETE-SUCCESS", 0); + checkDummyTransportMessages("simpleUserNotifier", 1); + checkDummyTransportMessages("simpleUserNotifier-ADD", 0); + + assertSteadyResources(); + + String expected = "Notification about user-related operation (status: SUCCESS)\n" + + "\n" + + "User: Jack Sparrow (jack, oid c0c010c0-d34d-b33f-f00d-111111111111)\n" + + "\n" + + "The user record was modified. Modified attributes are:\n" + + " - Assignment:\n" + + " - DELETE: \n" + + " - Description: hi\n" + + " - Target: Superuser (role) [default]\n" + + "\n" + + "Channel: "; + assertEquals("Wrong message body", expected, dummyTransport.getMessages("dummy:simpleUserNotifier").get(0).getBody()); } @Test diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java index 1648fc35056..66c1556060d 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java @@ -42,6 +42,7 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang.Validate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -100,7 +101,7 @@ public String formatObjectModificationDelta(ObjectDelta ob retval.append(" - "); retval.append(getItemDeltaLabel(itemDelta, objectDefinition)); retval.append(":\n"); - formatItemDeltaContent(retval, itemDelta, hiddenPaths, showOperationalAttributes); + formatItemDeltaContent(retval, itemDelta, objectOld, hiddenPaths, showOperationalAttributes); } explainPaths(retval, toBeDisplayed, objectDefinition, objectOld, objectNew, hiddenPaths, showOperationalAttributes); @@ -158,18 +159,24 @@ private void explainPaths(StringBuilder sb, List deltas, PrismObjectD } } - private void formatItemDeltaContent(StringBuilder sb, ItemDelta itemDelta, List hiddenPaths, boolean showOperationalAttributes) { - formatItemDeltaValues(sb, "ADD", itemDelta.getValuesToAdd(), false, hiddenPaths, showOperationalAttributes); - formatItemDeltaValues(sb, "DELETE", itemDelta.getValuesToDelete(), true, hiddenPaths, showOperationalAttributes); - formatItemDeltaValues(sb, "REPLACE", itemDelta.getValuesToReplace(), false, hiddenPaths, showOperationalAttributes); + private void formatItemDeltaContent(StringBuilder sb, ItemDelta itemDelta, PrismObject objectOld, + List hiddenPaths, boolean showOperationalAttributes) { + formatItemDeltaValues(sb, "ADD", itemDelta.getValuesToAdd(), false, itemDelta.getPath(), objectOld, hiddenPaths, showOperationalAttributes); + formatItemDeltaValues(sb, "DELETE", itemDelta.getValuesToDelete(), true, itemDelta.getPath(), objectOld, hiddenPaths, showOperationalAttributes); + formatItemDeltaValues(sb, "REPLACE", itemDelta.getValuesToReplace(), false, itemDelta.getPath(), objectOld, hiddenPaths, showOperationalAttributes); } - private void formatItemDeltaValues(StringBuilder sb, String type, Collection values, boolean mightBeRemoved, List hiddenPaths, boolean showOperationalAttributes) { + private void formatItemDeltaValues(StringBuilder sb, String type, Collection values, + boolean isDelete, ItemPath path, PrismObject objectOld, + List hiddenPaths, boolean showOperationalAttributes) { if (values != null) { for (PrismValue prismValue : values) { sb.append(" - ").append(type).append(": "); String prefix = " "; - formatPrismValue(sb, prefix, prismValue, mightBeRemoved, hiddenPaths, showOperationalAttributes); + if (isDelete && prismValue instanceof PrismContainerValue) { + prismValue = fixEmptyContainerValue((PrismContainerValue) prismValue, path, objectOld); + } + formatPrismValue(sb, prefix, prismValue, isDelete, hiddenPaths, showOperationalAttributes); if (!(prismValue instanceof PrismContainerValue)) { // container values already end with newline sb.append("\n"); } @@ -177,6 +184,18 @@ private void formatItemDeltaValues(StringBuilder sb, String type, Collection hiddenAttributes, boolean showOperationalAttributes) { Validate.notNull(shadowType, "shadowType is null");