Skip to content

Commit

Permalink
adding support for predefined activation scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
skublik committed Jun 21, 2023
1 parent 174ee09 commit 39cb22c
Show file tree
Hide file tree
Showing 21 changed files with 1,931 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ public abstract class SchemaConstants {
ActivationType.F_VALID_FROM);
public static final ItemPath PATH_ACTIVATION_VALID_TO = ItemPath.create(C_ACTIVATION,
ActivationType.F_VALID_TO);
public static final ItemPath PATH_ACTIVATION_EXISTENCE = ItemPath.create(C_ACTIVATION,
"existence");
public static final ItemPath PATH_ACTIVATION_DISABLE_REASON = ItemPath.create(ShadowType.F_ACTIVATION,
ActivationType.F_DISABLE_REASON);
public static final ItemPath PATH_ACTIVATION_LOCKOUT_STATUS = ItemPath.create(C_ACTIVATION,
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ public abstract class AbstractMappingImpl<V extends PrismValue, D extends ItemDe
/**
* Evaluation of time constraints.
*/
private TimeConstraintsEvaluation timeConstraintsEvaluation;
private MappingTimeConstraintsEvaluation timeConstraintsEvaluation;

/**
* When the mapping evaluation started. Used only if profiling is turned on.
Expand Down Expand Up @@ -1205,7 +1205,7 @@ private boolean computeConditionResult(Collection<PrismPropertyValue<Boolean>> b
private void evaluateTimeConstraint(OperationResult result) throws SchemaException, ObjectNotFoundException,
CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
if (timeConstraintsEvaluation == null) {
timeConstraintsEvaluation = new TimeConstraintsEvaluation(this);
timeConstraintsEvaluation = new MappingTimeConstraintsEvaluation(this);
timeConstraintsEvaluation.evaluate(result);
}
timeConstraintsEvaluation.isTimeConstraintValid();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
/**
* Evaluates mapping time constraints.
*/
class TimeConstraintsEvaluation implements Serializable {
class MappingTimeConstraintsEvaluation implements Serializable {

private static final Trace LOGGER = TraceManager.getTrace(TimeConstraintsEvaluation.class);
private static final Trace LOGGER = TraceManager.getTrace(MappingTimeConstraintsEvaluation.class);

/**
* "Parent" mapping evaluation.
Expand All @@ -52,7 +52,7 @@ class TimeConstraintsEvaluation implements Serializable {
*/
private XMLGregorianCalendar nextRecomputeTime;

TimeConstraintsEvaluation(AbstractMappingImpl<?, ?, ?> m) {
MappingTimeConstraintsEvaluation(AbstractMappingImpl<?, ?, ?> m) {
this.m = m;
}

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright (C) 2010-2023 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.model.impl.lens.projector.mappings.predefinedActivationMapping;

import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.LensProjectionContext;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

import javax.xml.datatype.XMLGregorianCalendar;
import java.util.List;

/**
* This evaluator delayed delete base on duration from configuration {@link DelayedDeleteActivationMappingType}.
* As reference time is used value of attribute activation/disableTimestamp from shadow.
* We should combine with {@link DisableInsteadDeleteEvaluator}.
*/
public class DelayedDeleteEvaluator extends PredefinedActivationMappingEvaluator {

private static final Trace LOGGER = TraceManager.getTrace(DelayedDeleteEvaluator.class);

private TimeConstraintEvaluation timeEvaluation;

public DelayedDeleteEvaluator(ResourceActivationDefinitionType activationDefinitionBean) {
super(activationDefinitionBean);
}

@Override
public void init() {
super.init();
timeEvaluation = new TimeConstraintEvaluation(
ItemPath.create(FocusType.F_ACTIVATION, ActivationType.F_DISABLE_TIMESTAMP),
getActivationDefinitionBean().getDelayedDelete().getDeleteAfter());
}

public <F extends FocusType> boolean defineExistence(
final LensContext<F> context, final LensProjectionContext projCtx) {
return false;
}

@Override
public <F extends FocusType> XMLGregorianCalendar defineTimeForTriggerOfExistence(
LensContext<F> context, LensProjectionContext projCtx, XMLGregorianCalendar now)
throws SchemaException, ConfigurationException {
checkInitialization();

if (timeEvaluation.isTimeConstraintValid() == null) {
timeEvaluation.evaluateFrom(projCtx.getObjectDeltaObject(), now);
}

if (timeEvaluation.isTimeConstraintValid()) {
return null;
}

if (isConditionSatisfied(projCtx)) {
return timeEvaluation.getNextRecomputeTime();
}

return null;
}

@Override
public <F extends FocusType> boolean isConfigured(Task task) {
if (getActivationDefinitionBean().getDelayedDelete() == null) {
LOGGER.trace(
"DelayedDeleteEvaluator: non-exist configuration for delayedDelete in: {}, skipping",
getActivationDefinitionBean());
return false;
}

DelayedDeleteActivationMappingType delayedDelete = getActivationDefinitionBean().getDelayedDelete();
if (!task.canSee(delayedDelete.getLifecycleState())) {
LOGGER.trace("DelayedDeleteEvaluator: not applicable to the execution mode, skipping");
return false;
}
return true;
}

@Override
public <F extends FocusType> boolean isApplicable(
LensContext<F> context, LensProjectionContext projCtx, XMLGregorianCalendar now)
throws SchemaException, ConfigurationException {
checkInitialization();

timeEvaluation.evaluateFrom(projCtx.getObjectDeltaObject(), now);
if (!timeEvaluation.isTimeConstraintValid()) {
LOGGER.trace("DelayedDeleteEvaluator: time constraint isn't valid, skipping");
return false;
}

if (isConditionSatisfied(projCtx)) {
LOGGER.trace(
"DelayedDeleteEvaluator: activation status isn't disabled "
+ "or disable reason isn't mapped or deprovision, skipping");
return false;
}

return true;
}

private boolean isConditionSatisfied(LensProjectionContext projCtx) throws SchemaException, ConfigurationException {
if (!isExpectedValueOfItem(
projCtx.getObjectDeltaObject(),
ItemPath.create(ShadowType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS),
List.of(ActivationStatusType.DISABLED))) {
return false;
}

if (!isExpectedValueOfItem(
projCtx.getObjectDeltaObject(),
ItemPath.create(ShadowType.F_ACTIVATION, ActivationType.F_DISABLE_REASON),
List.of(
SchemaConstants.MODEL_DISABLE_REASON_DEPROVISION,
SchemaConstants.MODEL_DISABLE_REASON_MAPPED))) {
return false;
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (C) 2010-2023 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.model.impl.lens.projector.mappings.predefinedActivationMapping;

import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.LensFocusContext;
import com.evolveum.midpoint.model.impl.lens.LensProjectionContext;
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractPredefinedActivationMappingType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceActivationDefinitionType;

import javax.xml.datatype.XMLGregorianCalendar;

/**
* This evaluator change midpoint default behaviour and disable account.
* Disabling the account instead of deleting is a common requirement.
*/
public class DisableInsteadDeleteEvaluator extends PredefinedActivationMappingEvaluator {

private static final Trace LOGGER = TraceManager.getTrace(DisableInsteadDeleteEvaluator.class);

public DisableInsteadDeleteEvaluator(ResourceActivationDefinitionType activationDefinitionBean) {
super(activationDefinitionBean);
}

public <F extends FocusType> boolean defineExistence(final LensContext<F> context, final LensProjectionContext projCtx) {
LensFocusContext<F> focusContext = context.getFocusContext();
if (focusContext == null) {
LOGGER.trace(
"DisableInsteadDeleteEvaluator: couldn't find focus context, return legal {} for existence",
projCtx.isLegal());
return projCtx.isLegal();
}

if (focusContext.isDelete()) {
LOGGER.trace("DisableInsteadDeleteEvaluator: focus is deleting, return false for existence");
return false;
}
return true;
}

@Override
public <V extends PrismValue, D extends ItemDefinition<?>, F extends FocusType> void defineAdministratorStatus(
LensContext<F> context, LensProjectionContext projCtx) throws SchemaException {
ItemDefinition<?> targetItemDefinition =
projCtx.getObjectDefinition().findItemDefinition(SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS);

//noinspection unchecked
ItemDelta<V, D> targetItemDelta =
(ItemDelta<V, D>) targetItemDefinition.createEmptyDelta(SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS);

V value = (V) PrismContext.get().itemFactory().createPropertyValue(ActivationStatusType.DISABLED);
targetItemDelta.setValuesToReplace(value);

LOGGER.trace("DisableInsteadDeleteEvaluator adds new delta for {}: {}", projCtx, targetItemDelta);
projCtx.swallowToSecondaryDelta(targetItemDelta);
}

@Override
public <F extends FocusType> boolean isConfigured(Task task) {
if (getActivationDefinitionBean().getDisableInsteadDelete() == null) {
LOGGER.trace(
"DisableInsteadDeleteEvaluator: non-exist configuration for disableInsteadDelete in: {}, skipping",
getActivationDefinitionBean());
return false;
}

AbstractPredefinedActivationMappingType disableInsteadDeleteBean = getActivationDefinitionBean().getDisableInsteadDelete();
if (!task.canSee(disableInsteadDeleteBean.getLifecycleState())) {
LOGGER.trace("DisableInsteadDeleteEvaluator: not applicable to the execution mode, skipping");
return false;
}
return true;
}

@Override
public <F extends FocusType> boolean isApplicable(
LensContext<F> context, LensProjectionContext projCtx, XMLGregorianCalendar now) {
LensFocusContext<F> focusContext = context.getFocusContext();
if (focusContext == null) {
LOGGER.trace("DisableInsteadDeleteEvaluator: couldn't find focus context in {}, skipping", context.debugDump());
return false;
}

if (Boolean.TRUE.equals(projCtx.isLegal())) {
LOGGER.trace("DisableInsteadDeleteEvaluator: focus is deleting, skipping");
return false;
}
return true;
}

@Override
protected boolean supportsAdministratorStatus() {
return true;
}
}

0 comments on commit 39cb22c

Please sign in to comment.