diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java index 9bbb65b1010..58e5f65b884 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java @@ -463,6 +463,7 @@ public abstract class SchemaConstants { public static final QName C_EVENT = new QName(NS_C, "event"); public static final QName C_EVENT_HANDLER = new QName(NS_C, "eventHandler"); // TODO: no such element in common-3 - is it OK? public static final QName C_TEXT_FORMATTER = new QName(NS_C, "textFormatter"); + public static final QName C_NOTIFICATION_FUNCTIONS = new QName(NS_C, "notificationFunctions"); public static final QName C_TRANSPORT_NAME = new QName(NS_C, "transportName"); public static final QName C_FROM = new QName(NS_C, "from"); diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationFunctions.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationFunctions.java index ccbe11dc460..a2e3c34c37d 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationFunctions.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationFunctions.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.notifications.api; import com.evolveum.midpoint.notifications.api.events.Event; +import com.evolveum.midpoint.notifications.api.events.ModelEvent; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.path.ItemPath; @@ -40,4 +41,10 @@ public interface NotificationFunctions { List getSynchronizationPaths(); List getAuxiliaryPaths(); + + // TODO: polish this method + // TODO indicate somehow if password was erased from the focus + // We should (probably) return only a value if it has been (successfully) written to the focus. + String getFocusPasswordFromEvent(ModelEvent modelEvent); + } diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/Event.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/Event.java index 83a72fd355d..0a5c502577f 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/Event.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/Event.java @@ -113,4 +113,15 @@ public interface Event extends DebugDumpable, ShortDumpable { * A better is to define handlers in system configuration. */ EventHandlerType getAdHocHandler(); + + /** + * Returns plaintext focus password value, if known. + * Beware: might not always work correctly: + * 1. If the change execution was only partially successful, the value returned might or might not be stored in the repo + * 2. If the password was changed to null, the 'null' value is returned. So the caller cannot distinguish it from "no change" + * situation. A new method for this would be needed. + */ + default String getFocusPassword() { + return null; + } } diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/ModelEvent.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/ModelEvent.java index 566e29de140..4f6cdbefd03 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/ModelEvent.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/ModelEvent.java @@ -221,6 +221,10 @@ public String getContentAsFormattedList(boolean showSynchronizationItems, boolea return getNotificationFunctions().getContentAsFormattedList(this, showSynchronizationItems, showAuxiliaryAttributes); } + public String getFocusPassword() { + return getNotificationFunctions().getFocusPasswordFromEvent(this); + } + @Override public String debugDump(int indent) { StringBuilder sb = DebugUtil.createTitleStringBuilderLn(this.getClass(), indent); diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationFunctionsImpl.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationFunctionsImpl.java index ccf3fd1a1b9..2a51200e722 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationFunctionsImpl.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationFunctionsImpl.java @@ -40,6 +40,7 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.schema.util.ShadowUtil; +import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.CommonException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; @@ -57,6 +58,8 @@ import java.util.*; +import static java.util.Collections.singletonList; + /** * @author mederly */ @@ -377,4 +380,54 @@ private String getResourceObjectModifiedAttributesAsFormattedList(ResourceObject return rv.toString(); } + // TODO: polish this method + // We should (probably) return only a value if it has been (successfully) written to the focus. + @Override + public String getFocusPasswordFromEvent(ModelEvent modelEvent) { + if (modelEvent.getFocusDeltas().isEmpty()) { + LOGGER.trace("getFocusPasswordFromEvent: No user deltas in event"); + return null; + } + String password = getPasswordFromDeltas(modelEvent.getFocusDeltas()); + if (password != null) { + LOGGER.trace("getFocusPasswordFromEvent: Found password in user executed delta(s)"); + return password; + } + // in executed deltas + + //noinspection unchecked + ObjectDelta focusPrimaryDelta = (ObjectDelta) modelEvent.getFocusPrimaryDelta(); + //noinspection unchecked + ObjectDelta focusSecondaryDelta = (ObjectDelta) modelEvent.getFocusSecondaryDelta(); + if (focusPrimaryDelta == null && focusSecondaryDelta == null) { + LOGGER.trace("getFocusPasswordFromEvent: No password in executed delta(s) and no primary/secondary deltas"); + return null; + } + if (focusPrimaryDelta != null) { + password = getPasswordFromDeltas(singletonList(focusPrimaryDelta)); + if (password != null) { + LOGGER.trace("getFocusPasswordFromEvent: Found password in user primary delta, continuing"); + return password; + } + } + if (focusSecondaryDelta != null) { + password = getPasswordFromDeltas(singletonList(focusSecondaryDelta)); + if (password != null) { + LOGGER.trace("getFocusPasswordFromEvent: Found password in user secondary delta(s)"); + return password; + } + } + LOGGER.trace("getFocusPasswordFromEvent: No password in executed delta(s) nor in primary/secondary deltas"); + return null; + } + + private String getPasswordFromDeltas(List> deltas) { + try { + //noinspection unchecked + return midpointFunctions.getPlaintextUserPasswordFromDeltas((List) deltas); + } catch (EncryptionException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't decrypt password from user deltas: {}", e, DebugUtil.debugDump(deltas)); + return null; + } + } } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java index 30ecac73e3e..bd8dc90e7fb 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.notifications.impl.handlers; +import com.evolveum.midpoint.notifications.impl.formatters.TextFormatter; import com.evolveum.midpoint.repo.common.expression.Expression; import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; @@ -64,19 +65,13 @@ public abstract class BaseHandler implements EventHandler { private static final Trace LOGGER = TraceManager.getTrace(BaseHandler.class); - @Autowired - protected NotificationManagerImpl notificationManager; + @Autowired protected NotificationManagerImpl notificationManager; + @Autowired protected NotificationFunctionsImpl notificationsUtil; + @Autowired protected PrismContext prismContext; + @Autowired protected ExpressionFactory expressionFactory; + @Autowired protected TextFormatter textFormatter; - @Autowired - protected NotificationFunctionsImpl notificationsUtil; - - @Autowired - protected PrismContext prismContext; - - @Autowired - protected ExpressionFactory expressionFactory; - - protected void register(Class clazz) { + protected void register(Class clazz) { notificationManager.registerEventHandler(clazz, this); } @@ -199,10 +194,9 @@ protected ExpressionVariables getDefaultVariables(Event event, OperationResult r ExpressionVariables expressionVariables = new ExpressionVariables(); Map variables = new HashMap<>(); event.createExpressionVariables(variables, result); + variables.put(SchemaConstants.C_TEXT_FORMATTER, textFormatter); + variables.put(SchemaConstants.C_NOTIFICATION_FUNCTIONS, notificationsUtil); expressionVariables.addVariableDefinitions(variables); return expressionVariables; } - - - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/CustomNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/CustomNotifier.java index b46f6000fb8..97bac7709dd 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/CustomNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/CustomNotifier.java @@ -178,12 +178,4 @@ private List evaluateExpression(ExpressionType expressi .evaluateExpressionInContext(expression, params, task, result); return exprResult.getZeroSet().stream().map(PrismPropertyValue::getValue).collect(Collectors.toList()); } - - @Override - protected ExpressionVariables getDefaultVariables(Event event, OperationResult result) { - ExpressionVariables variables = super.getDefaultVariables(event, result); - variables.addVariableDefinition(SchemaConstants.C_TEXT_FORMATTER, textFormatter); - return variables; - } - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/GeneralNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/GeneralNotifier.java index e7047f2daf9..c61c4766ff1 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/GeneralNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/GeneralNotifier.java @@ -385,13 +385,6 @@ private String formatPath(ItemDelta itemDelta) { return sb.toString(); } - @Override - protected ExpressionVariables getDefaultVariables(Event event, OperationResult result) { - ExpressionVariables variables = super.getDefaultVariables(event, result); - variables.addVariableDefinition(SchemaConstants.C_TEXT_FORMATTER, textFormatter); - return variables; - } - public String formatRequester(Event event, OperationResult result) { SimpleObjectRef requesterRef = event.getRequester(); if (requesterRef == null) { diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java index cd88e326ac3..210fd4dadf7 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java @@ -16,32 +16,21 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import com.evolveum.midpoint.model.api.expr.MidpointFunctions; import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.notifications.api.events.ModelEvent; import com.evolveum.midpoint.notifications.impl.NotificationFunctionsImpl; -import com.evolveum.midpoint.prism.crypto.EncryptionException; -import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.DebugUtil; -import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserPasswordNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; -import java.util.List; - -import static java.util.Collections.singletonList; - /** * @author mederly */ @@ -50,9 +39,6 @@ public class UserPasswordNotifier extends GeneralNotifier { private static final Trace LOGGER = TraceManager.getTrace(UserPasswordNotifier.class); - @Autowired - private MidpointFunctions midpointFunctions; - @Autowired private NotificationFunctionsImpl notificationsUtil; @@ -71,60 +57,13 @@ protected boolean quickCheckApplicability(Event event, GeneralNotifierType gener } } - @Override protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { if (!event.isAlsoSuccess()) { // TODO LOGGER.trace("Operation was not successful, exiting."); return false; } - return getPasswordFromEvent((ModelEvent) event) != null; // logging is done in the called method - } - - private String getPasswordFromEvent(ModelEvent modelEvent) { - if (modelEvent.getFocusDeltas().isEmpty()) { - LOGGER.trace("No user deltas in event, exiting."); - return null; - } - String password = getPasswordFromDeltas(modelEvent.getFocusDeltas()); - if (password != null) { - LOGGER.trace("Found password in user executed delta(s), continuing."); - return password; - } - //noinspection unchecked - ObjectDelta focusPrimaryDelta = (ObjectDelta) modelEvent.getFocusPrimaryDelta(); - //noinspection unchecked - ObjectDelta focusSecondaryDelta = (ObjectDelta) modelEvent.getFocusSecondaryDelta(); - if (focusPrimaryDelta == null && focusSecondaryDelta == null) { - LOGGER.trace("No password in executed delta(s) and no primary/secondary deltas, exiting."); - return null; - } - if (focusPrimaryDelta != null) { - password = getPasswordFromDeltas(singletonList(focusPrimaryDelta)); - if (password != null) { - LOGGER.trace("Found password in user primary delta, continuing."); - return password; - } - } - if (focusSecondaryDelta != null) { - password = getPasswordFromDeltas(singletonList(focusSecondaryDelta)); - if (password != null) { - LOGGER.trace("Found password in user secondary delta(s), continuing."); - return password; - } - } - LOGGER.trace("No password in executed delta(s) nor in primary/secondary deltas, exiting."); - return null; - } - - private String getPasswordFromDeltas(List> deltas) { - try { - //noinspection unchecked - return midpointFunctions.getPlaintextUserPasswordFromDeltas((List) deltas); - } catch (EncryptionException e) { - LoggingUtils.logException(LOGGER, "Couldn't decrypt password from user deltas: {}", e, DebugUtil.debugDump(deltas)); - return null; - } + return event.getFocusPassword() != null; // logging is done in the called method } @Override @@ -135,7 +74,7 @@ protected String getSubject(Event event, GeneralNotifierType generalNotifierType @Override protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { return "Password for user " + notificationsUtil.getObjectType(event.getRequestee(), false, result).getName() - + " is: " + getPasswordFromEvent((ModelEvent) event); + + " is: " + event.getFocusPassword(); } @Override