Skip to content

Commit

Permalink
Make password available to notification scripts
Browse files Browse the repository at this point in the history
The password-retrieval method was moved to NotificationFunctions and
now the password can be retrieved from the event via
event.getFocusPassword().

Introducing some other minor changes as well.
  • Loading branch information
mederly committed Sep 3, 2018
1 parent df0e890 commit d4c2067
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 93 deletions.
Expand Up @@ -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");
Expand Down
Expand Up @@ -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;
Expand All @@ -40,4 +41,10 @@ public interface NotificationFunctions {
List<ItemPath> getSynchronizationPaths();

List<ItemPath> 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);

}
Expand Up @@ -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;
}
}
Expand Up @@ -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);
Expand Down
Expand Up @@ -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;
Expand All @@ -57,6 +58,8 @@

import java.util.*;

import static java.util.Collections.singletonList;

/**
* @author mederly
*/
Expand Down Expand Up @@ -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<FocusType> focusPrimaryDelta = (ObjectDelta) modelEvent.getFocusPrimaryDelta();
//noinspection unchecked
ObjectDelta<FocusType> 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<ObjectDelta<FocusType>> 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;
}
}
}
Expand Up @@ -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;
Expand Down Expand Up @@ -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<? extends EventHandlerType> clazz) {
protected void register(Class<? extends EventHandlerType> clazz) {
notificationManager.registerEventHandler(clazz, this);
}

Expand Down Expand Up @@ -199,10 +194,9 @@ protected ExpressionVariables getDefaultVariables(Event event, OperationResult r
ExpressionVariables expressionVariables = new ExpressionVariables();
Map<QName, Object> 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;
}



}
Expand Up @@ -178,12 +178,4 @@ private List<NotificationMessageType> 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;
}

}
Expand Up @@ -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) {
Expand Down
Expand Up @@ -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
*/
Expand All @@ -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;

Expand All @@ -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<FocusType> focusPrimaryDelta = (ObjectDelta) modelEvent.getFocusPrimaryDelta();
//noinspection unchecked
ObjectDelta<FocusType> 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<ObjectDelta<FocusType>> 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
Expand All @@ -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
Expand Down

0 comments on commit d4c2067

Please sign in to comment.