diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.html index 11e0d9c7500..91010e8ae0e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.html @@ -35,7 +35,7 @@ -
+
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.java index 3d9ad2d9347..81132c31efa 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.java @@ -161,10 +161,11 @@ protected void onError(AjaxRequestTarget target, RuntimeException e) { } }); + feedback.setFilter(new ComponentFeedbackMessageFilter(inputPanel.getValidatableComponent())); + } else { + feedback.setFilter(new ComponentFeedbackMessageFilter(component)); } - feedback.setFilter(new ComponentFeedbackMessageFilter(component)); - if (component instanceof InputPanel) { InputPanel inputPanel = (InputPanel) component; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/message/FeedbackAlerts.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/message/FeedbackAlerts.html index 56fe2ad5846..aab2db41e60 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/message/FeedbackAlerts.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/message/FeedbackAlerts.html @@ -16,7 +16,7 @@ -
+
diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/ActivationComputer.java b/infra/common/src/main/java/com/evolveum/midpoint/common/ActivationComputer.java index ab1d32711a5..0e28eb59af3 100644 --- a/infra/common/src/main/java/com/evolveum/midpoint/common/ActivationComputer.java +++ b/infra/common/src/main/java/com/evolveum/midpoint/common/ActivationComputer.java @@ -90,15 +90,13 @@ public TimeIntervalStatusType getValidityStatus(ActivationType activationType, X XMLGregorianCalendar validTo = activationType.getValidTo(); if (validFrom == null && validTo == null) { return null; + } else if (validTo != null && referenceTime.compare(validTo) == DatatypeConstants.GREATER) { + return TimeIntervalStatusType.AFTER; + } else if (validFrom != null && referenceTime.compare(validFrom) == DatatypeConstants.LESSER) { + return TimeIntervalStatusType.BEFORE; + } else { + return TimeIntervalStatusType.IN; } - TimeIntervalStatusType status = TimeIntervalStatusType.IN; - if (validFrom != null && (referenceTime == null || referenceTime.compare(validFrom) == DatatypeConstants.LESSER)) { - status = TimeIntervalStatusType.BEFORE; - } - if (validTo != null && referenceTime.compare(validTo) == DatatypeConstants.GREATER) { - status = TimeIntervalStatusType.AFTER; - } - return status; } public void computeEffective(String lifecycleStatus, ActivationType activationType, LifecycleStateModelType stateModel) { diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ApprovalContextUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ApprovalContextUtil.java index c354ff6f005..54bac8585f7 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ApprovalContextUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ApprovalContextUtil.java @@ -249,10 +249,6 @@ public static ApprovalStageDefinitionType getStageDefinition(ApprovalContextType } } - public static List getStages(ApprovalSchemaType approvalSchema) { - return !approvalSchema.getStage().isEmpty() ? approvalSchema.getStage() : null; - } - // we must be strict here; in case of suspicion, throw an exception @SuppressWarnings("unchecked") public static List getEventsForCurrentStage(@NotNull CaseType aCase, @NotNull Class clazz) { @@ -328,7 +324,7 @@ public static void normalizeStages(ApprovalSchemaType schema) { @NotNull private static List getSortedStages(ApprovalSchemaType schema) { - List stages = new ArrayList<>(getStages(schema)); + List stages = new ArrayList<>(schema.getStage()); stages.sort(Comparator.comparing(stage -> getNumber(stage), Comparator.nullsLast(Comparator.naturalOrder()))); return stages; } diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-case-management-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-case-management-3.xsd index 5b1d4306ba5..4cce8e38bcf 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-case-management-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-case-management-3.xsd @@ -168,10 +168,13 @@ Reference to the task holding workflow context for wf-related cases. - EXPERIMENTAL. Probably will be removed. + DEPRECATED. Not used any more. The relation is defined the other way: + task.objectRef points to this case. tns:TaskType + true + 4.0.3 diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/complex/TestPolicyDrivenRoleLifecycle.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/complex/TestPolicyDrivenRoleLifecycle.java index ac8e1b27d4b..01c07122bc4 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/complex/TestPolicyDrivenRoleLifecycle.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/complex/TestPolicyDrivenRoleLifecycle.java @@ -47,8 +47,6 @@ /** * A complex policy-drive role lifecycle scenario (see https://wiki.evolveum.com/display/midPoint/Sample+scenario). - * - * @author mederly */ @ContextConfiguration(locations = {"classpath:ctx-certification-test-main.xml"}) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java index 1d5d9c15fb5..60d5ae5a168 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/mapping/MappingImpl.java @@ -636,6 +636,9 @@ private void addToMinusIfNecessary(V originalValue) { @SuppressWarnings("unused") // todo is this externally used? public boolean isSatisfyCondition() { + if (conditionOutputTriple == null) { + return true; + } boolean conditionOutputOld = computeConditionResult(conditionOutputTriple.getNonPositiveValues()); boolean conditionResultOld = conditionOutputOld && conditionMaskOld; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java index 720797d9962..0893306a5fc 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java @@ -223,7 +223,7 @@ private EvaluationContext(@NotNull EvaluatedAssignmentImpl evalAssignment, */ public EvaluatedAssignmentImpl evaluate( ItemDeltaItem,PrismContainerDefinition> assignmentIdi, - PlusMinusZero primaryAssignmentMode, boolean evaluateOld, ObjectType source, String sourceDescription, boolean forcedAssignment, Task task, OperationResult parentResult) + PlusMinusZero primaryAssignmentMode, boolean evaluateOld, AssignmentHolderType source, String sourceDescription, boolean forcedAssignment, Task task, OperationResult parentResult) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, PolicyViolationException, SecurityViolationException, ConfigurationException, CommunicationException { OperationResult result = parentResult.subresult(OP_EVALUATE) .setMinor() @@ -487,8 +487,12 @@ private boolean evaluateSegmentContent(AssignmentPathSegm AssignmentType assignmentType = getAssignmentType(segment, ctx); - boolean isAssignmentValid = LensUtil.isAssignmentValid(focusOdo.getNewObject().asObjectable(), assignmentType, - now, activationComputer, focusStateModel); + // Assignment validity is checked with respect to the assignment source, not to the focus object. + // So, if (e.g.) focus is in "draft" state, only validity of direct assignments should be influenced by this fact. + // Other assignments (e.g. from roles to metaroles) should be considered valid, provided these roles are + // in active lifecycle states. See also MID-6114. + AssignmentHolderType source = segment.isMatchingOrder() ? focusOdo.getNewObject().asObjectable() : segment.getSource(); + boolean isAssignmentValid = LensUtil.isAssignmentValid(source, assignmentType, now, activationComputer, focusStateModel); if (isAssignmentValid || segment.isValidityOverride()) { // Note: validityOverride is currently the same as "isDirectAssignment" - which is very probably OK. // Direct assignments are visited even if they are not valid (i.e. effectively disabled). @@ -508,7 +512,7 @@ private boolean evaluateSegmentContent(AssignmentPathSegm } } } - if (assignmentType.getPolicyRule() != null && !loginMode) { + if (!loginMode && assignmentType.getPolicyRule() != null) { // Here we ignore "reallyValid". It is OK, because reallyValid can be false here only when // evaluating direct assignments; and invalid ones are marked as such via EvaluatedAssignment.isValid. // TODO is it ok? @@ -986,7 +990,7 @@ private void evaluateAssignment(AssignmentPathSegmentImpl segment, PlusMinusZero } private void evaluateInducement(AssignmentPathSegmentImpl segment, PlusMinusZero mode, boolean isValid, EvaluationContext ctx, - AssignmentHolderType targetType, AssignmentType inducement, OperationResult result) + AssignmentHolderType target, AssignmentType inducement, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, PolicyViolationException, SecurityViolationException, ConfigurationException, CommunicationException { ObjectType orderOneObject = getOrderOneObject(segment); @@ -994,7 +998,7 @@ private void evaluateInducement(AssignmentPathSegmentImpl segment, PlusMinusZero if (!isInducementApplicableToFocusType(inducement.getFocusType())) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Skipping application of inducement {} because the focusType does not match (specified: {}, actual: {})", - FocusTypeUtil.dumpAssignment(inducement), inducement.getFocusType(), targetType.getClass().getSimpleName()); + FocusTypeUtil.dumpAssignment(inducement), inducement.getFocusType(), target.getClass().getSimpleName()); } return; } @@ -1004,8 +1008,8 @@ private void evaluateInducement(AssignmentPathSegmentImpl segment, PlusMinusZero } return; } - String subSourceDescription = targetType+" in "+segment.sourceDescription; - AssignmentPathSegmentImpl nextSegment = new AssignmentPathSegmentImpl(targetType, subSourceDescription, inducement, false, relationRegistry, prismContext); + String subSourceDescription = target+" in "+segment.sourceDescription; + AssignmentPathSegmentImpl nextSegment = new AssignmentPathSegmentImpl(target, subSourceDescription, inducement, false, relationRegistry, prismContext); // note that 'old' and 'new' values for assignment in nextSegment are the same boolean nextIsMatchingOrder = AssignmentPathSegmentImpl.computeMatchingOrder( segment.getEvaluationOrder(), nextSegment.getAssignmentNew()); @@ -1031,7 +1035,7 @@ private void evaluateInducement(AssignmentPathSegmentImpl segment, PlusMinusZero // processMembership attribute to false for these inducements. if (LOGGER.isTraceEnabled()) { LOGGER.trace("orig EO({}): evaluate {} inducement({}) {}; new EO({})", - segment.getEvaluationOrder().shortDump(), targetType, FocusTypeUtil.dumpInducementConstraints(inducement), + segment.getEvaluationOrder().shortDump(), target, FocusTypeUtil.dumpInducementConstraints(inducement), FocusTypeUtil.dumpAssignment(inducement), nextEvaluationOrderHolder.getValue().shortDump()); } assert !ctx.assignmentPath.isEmpty(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPathSegmentImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPathSegmentImpl.java index 0d1c5eba458..69ed81a6b72 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPathSegmentImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPathSegmentImpl.java @@ -26,8 +26,6 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import net.sf.ehcache.store.disk.ods.AATreeSet; - import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -53,7 +51,7 @@ public class AssignmentPathSegmentImpl implements AssignmentPathSegment { // "assignment path segment" information - final ObjectType source; // we avoid "getter" notation for some final fields to simplify client code + final AssignmentHolderType source; // we avoid "getter" notation for some final fields to simplify client code private final ItemDeltaItem,PrismContainerDefinition> assignmentIdi; private final boolean isAssignment; // false means inducement private QName relation; @@ -249,7 +247,7 @@ public class AssignmentPathSegmentImpl implements AssignmentPathSegment { * is like this: count the number of times the evaluation order for target reached ZERO level. First encounter with * that level is on "this target". And we assume that each subsequent marks a target that is among "others". * - * @see AssignmentEvaluator#appliesDirectly + * See AssignmentEvaluator.appliesDirectly */ private Boolean isMatchingOrder = null; private EvaluationOrder evaluationOrder; @@ -262,14 +260,14 @@ public class AssignmentPathSegmentImpl implements AssignmentPathSegment { private boolean evaluatedForOld; - AssignmentPathSegmentImpl(ObjectType source, String sourceDescription, + AssignmentPathSegmentImpl(AssignmentHolderType source, String sourceDescription, ItemDeltaItem, PrismContainerDefinition> assignmentIdi, boolean isAssignment, boolean evaluatedForOld, @NotNull RelationRegistry relationRegistry, @NotNull PrismContext prismContext) { this.source = source; this.sourceDescription = sourceDescription; if (assignmentIdi.getDefinition() == null) { - throw new IllegalArgumentException("Attept to set segment assignment IDI withough a definition"); + throw new IllegalArgumentException("Attempt to set segment assignment IDI without a definition"); } this.assignmentIdi = assignmentIdi; this.isAssignment = isAssignment; @@ -278,7 +276,7 @@ public class AssignmentPathSegmentImpl implements AssignmentPathSegment { this.prismContext = prismContext; } - public AssignmentPathSegmentImpl(ObjectType source, String sourceDescription, AssignmentType assignment, boolean isAssignment, + public AssignmentPathSegmentImpl(AssignmentHolderType source, String sourceDescription, AssignmentType assignment, boolean isAssignment, RelationRegistry relationRegistry, PrismContext prismContext) { this(source, sourceDescription, createAssignmentIdi(assignment), isAssignment, false, relationRegistry, prismContext); } @@ -286,6 +284,7 @@ public AssignmentPathSegmentImpl(ObjectType source, String sourceDescription, As private static ItemDeltaItem, PrismContainerDefinition> createAssignmentIdi( AssignmentType assignment) { try { + //noinspection unchecked,rawtypes return new ItemDeltaItem<>(LensUtil.createAssignmentSingleValueContainer(assignment), assignment.asPrismContainerValue().getDefinition()); } catch (SchemaException e) { // should not really occur! @@ -344,7 +343,7 @@ public void setTarget(ObjectType target) { } @Override - public ObjectType getSource() { + public AssignmentHolderType getSource() { return source; } @@ -501,6 +500,7 @@ public int hashCode() { return result; } + @SuppressWarnings("RedundantIfStatement") @Override public boolean equals(Object obj) { if (this == obj) @@ -649,6 +649,7 @@ public boolean matches(@NotNull List orderConstraints) { // preliminary implementation; use only to compare segments in paths (pointing to the same target OID) // that are to be checked for equivalency + @SuppressWarnings("SimplifiableIfStatement") @Override public boolean equivalent(AssignmentPathSegment otherSegment) { if (!prismContext.relationsEquivalent(relation, otherSegment.getRelation())) { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java index e3b771b074d..3953f057bd4 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java @@ -546,22 +546,20 @@ public static boolean evaluateIterationCondition(LensCont /** * Used for assignments and similar objects that do not have separate lifecycle. */ - public static boolean isAssignmentValid(AssignmentHolderType focus, AssignmentType assignmentType, XMLGregorianCalendar now, + public static boolean isAssignmentValid(AssignmentHolderType focus, AssignmentType assignment, XMLGregorianCalendar now, ActivationComputer activationComputer, LifecycleStateModelType focusStateModel) { - ObjectReferenceType targetRef = assignmentType.getTargetRef(); - if (targetRef != null) { - if (QNameUtil.match(ArchetypeType.COMPLEX_TYPE, targetRef.getType())) { - // Archetype assignments are always valid, even in non-valid lifecycle states. - // The object cannot lose its (arche)type. - return true; - } + ObjectReferenceType targetRef = assignment.getTargetRef(); + if (targetRef != null && QNameUtil.match(ArchetypeType.COMPLEX_TYPE, targetRef.getType())) { + // Archetype assignments are always valid, even in non-valid lifecycle states. + // The object cannot lose its (arche)type. + return true; } String focusLifecycleState = focus.getLifecycleState(); if (!activationComputer.lifecycleHasActiveAssignments(focusLifecycleState, focusStateModel)) { return false; } - return isValid(assignmentType.getLifecycleState(), assignmentType.getActivation(), now, activationComputer, focusStateModel); + return isValid(assignment.getLifecycleState(), assignment.getActivation(), now, activationComputer, focusStateModel); } public static Collection getForcedAssignments(LifecycleStateModelType lifecycleModel, String targetLifecycle, diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentProcessor.java index 74621344167..52df941d683 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentProcessor.java @@ -194,7 +194,7 @@ private void processAssig // Initializing assignment evaluator. This will be used later to process all the assignments including the nested // assignments (roles). AssignmentEvaluator assignmentEvaluator = createAssignmentEvaluator(context, now); - ObjectType source = determineSource(focusContext); + AssignmentHolderType source = determineSource(focusContext); AssignmentTripleEvaluator assignmentTripleEvaluator = new AssignmentTripleEvaluator<>(); assignmentTripleEvaluator.setActivationComputer(activationComputer); @@ -595,9 +595,9 @@ private void checkAssignmentDeltaSanity(LensCon } } - private ObjectType determineSource(LensFocusContext focusContext) + private AssignmentHolderType determineSource(LensFocusContext focusContext) throws SchemaException { - ObjectDelta delta = focusContext.getWaveDelta(focusContext.getLensContext().getExecutionWave()); + ObjectDelta delta = focusContext.getWaveDelta(focusContext.getLensContext().getExecutionWave()); if (delta != null && !delta.isEmpty()) { return focusContext.getObjectNew().asObjectable(); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java index d6f3d2f0f7e..0b86acd9a79 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java @@ -63,7 +63,7 @@ public class AssignmentTripleEvaluator { private static final String OP_EVALUATE_ASSIGNMENT = AssignmentTripleEvaluator.class.getName()+".evaluateAssignment"; private LensContext context; - private ObjectType source; + private AssignmentHolderType source; private AssignmentEvaluator assignmentEvaluator; private ActivationComputer activationComputer; private PrismContext prismContext; @@ -87,11 +87,11 @@ public void setContext(LensContext context) { } } - public ObjectType getSource() { + public AssignmentHolderType getSource() { return source; } - public void setSource(ObjectType source) { + public void setSource(AssignmentHolderType source) { this.source = source; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/mappings/MappingEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/mappings/MappingEvaluator.java index 9169347f443..0ee0c172d6c 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/mappings/MappingEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/mappings/MappingEvaluator.java @@ -488,7 +488,7 @@ public mapping: mappings) { XMLGregorianCalendar mappingNextRecomputeTime = mapping.getNextRecomputeTime(); if (mappingNextRecomputeTime != null) { - if (nextRecomputeTime == null || nextRecomputeTime.compare(mappingNextRecomputeTime) == DatatypeConstants.GREATER) { + if (mapping.isSatisfyCondition() && (nextRecomputeTime == null || nextRecomputeTime.compare(mappingNextRecomputeTime) == DatatypeConstants.GREATER)) { nextRecomputeTime = mappingNextRecomputeTime; // TODO: maybe better description? But consider storage requirements. We do not want to store too much. triggerOriginDescription = mapping.getIdentifier(); diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/common/StageComputeHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/common/StageComputeHelper.java index 3cfb9053c54..d32ba892c8b 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/common/StageComputeHelper.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/common/StageComputeHelper.java @@ -136,7 +136,7 @@ public ComputationResult computeStageApprovers(ApprovalStageDefinitionType stage return variables; }; - if (rv.predeterminedOutcome == null && stageDef.getAutomaticallyCompleted() != null) { + if (stageDef.getAutomaticallyCompleted() != null) { try { expressionVariables = enhancedVariablesProvider.get(); String outcome = evaluateAutoCompleteExpression(stageDef, expressionVariables, opTask, opResult); diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java index 701575819a9..8336aebc3e8 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java @@ -28,7 +28,6 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.CaseTypeUtil; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; -import com.evolveum.midpoint.schema.util.ApprovalContextUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskExecutionStatus; import com.evolveum.midpoint.task.api.TaskManager; @@ -196,7 +195,7 @@ public boolean isEmpty(PcpStartInstruction instruction, if (actx == null) { return true; } - List stages = ApprovalContextUtil.getStages(actx.getApprovalSchema()); + List stages = actx.getApprovalSchema().getStage(); // first pass: if there is any stage that is obviously not skippable, let's return false without checking the expressions for (ApprovalStageDefinitionType stage : stages) { if (stage.getAutomaticallyCompleted() == null) { @@ -241,6 +240,7 @@ private List gatherStartInstructions logAspectResult(aspect, instructions, changesBeingDecomposed); startProcessInstructions.addAll(instructions); } + result.addParam("instructionsCount", startProcessInstructions.size()); return startProcessInstructions; } catch (Throwable t) { result.recordFatalError(t); diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/AssignmentPolicyAspectPart.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/AssignmentPolicyAspectPart.java index 7c8d98dafc6..99ab76588f1 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/AssignmentPolicyAspectPart.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/AssignmentPolicyAspectPart.java @@ -68,8 +68,6 @@ /** * Part of PolicyRuleBasedAspect related to assignments. - * - * @author mederly */ @Component public class AssignmentPolicyAspectPart { diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/PolicyRuleBasedAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/PolicyRuleBasedAspect.java index 2a43a6b5642..7338fea1a62 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/PolicyRuleBasedAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/PolicyRuleBasedAspect.java @@ -95,6 +95,7 @@ public List getStartInstructions(@No .extractAssignmentBasedInstructions(objectTreeDeltas, requester, instructions, ctx, result); objectPolicyAspectPart.extractObjectBasedInstructions(objectTreeDeltas, requester, instructions, ctx, result); } + result.addParam("instructionsCount", instructions.size()); return instructions; } catch (Throwable t) { result.recordFatalError(t); diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/AbstractTestAssignmentApproval.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/AbstractTestAssignmentApproval.java index 049fea6b633..3eae1d25716 100644 --- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/AbstractTestAssignmentApproval.java +++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/AbstractTestAssignmentApproval.java @@ -6,6 +6,26 @@ */ package com.evolveum.midpoint.wf.impl.assignments; +import static java.util.Collections.singletonList; +import static org.testng.AssertJUnit.assertEquals; + +import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createAssignmentTo; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.test.TestResource; + +import org.jetbrains.annotations.NotNull; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Test; + import com.evolveum.midpoint.model.api.context.ModelState; import com.evolveum.midpoint.model.api.util.DeputyUtils; import com.evolveum.midpoint.model.impl.lens.LensContext; @@ -28,28 +48,12 @@ import com.evolveum.midpoint.wf.impl.ExpectedWorkItem; import com.evolveum.midpoint.wf.impl.WorkflowResult; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.annotation.DirtiesContext.ClassMode; -import org.springframework.test.context.ContextConfiguration; -import org.testng.annotations.Test; - -import javax.xml.namespace.QName; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createAssignmentTo; -import static org.testng.AssertJUnit.assertEquals; /** * Testing approvals of role assignments: create/delete assignment, potentially for more roles and combined with other operations. * Testing also with deputies specified. * * Subclasses provide specializations regarding ways how rules and/or approvers are attached to roles. - * - * @author mederly */ @ContextConfiguration(locations = {"classpath:ctx-workflow-test-main.xml"}) @DirtiesContext(classMode = ClassMode.AFTER_CLASS) @@ -61,73 +65,67 @@ public abstract class AbstractTestAssignmentApproval extends AbstractWfTestPolic private static final File METAROLE_DEFAULT_FILE = new File(TEST_RESOURCE_DIR, "metarole-default.xml"); - private static final File ROLE_ROLE1_FILE = new File(TEST_RESOURCE_DIR, "role-role1.xml"); - private static final File ROLE_ROLE1B_FILE = new File(TEST_RESOURCE_DIR, "role-role1b.xml"); - private static final File ROLE_ROLE2_FILE = new File(TEST_RESOURCE_DIR, "role-role2.xml"); - private static final File ROLE_ROLE2B_FILE = new File(TEST_RESOURCE_DIR, "role-role2b.xml"); - private static final File ROLE_ROLE3_FILE = new File(TEST_RESOURCE_DIR, "role-role3.xml"); - private static final File ROLE_ROLE3B_FILE = new File(TEST_RESOURCE_DIR, "role-role3b.xml"); - private static final File ROLE_ROLE4_FILE = new File(TEST_RESOURCE_DIR, "role-role4.xml"); - private static final File ROLE_ROLE4B_FILE = new File(TEST_RESOURCE_DIR, "role-role4b.xml"); - private static final File ROLE_ROLE10_FILE = new File(TEST_RESOURCE_DIR, "role-role10.xml"); - private static final File ROLE_ROLE10B_FILE = new File(TEST_RESOURCE_DIR, "role-role10b.xml"); - private static final File ROLE_ROLE15_FILE = new File(TEST_RESOURCE_DIR, "role-role15.xml"); - - private static final File USER_JACK_DEPUTY_FILE = new File(TEST_RESOURCE_DIR, "user-jack-deputy.xml"); // delegation is created only when needed - private static final File USER_LEAD1_FILE = new File(TEST_RESOURCE_DIR, "user-lead1.xml"); - private static final File USER_LEAD1_DEPUTY_1_FILE = new File(TEST_RESOURCE_DIR, "user-lead1-deputy1.xml"); - private static final File USER_LEAD1_DEPUTY_2_FILE = new File(TEST_RESOURCE_DIR, "user-lead1-deputy2.xml"); - private static final File USER_LEAD2_FILE = new File(TEST_RESOURCE_DIR, "user-lead2.xml"); - private static final File USER_LEAD3_FILE = new File(TEST_RESOURCE_DIR, "user-lead3.xml"); - private static final File USER_LEAD10_FILE = new File(TEST_RESOURCE_DIR, "user-lead10.xml"); - private static final File USER_LEAD15_FILE = new File(TEST_RESOURCE_DIR, "user-lead15.xml"); - - String roleRole1Oid; - String roleRole1bOid; - String roleRole2Oid; - String roleRole2bOid; - String roleRole3Oid; - String roleRole3bOid; - String roleRole4Oid; - String roleRole4bOid; - String roleRole10Oid; - String roleRole10bOid; - String roleRole15Oid; - - private String userJackDeputyOid; - private String userLead1Oid; - private String userLead1Deputy1Oid; - private String userLead1Deputy2Oid; - private String userLead2Oid; - private String userLead3Oid; + // Roles 1-3 are approved using implicit or global policy rule -- they have no metarole causing approval + // The approval is triggered because Lead 1-3 are set as approvers for these roles. + // There is no approver for role 4 so it does not undertake aby approval. + static final TestResource ROLE1 = new TestResource(TEST_RESOURCE_DIR, "role-role1.xml", "00000001-d34d-b33f-f00d-000000000001"); + static final TestResource ROLE2 = new TestResource(TEST_RESOURCE_DIR, "role-role2.xml", "00000001-d34d-b33f-f00d-000000000002"); + static final TestResource ROLE3 = new TestResource(TEST_RESOURCE_DIR, "role-role3.xml", "00000001-d34d-b33f-f00d-000000000003"); + static final TestResource ROLE4 = new TestResource(TEST_RESOURCE_DIR, "role-role4.xml", "00000001-d34d-b33f-f00d-000000000004"); + + // Roles 1b-3b are approved using metarole holding a policy rule that engages users with "special-approver" relation. + // The approval is triggered because Lead 1-3 are set as "special approvers" for these roles. + // There is no approver for role 4 so it does not undertake aby approval. + static final TestResource ROLE1B = new TestResource(TEST_RESOURCE_DIR, "role-role1b.xml", "00000001-d34d-b33f-f00d-00000000001b"); + static final TestResource ROLE2B = new TestResource(TEST_RESOURCE_DIR, "role-role2b.xml", "00000001-d34d-b33f-f00d-00000000002b"); + static final TestResource ROLE3B = new TestResource(TEST_RESOURCE_DIR, "role-role3b.xml", "00000001-d34d-b33f-f00d-00000000003b"); + static final TestResource ROLE4B = new TestResource(TEST_RESOURCE_DIR, "role-role4b.xml", "00000001-d34d-b33f-f00d-00000000004b"); + + // Note: Role10/10b is induced so it is _not_ being approved. Only direct assignments are covered by approvals. + static final TestResource ROLE10 = new TestResource(TEST_RESOURCE_DIR, "role-role10.xml", "00000001-d34d-b33f-f00d-000000000010"); + static final TestResource ROLE10B = new TestResource(TEST_RESOURCE_DIR, "role-role10b.xml", "00000001-d34d-b33f-f00d-00000000010b"); + + // delegation for jack-deputy is created only when needed + private static final TestResource USER_JACK_DEPUTY = new TestResource(TEST_RESOURCE_DIR, "user-jack-deputy.xml", "e44769f2-030b-4e9c-9ddf-76bb3a348f9c"); + private static final TestResource USER_LEAD1 = new TestResource(TEST_RESOURCE_DIR, "user-lead1.xml", "00000001-d34d-b33f-f00d-L00000000001"); + private static final TestResource USER_LEAD1_DEPUTY_1 = new TestResource(TEST_RESOURCE_DIR, "user-lead1-deputy1.xml", "00000001-d34d-b33f-f00d-LD1000000001"); + private static final TestResource USER_LEAD1_DEPUTY_2 = new TestResource(TEST_RESOURCE_DIR, "user-lead1-deputy2.xml", "00000001-d34d-b33f-f00d-LD1000000002"); + private static final TestResource USER_LEAD2 = new TestResource(TEST_RESOURCE_DIR, "user-lead2.xml", "00000001-d34d-b33f-f00d-L00000000002"); + private static final TestResource USER_LEAD3 = new TestResource(TEST_RESOURCE_DIR, "user-lead3.xml", "00000001-d34d-b33f-f00d-L00000000003"); + private static final TestResource USER_LEAD10 = new TestResource(TEST_RESOURCE_DIR, "user-lead10.xml", "00000001-d34d-b33f-f00d-L00000000010"); + + // Draft user. His assignments should undertake approvals just like other users' assignments (MID-6113). + private static final TestResource USER_DRAFT = new TestResource(TEST_RESOURCE_DIR, "user-draft.xml","e3c00bba-8ce0-4727-a294-91842264c2de"); protected abstract String getRoleOid(int number); protected abstract String getRoleName(int number); + private boolean lead1DeputiesLoaded; + @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); repoAddObjectFromFile(METAROLE_DEFAULT_FILE, initResult); - roleRole1Oid = repoAddObjectFromFile(ROLE_ROLE1_FILE, initResult).getOid(); - roleRole1bOid = repoAddObjectFromFile(ROLE_ROLE1B_FILE, initResult).getOid(); - roleRole2Oid = repoAddObjectFromFile(ROLE_ROLE2_FILE, initResult).getOid(); - roleRole2bOid = repoAddObjectFromFile(ROLE_ROLE2B_FILE, initResult).getOid(); - roleRole3Oid = repoAddObjectFromFile(ROLE_ROLE3_FILE, initResult).getOid(); - roleRole3bOid = repoAddObjectFromFile(ROLE_ROLE3B_FILE, initResult).getOid(); - roleRole4Oid = repoAddObjectFromFile(ROLE_ROLE4_FILE, initResult).getOid(); - roleRole4bOid = repoAddObjectFromFile(ROLE_ROLE4B_FILE, initResult).getOid(); - roleRole10Oid = repoAddObjectFromFile(ROLE_ROLE10_FILE, initResult).getOid(); - roleRole10bOid = repoAddObjectFromFile(ROLE_ROLE10B_FILE, initResult).getOid(); - roleRole15Oid = repoAddObjectFromFile(ROLE_ROLE15_FILE, initResult).getOid(); - - userJackDeputyOid = repoAddObjectFromFile(USER_JACK_DEPUTY_FILE, initResult).getOid(); - userLead1Oid = addAndRecomputeUser(USER_LEAD1_FILE, initTask, initResult); - userLead2Oid = addAndRecomputeUser(USER_LEAD2_FILE, initTask, initResult); - userLead3Oid = addAndRecomputeUser(USER_LEAD3_FILE, initTask, initResult); - addAndRecomputeUser(USER_LEAD15_FILE, initTask, initResult); + repoAdd(ROLE1, initResult); + repoAdd(ROLE1B, initResult); + repoAdd(ROLE2, initResult); + repoAdd(ROLE2B, initResult); + repoAdd(ROLE3, initResult); + repoAdd(ROLE3B, initResult); + repoAdd(ROLE4, initResult); + repoAdd(ROLE4B, initResult); + repoAdd(ROLE10, initResult); + repoAdd(ROLE10B, initResult); + + repoAdd(USER_JACK_DEPUTY, initResult); + addAndRecomputeUser(USER_LEAD1.file, initTask, initResult); + addAndRecomputeUser(USER_LEAD2.file, initTask, initResult); + addAndRecomputeUser(USER_LEAD3.file, initTask, initResult); // LEAD10 will be imported later! + + repoAdd(USER_DRAFT, initResult); } /** @@ -141,7 +139,7 @@ public void test010AddRole1Assignment() throws Exception { TestUtil.displayTestTitle(this, TEST_NAME); login(userAdministrator); - OperationResult result = executeAssignRole1ToJack(TEST_NAME, false, false, null, null, true); + OperationResult result = executeAssignRole1(TEST_NAME, userJackOid, false, false, USER_LEAD1.oid, null, true); // MID-5814 OperationResultAsserter.forResult(result) @@ -189,7 +187,7 @@ public void test030AddRole1AssignmentAgain() throws Exception { Task task = createTask(TEST_NAME); importLead10(task, task.getResult()); - executeAssignRole1ToJack(TEST_NAME, false, false, null, null, false); + executeAssignRole1(TEST_NAME, userJackOid, false, false, USER_LEAD1.oid, null, false); } /** @@ -202,7 +200,7 @@ public void test040AddRole1AssignmentImmediate() throws Exception { login(userAdministrator); unassignAllRoles(userJackOid); - executeAssignRole1ToJack(TEST_NAME, true, false, null, null, false); + executeAssignRole1(TEST_NAME, userJackOid, true, false, USER_LEAD1.oid, null, false); } /** @@ -297,12 +295,12 @@ public void test100AddCreateDelegation() throws Exception { OperationResult result = task.getResult(); // WHEN - assignDeputy(userJackDeputyOid, userJackOid, a -> { + assignDeputy(USER_JACK_DEPUTY.oid, userJackOid, a -> { //a.beginLimitTargetContent().allowTransitive(true); }, task, result); // THEN - PrismObject deputy = getUser(userJackDeputyOid); + PrismObject deputy = getUser(USER_JACK_DEPUTY.oid); display("deputy after", deputy); result.computeStatus(); @@ -323,7 +321,7 @@ public void test130AddRole1aAssignmentWithDeputy() throws Exception { importLead1Deputies(task, task.getResult()); unassignAllRoles(userJackOid); - executeAssignRole1ToJack(TEST_NAME, false, true, null, null, false); + executeAssignRole1(TEST_NAME, userJackOid, false, true, USER_LEAD1.oid, null, false); } /** @@ -336,7 +334,7 @@ public void test132AddRole1aAssignmentWithDeputyApprovedByDeputy1() throws Excep login(userAdministrator); unassignAllRoles(userJackOid); - executeAssignRole1ToJack(TEST_NAME, false, true, userLead1Deputy1Oid, null, false); + executeAssignRole1(TEST_NAME, userJackOid, false, true, USER_LEAD1_DEPUTY_1.oid, null, false); } @Test(enabled = false) @@ -346,28 +344,40 @@ public void test150AddRole1ApproverAssignment() throws Exception { login(userAdministrator); unassignAllRoles(userJackOid); - executeAssignRole1ToJack(TEST_NAME, false, true, null, SchemaConstants.ORG_APPROVER, false); + executeAssignRole1(TEST_NAME, userJackOid, false, true, USER_LEAD1.oid, SchemaConstants.ORG_APPROVER, false); } - private OperationResult executeAssignRole1ToJack(String TEST_NAME, boolean immediate, boolean deputy, String approverOid, QName relation, - boolean useTracing) throws Exception { - PrismObject jack = getUser(userJackOid); - AssignmentType assignment = createAssignmentTo(getRoleOid(1), ObjectTypes.ROLE, prismContext); - assignment.getTargetRef().setRelation(relation); - ObjectDelta addRole1Delta = prismContext + @Test + public void test200AddRole1AssignmentToDraftUser() throws Exception { + final String TEST_NAME = "test200AddRole1AssignmentToDraftUser"; + TestUtil.displayTestTitle(this, TEST_NAME); + login(userAdministrator); + + executeAssignRole1(TEST_NAME, USER_DRAFT.oid, false, true, USER_LEAD1.oid, null, false); + } + + // in memory tracing is required to check for MID-5814 + private OperationResult executeAssignRole1(String TEST_NAME, String userOid, boolean immediate, boolean deputiesOfLeadOneSeeItems, String approverOid, QName relation, + boolean useInMemoryTracing) throws Exception { + PrismObject user = getUser(userOid); + String userName = user.getName().getOrig(); + // @formatter:off + ObjectDelta delta = prismContext .deltaFor(UserType.class) - .item(UserType.F_ASSIGNMENT).add(assignment) - .asObjectDelta(userJackOid); - String realApproverOid = approverOid != null ? approverOid : userLead1Oid; + .item(UserType.F_ASSIGNMENT) + .add(new AssignmentType(prismContext) + .targetRef(getRoleOid(1), RoleType.COMPLEX_TYPE, relation)) + .asObjectDelta(userOid); + // @formatter:on return executeTest2(TEST_NAME, new TestDetails2() { @Override protected PrismObject getFocus(OperationResult result) { - return jack.clone(); + return user.clone(); } @Override protected ObjectDelta getFocusDelta() { - return addRole1Delta.clone(); + return delta.clone(); } @Override @@ -377,62 +387,65 @@ protected int getNumberOfDeltasToApprove() { @Override protected List getApprovals() { - return Collections.singletonList(true); + return singletonList(true); } @Override protected List> getExpectedDeltasToApprove() { - return Collections.singletonList(addRole1Delta.clone()); + return singletonList(delta.clone()); } @Override protected ObjectDelta getExpectedDelta0() { return prismContext.deltaFactory().object() - .createModifyDelta(jack.getOid(), Collections.emptyList(), UserType.class); + .createModifyDelta(user.getOid(), Collections.emptyList(), UserType.class); } @Override protected String getObjectOid() { - return jack.getOid(); + return user.getOid(); } @Override protected List getExpectedTasks() { - return Collections.singletonList(new ExpectedTask(getRoleOid(1), "Assigning role \"" + getRoleName(1) + "\" to user \"jack\"")); + return singletonList(new ExpectedTask(getRoleOid(1), "Assigning role \"" + + getRoleName(1) + "\" to user \"" + userName + "\"")); } @Override protected List getExpectedWorkItems() { ExpectedTask expTask = getExpectedTasks().get(0); - return Collections.singletonList(new ExpectedWorkItem(userLead1Oid, getRoleOid(1), expTask)); + return singletonList(new ExpectedWorkItem(USER_LEAD1.oid, getRoleOid(1), expTask)); } @Override protected void assertDeltaExecuted(int number, boolean yes, Task opTask, OperationResult result) throws Exception { if (number == 1) { if (yes) { - assertAssignedRole(userJackOid, getRoleOid(1), opTask, result); + assertAssignedRole(userOid, getRoleOid(1), opTask, result); checkAuditRecords(createResultMap(getRoleOid(1), WorkflowResult.APPROVED)); - checkUserApprovers(userJackOid, Collections.singletonList(realApproverOid), result); + checkUserApprovers(userOid, singletonList(approverOid), result); } else { - assertNotAssignedRole(userJackOid, getRoleOid(1), opTask, result); + assertNotAssignedRole(userOid, getRoleOid(1), opTask, result); } } } @Override protected Boolean decideOnApproval(CaseWorkItemType caseWorkItem) throws Exception { - assertActiveWorkItems(userLead1Oid, 1); - assertActiveWorkItems(userLead1Deputy1Oid, deputy ? 1 : 0); - assertActiveWorkItems(userLead1Deputy2Oid, deputy ? 1 : 0); + assertActiveWorkItems(USER_LEAD1.oid, 1); + if (lead1DeputiesLoaded || deputiesOfLeadOneSeeItems) { + assertActiveWorkItems(USER_LEAD1_DEPUTY_1.oid, deputiesOfLeadOneSeeItems ? 1 : 0); + assertActiveWorkItems(USER_LEAD1_DEPUTY_2.oid, deputiesOfLeadOneSeeItems ? 1 : 0); + } checkTargetOid(caseWorkItem, getRoleOid(1)); - login(getUser(realApproverOid)); + login(getUser(approverOid)); return true; } @Override public void setTracing(Task opTask) { - if (useTracing) { + if (useInMemoryTracing) { opTask.addTracingRequest(TracingRootType.CLOCKWORK_RUN); opTask.addTracingRequest(TracingRootType.WORKFLOW_OPERATION); opTask.setTracingProfile( @@ -469,24 +482,19 @@ private void assertActiveWorkItems(String approverOid, int expectedCount) throws private void executeAssignRoles123ToJack(String TEST_NAME, boolean immediate, boolean approve1, boolean approve2, boolean approve3) throws Exception { PrismObject jack = getUser(userJackOid); - ObjectDelta addRole1Delta = prismContext - .deltaFor(UserType.class) + ObjectDelta addRole1Delta = prismContext.deltaFor(UserType.class) .item(UserType.F_ASSIGNMENT).add(createAssignmentTo(getRoleOid(1), ObjectTypes.ROLE, prismContext)) .asObjectDelta(userJackOid); - ObjectDelta addRole2Delta = prismContext - .deltaFor(UserType.class) + ObjectDelta addRole2Delta = prismContext.deltaFor(UserType.class) .item(UserType.F_ASSIGNMENT).add(createAssignmentTo(getRoleOid(2), ObjectTypes.ROLE, prismContext)) .asObjectDelta(userJackOid); - ObjectDelta addRole3Delta = prismContext - .deltaFor(UserType.class) + ObjectDelta addRole3Delta = prismContext.deltaFor(UserType.class) .item(UserType.F_ASSIGNMENT).add(createAssignmentTo(getRoleOid(3), ObjectTypes.ROLE, prismContext)) .asObjectDelta(userJackOid); - ObjectDelta addRole4Delta = prismContext - .deltaFor(UserType.class) + ObjectDelta addRole4Delta = prismContext.deltaFor(UserType.class) .item(UserType.F_ASSIGNMENT).add(createAssignmentTo(getRoleOid(4), ObjectTypes.ROLE, prismContext)) .asObjectDelta(userJackOid); - ObjectDelta changeDescriptionDelta = prismContext - .deltaFor(UserType.class) + ObjectDelta changeDescriptionDelta = prismContext.deltaFor(UserType.class) .item(UserType.F_DESCRIPTION).replace(TEST_NAME) .asObjectDelta(userJackOid); ObjectDelta primaryDelta = ObjectDeltaCollectionsUtil @@ -541,9 +549,9 @@ protected List getExpectedTasks() { protected List getExpectedWorkItems() { List expTasks = getExpectedTasks(); return Arrays.asList( - new ExpectedWorkItem(userLead1Oid, getRoleOid(1), expTasks.get(0)), - new ExpectedWorkItem(userLead2Oid, getRoleOid(2), expTasks.get(1)), - new ExpectedWorkItem(userLead3Oid, getRoleOid(3), expTasks.get(2)) + new ExpectedWorkItem(USER_LEAD1.oid, getRoleOid(1), expTasks.get(0)), + new ExpectedWorkItem(USER_LEAD2.oid, getRoleOid(2), expTasks.get(1)), + new ExpectedWorkItem(USER_LEAD3.oid, getRoleOid(3), expTasks.get(2)) ); } @@ -580,13 +588,13 @@ protected void assertDeltaExecuted(int number, boolean yes, Task opTask, Operati protected Boolean decideOnApproval(CaseWorkItemType caseWorkItem) throws Exception { String targetOid = getTargetOid(caseWorkItem); if (getRoleOid(1).equals(targetOid)) { - login(getUser(userLead1Oid)); + login(getUser(USER_LEAD1.oid)); return approve1; } else if (getRoleOid(2).equals(targetOid)) { - login(getUser(userLead2Oid)); + login(getUser(USER_LEAD2.oid)); return approve2; } else if (getRoleOid(3).equals(targetOid)) { - login(getUser(userLead3Oid)); + login(getUser(USER_LEAD3.oid)); return approve3; } else { throw new IllegalStateException("Unexpected approval request for " + targetOid); @@ -607,11 +615,12 @@ public void zzzMarkAsNotInitialized() { } private void importLead10(Task task, OperationResult result) throws Exception { - addAndRecomputeUser(USER_LEAD10_FILE, task, result); + addAndRecomputeUser(USER_LEAD10.file, task, result); } private void importLead1Deputies(Task task, OperationResult result) throws Exception { - userLead1Deputy1Oid = addAndRecomputeUser(USER_LEAD1_DEPUTY_1_FILE, task, result); - userLead1Deputy2Oid = addAndRecomputeUser(USER_LEAD1_DEPUTY_2_FILE, task, result); + addAndRecomputeUser(USER_LEAD1_DEPUTY_1.file, task, result); + addAndRecomputeUser(USER_LEAD1_DEPUTY_2.file, task, result); + lead1DeputiesLoaded = true; } } diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalGlobal.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalGlobal.java index 59081219784..66d7860752f 100644 --- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalGlobal.java +++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalGlobal.java @@ -10,6 +10,7 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.test.TestResource; import com.evolveum.midpoint.util.exception.PolicyViolationException; import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseWorkItemType; @@ -19,14 +20,25 @@ import static org.testng.AssertJUnit.assertEquals; /** - * Shouldn't be used, as global policy rules for assignments are not implemented yet. * - * @author mederly */ public class TestAssignmentApprovalGlobal extends AbstractTestAssignmentApproval { private static final File SYSTEM_CONFIGURATION_GLOBAL_FILE = new File(TEST_RESOURCE_DIR, "system-configuration-global.xml"); + // Role15 has its approver but there is also a global policy rule that prevents it from being assigned. + private static final TestResource ROLE15 = new TestResource(TEST_RESOURCE_DIR, "role-role15.xml", "00000001-d34d-b33f-f00d-000000000015"); + + private static final TestResource USER_LEAD15 = new TestResource(TEST_RESOURCE_DIR, "user-lead15.xml", "00000001-d34d-b33f-f00d-L00000000015"); + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + repoAdd(ROLE15, initResult); + addAndRecomputeUser(USER_LEAD15.file, initTask, initResult); + } + @Override protected File getSystemConfigurationFile() { return SYSTEM_CONFIGURATION_GLOBAL_FILE; @@ -36,11 +48,11 @@ protected File getSystemConfigurationFile() { @Override protected String getRoleOid(int number) { switch (number) { - case 1: return roleRole1Oid; - case 2: return roleRole2Oid; - case 3: return roleRole3Oid; - case 4: return roleRole4Oid; - case 10: return roleRole10Oid; + case 1: return ROLE1.oid; + case 2: return ROLE2.oid; + case 3: return ROLE3.oid; + case 4: return ROLE4.oid; + case 10: return ROLE10.oid; default: throw new IllegalArgumentException("Wrong role number: " + number); } } @@ -70,9 +82,9 @@ public void test300ApprovalAndEnforce() throws Exception { OperationResult result = task.getResult(); try { - assignRole(userJackOid, roleRole15Oid, task, result); + assignRole(userJackOid, ROLE15.oid, task, result); + fail("Unexpected success"); } catch (PolicyViolationException e) { - // ok System.out.println("Got expected exception: " + e); } List currentWorkItems = modelService.searchContainers(CaseWorkItemType.class, getOpenItemsQuery(), null, task, result); diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalMetaroleExplicit.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalMetaroleExplicit.java index 29696826e91..9f0c978ed4b 100644 --- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalMetaroleExplicit.java +++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalMetaroleExplicit.java @@ -9,8 +9,6 @@ /** * Tests assigning of roles 1..3 with explicitly assigned metaroles (with policy rules). - * - * @author mederly */ @SuppressWarnings("Duplicates") public class TestAssignmentApprovalMetaroleExplicit extends AbstractTestAssignmentApproval { @@ -18,11 +16,11 @@ public class TestAssignmentApprovalMetaroleExplicit extends AbstractTestAssignme @Override protected String getRoleOid(int number) { switch (number) { - case 1: return roleRole1bOid; - case 2: return roleRole2bOid; - case 3: return roleRole3bOid; - case 4: return roleRole4bOid; - case 10: return roleRole10bOid; + case 1: return ROLE1B.oid; + case 2: return ROLE2B.oid; + case 3: return ROLE3B.oid; + case 4: return ROLE4B.oid; + case 10: return ROLE10B.oid; default: throw new IllegalArgumentException("Wrong role number: " + number); } } diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalPlainImplicit.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalPlainImplicit.java index fb3a08197a0..b32d3e1d26a 100644 --- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalPlainImplicit.java +++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentApprovalPlainImplicit.java @@ -10,8 +10,6 @@ /** * Tests assigning of roles 1..3 with implicitly defined approvers (i.e. via org:approver assignment). * As for policy rules, the default ones are used. - * - * @author mederly */ @SuppressWarnings("Duplicates") public class TestAssignmentApprovalPlainImplicit extends AbstractTestAssignmentApproval { @@ -19,11 +17,11 @@ public class TestAssignmentApprovalPlainImplicit extends AbstractTestAssignmentA @Override protected String getRoleOid(int number) { switch (number) { - case 1: return roleRole1Oid; - case 2: return roleRole2Oid; - case 3: return roleRole3Oid; - case 4: return roleRole4Oid; - case 10: return roleRole10Oid; + case 1: return ROLE1.oid; + case 2: return ROLE2.oid; + case 3: return ROLE3.oid; + case 4: return ROLE4.oid; + case 10: return ROLE10.oid; default: throw new IllegalArgumentException("Wrong role number: " + number); } } diff --git a/model/workflow-impl/src/test/resources/assignments/user-draft.xml b/model/workflow-impl/src/test/resources/assignments/user-draft.xml new file mode 100644 index 00000000000..3535937b57c --- /dev/null +++ b/model/workflow-impl/src/test/resources/assignments/user-draft.xml @@ -0,0 +1,12 @@ + + + + draft + draft + Draft + diff --git a/model/workflow-impl/src/test/resources/assignments/user-lead1.xml b/model/workflow-impl/src/test/resources/assignments/user-lead1.xml index 7ff753d829c..442b446a831 100644 --- a/model/workflow-impl/src/test/resources/assignments/user-lead1.xml +++ b/model/workflow-impl/src/test/resources/assignments/user-lead1.xml @@ -24,9 +24,6 @@ - - - Lead1 Lead1 diff --git a/model/workflow-impl/src/test/resources/assignments/user-lead2.xml b/model/workflow-impl/src/test/resources/assignments/user-lead2.xml index f9b9529a833..d3b88e53fd5 100644 --- a/model/workflow-impl/src/test/resources/assignments/user-lead2.xml +++ b/model/workflow-impl/src/test/resources/assignments/user-lead2.xml @@ -16,9 +16,6 @@ - - - Lead2 Lead2 diff --git a/model/workflow-impl/src/test/resources/assignments/user-lead3.xml b/model/workflow-impl/src/test/resources/assignments/user-lead3.xml index ff6c19fb353..497f33d1721 100644 --- a/model/workflow-impl/src/test/resources/assignments/user-lead3.xml +++ b/model/workflow-impl/src/test/resources/assignments/user-lead3.xml @@ -16,9 +16,6 @@ - - - Lead3 Lead3