From d625c749762bcbc866633a5f31aa46180924c3e7 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Sat, 23 Sep 2017 05:38:00 +0200 Subject: [PATCH 01/19] Interim commit. --- .../xml/ns/public/common/common-core-3.xsd | 82 ++++++++++++---- .../public/common/common-model-context-3.xsd | 80 ++++++++++++++- .../xml/ns/public/common/common-policy-3.xsd | 97 ++++++++++--------- .../complex/system-configuration.xml | 41 +++++++- .../model/impl/lens/ChangeExecutor.java | 48 +++------ .../model/impl/lens/LensElementContext.java | 20 ++++ .../impl/lens/LensProjectionContext.java | 2 +- .../impl/lens/projector/FocusProcessor.java | 4 +- ...AssignmentPolicyRuleEvaluationContext.java | 16 +-- .../ObjectPolicyRuleEvaluationContext.java | 13 ++- .../policy/PolicyRuleEvaluationContext.java | 13 +-- .../projector/policy/PolicyRuleProcessor.java | 42 ++++++-- .../policy/PolicySituationUpdater.java | 9 ++ .../policy/RulesEvaluationContext.java | 31 ++++++ 14 files changed, 357 insertions(+), 141 deletions(-) create mode 100644 model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/RulesEvaluationContext.java diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd index 3cc847b530d..43e25402934 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd @@ -362,8 +362,50 @@ - - + + + + + The policy situation(s) of this object. The situations are result of + evaluation of the policy rules. This property is recorded for each object + and can be used for reporting, diagnostics, target selection in certification + campaigns, etc. + + + 3.5 + true + + + + + + + + Triggered policy rules for this assignment. (Not necessarily complete; subject to specified storage strategy.) + This is EXPERIMENTAL functionality. It is possibly to change in the near future. + + + 3.7 + true + + + + + + + + Recorded exception from a policy rule. The exceptions that are approved are + recoded here to avoid re-evaluating and re-approving them all the time. + This is EXPERIMENTAL functionality. It is likely to change in the near future. + + + 3.5 + true + + + + + @@ -2399,22 +2441,7 @@ - - - - The policy situation(s) of this object. The situations are result of - evaluation of the policy rules. This property is recorded for each object - and can be used for reporting, diagnostics, target selection in certification - campaigns, etc. - - - 3.5 - true - - - - - + @@ -3492,12 +3519,25 @@ - Fired policy rule triggers for this assignment. (Some fields of the triggers might be zeroed out - in order to save space. This is yet to be decided.) - This is EXPERIMENTAL functionality. It is likely to change in the near future. + DEPRECATED. DO NOT USE. 3.6 + true + 3.7 + true + + + + + + + + Triggered policy rules for this assignment. (Not necessarily complete; subject to specified storage strategy.) + This is EXPERIMENTAL functionality. It is possibly to change in the near future. + + + 3.7 true diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd index b9aecb7f036..0e306f80e99 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd @@ -506,10 +506,40 @@ - - - - + + + + DEPRECATED. Moved to EvaluatedPolicyRuleType. DO NOT USE. + + + true + 3.7 + + + + + + + DEPRECATED. Moved to EvaluatedPolicyRuleType. DO NOT USE. + + + true + 3.7 + + + + + + + DEPRECATED. Moved to EvaluatedPolicyRuleType. DO NOT USE. + + + true + 3.7 + + + + @@ -637,7 +667,47 @@ - + + + + TODO + + + 3.7 + + + + + + + TODO + + + 3.7 + + + + + + + TODO + + + 3.7 + + + + + + + TODO + + + 3.7 + + + + diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd index 185dfa04f07..534cb7687dd 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd @@ -300,43 +300,6 @@ - - - - Policy situation that is the result when this constraint is triggered. - TODO specify the relation to policySituation defined at the level of policy rule. - - - 3.7 - true - - - - - - - How is this constraint to be used? E.g. also for reporting or for certification? This determines - if its triggers and/or related policy situation should be stored into repository. - EXPERIMENTAL - - - 3.7 - true - - - - - - - If triggers are to be stored, what level of details should be preserved? - EXPERIMENTAL - - - 3.7 - true - - - @@ -449,7 +412,7 @@ - + If triggers are to be stored, what level of details should be preserved? @@ -461,33 +424,33 @@ - + - Only message and short message will be stored. + Triggers will not be stored. - + - + - Whole triggers will be stored. (But only those that are directly marked with expectedUse property.) + Only message and short message for each trigger will be stored. Hidden and final presentation settings are respected. - + - + - Whole triggers will be stored, including subtriggers. + The triggers for the rule will be stored (including subtriggers). Hidden and final presentation settings are respected. - + @@ -1051,6 +1014,14 @@ + + + + Record action. The operation will proceed. Policy situation will be recorded for + given object or assignment. It can be reported on or certified later on. + + + @@ -1404,6 +1375,38 @@ + + + + TODO + + + + 3.7 + true + + + + + + + + + How should be triggers stored? + EXPERIMENTAL + + + 3.7 + true + + + + + + + + + diff --git a/model/certification-impl/src/test/resources/complex/system-configuration.xml b/model/certification-impl/src/test/resources/complex/system-configuration.xml index ca588c142d4..8c8cd007d65 100644 --- a/model/certification-impl/src/test/resources/complex/system-configuration.xml +++ b/model/certification-impl/src/test/resources/complex/system-configuration.xml @@ -223,9 +223,6 @@ true - http://sample.org/situations#active-role-with-no-identifier - certification - fullReport role-active @@ -240,8 +237,6 @@ true - http://sample.org/situations#incomplete-role-c1-to-c4 - fullReport c1-no-risk-level @@ -389,6 +384,42 @@ RoleType + + re1-report-draft-roles-violating-c1-c4 + RE1: See all draft roles that do not meet constraints C1-C4. + + + incomplete-role-c1-to-c4 + + + http://sample.org/situations#incomplete-role-c1-to-c4 + + + full + + + + RoleType + + + + re2-report-active-roles-violating-c5 + RE2: See all active roles that do not meet constraint C5. + + + active-role-with-no-identifier + + + http://sample.org/situations#active-role-with-no-identifier + + + none + + + + RoleType + + test-primary diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java index 834c11784d6..6fc341b5c85 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java @@ -110,38 +110,17 @@ public class ChangeExecutor { private static final String OPERATION_UPDATE_SITUATION_ACCOUNT = ChangeExecutor.class.getName() + ".updateSituationInShadow"; - @Autowired - private transient TaskManager taskManager; - - @Autowired - @Qualifier("cacheRepositoryService") - private transient RepositoryService cacheRepositoryService; - - @Autowired - private ProvisioningService provisioning; - - @Autowired - private PrismContext prismContext; - - @Autowired - private ExpressionFactory expressionFactory; - - @Autowired - private SecurityEnforcer securityEnforcer; - - @Autowired - private Clock clock; - - @Autowired - private ModelObjectResolver objectResolver; - - @Autowired - private OperationalDataManager metadataManager; - - @Autowired - private PolicySituationUpdater policySituationUpdater; - @Autowired - private CredentialsProcessor credentialsProcessor; + @Autowired private transient TaskManager taskManager; + @Autowired @Qualifier("cacheRepositoryService") private transient RepositoryService cacheRepositoryService; + @Autowired private ProvisioningService provisioning; + @Autowired private PrismContext prismContext; + @Autowired private ExpressionFactory expressionFactory; + @Autowired private SecurityEnforcer securityEnforcer; + @Autowired private Clock clock; + @Autowired private ModelObjectResolver objectResolver; + @Autowired private OperationalDataManager metadataManager; + @Autowired private PolicySituationUpdater policySituationUpdater; + @Autowired private CredentialsProcessor credentialsProcessor; private PrismObjectDefinition userDefinition = null; private PrismObjectDefinition shadowDefinition = null; @@ -171,6 +150,11 @@ public boolean executeChanges(LensContext context, Tas if (focusContext != null) { ObjectDelta focusDelta = focusContext.getWaveExecutableDelta(context.getExecutionWave()); + for (ItemDelta itemDelta : focusContext.getPendingPolicySituationModifications()) { + focusContext.swallowToSecondaryDelta(itemDelta); + } + focusContext.clearPendingPolicySituationModifications(); + if (!focusContext.isDelete()) { focusDelta = policySituationUpdater.applyAssignmentSituation(context, focusDelta); policySituationUpdater.storeFocusPolicySituation(context); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java index abb553d18db..fee71efd96c 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java @@ -73,6 +73,14 @@ public abstract class LensElementContext implements ModelE private int iteration; private String iterationToken; + /** + * These are policy situation modifications that should be applied regardless of how the clockwork is exited + * (e.g. in primary state, in final state, with an exception). + * + * Currently implemented only for focus, not for projections. + */ + @NotNull private transient final List> pendingPolicySituationModifications = new ArrayList<>(); + /** * Initial intent regarding the account. It indicated what the initiator of the operation WANTS TO DO with the * context. @@ -250,6 +258,18 @@ public void swallowToPrimaryDelta(ItemDelta itemDelta) throws SchemaExcepti public abstract void swallowToSecondaryDelta(ItemDelta itemDelta) throws SchemaException; + public List> getPendingPolicySituationModifications() { + return pendingPolicySituationModifications; + } + + public void clearPendingPolicySituationModifications() { + pendingPolicySituationModifications.clear(); + } + + public void addToPendingPolicySituationModifications(ItemDelta modification) { + pendingPolicySituationModifications.add(modification); + } + public boolean isAdd() { if (ObjectDelta.isAdd(getPrimaryDelta())) { return true; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java index 12b4b59fdf7..c85343d4eba 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java @@ -243,7 +243,7 @@ public void addSecondaryDelta(ObjectDelta delta) throws SchemaExcept @Override public void swallowToSecondaryDelta(ItemDelta itemDelta) throws SchemaException { if (secondaryDelta == null) { - secondaryDelta = new ObjectDelta(getObjectTypeClass(), ChangeType.MODIFY, getPrismContext()); + secondaryDelta = new ObjectDelta<>(getObjectTypeClass(), ChangeType.MODIFY, getPrismContext()); secondaryDelta.setOid(getOid()); } secondaryDelta.swallow(itemDelta); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java index 2416410aede..a72191f2adc 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java @@ -260,7 +260,9 @@ private void processFocusFocus(LensContext context, Str // ASSIGNMENTS - LensUtil.partialExecute("assignments", + focusContext.clearPendingPolicySituationModifications(); + + LensUtil.partialExecute("assignments", () -> assignmentProcessor.processAssignmentsProjections(context, now, task, result), partialProcessingOptions::getAssignments); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/AssignmentPolicyRuleEvaluationContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/AssignmentPolicyRuleEvaluationContext.java index 734839749c2..93dae8057c0 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/AssignmentPolicyRuleEvaluationContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/AssignmentPolicyRuleEvaluationContext.java @@ -43,15 +43,18 @@ public class AssignmentPolicyRuleEvaluationContext extends public AssignmentPolicyRuleEvaluationContext(@NotNull EvaluatedPolicyRule policyRule, @NotNull EvaluatedAssignmentImpl evaluatedAssignment, boolean inPlus, boolean inZero, boolean inMinus, boolean isDirect, LensContext context, - DeltaSetTriple> evaluatedAssignmentTriple, Task task) { - this(policyRule, evaluatedAssignment, inPlus, inZero, inMinus, isDirect, context, evaluatedAssignmentTriple, task, ObjectState.AFTER); + DeltaSetTriple> evaluatedAssignmentTriple, Task task, + RulesEvaluationContext globalCtx) { + this(policyRule, evaluatedAssignment, inPlus, inZero, inMinus, isDirect, context, evaluatedAssignmentTriple, + task, ObjectState.AFTER, globalCtx); } public AssignmentPolicyRuleEvaluationContext(@NotNull EvaluatedPolicyRule policyRule, @NotNull EvaluatedAssignmentImpl evaluatedAssignment, boolean inPlus, boolean inZero, boolean inMinus, boolean isDirect, LensContext context, - DeltaSetTriple> evaluatedAssignmentTriple, Task task, ObjectState state) { - super(policyRule, context, task, state); + DeltaSetTriple> evaluatedAssignmentTriple, Task task, ObjectState state, + RulesEvaluationContext globalCtx) { + super(policyRule, context, task, globalCtx, state); this.evaluatedAssignment = evaluatedAssignment; this.inPlus = inPlus; this.inZero = inZero; @@ -62,7 +65,8 @@ public AssignmentPolicyRuleEvaluationContext(@NotNull EvaluatedPolicyRule policy @Override public AssignmentPolicyRuleEvaluationContext cloneWithStateConstraints(ObjectState state) { - return new AssignmentPolicyRuleEvaluationContext<>(policyRule, evaluatedAssignment, inPlus, inZero, inMinus, isDirect, lensContext, evaluatedAssignmentTriple, task, state); + return new AssignmentPolicyRuleEvaluationContext<>(policyRule, evaluatedAssignment, inPlus, inZero, inMinus, isDirect, lensContext, evaluatedAssignmentTriple, task, state, + globalCtx); } @Override @@ -98,6 +102,6 @@ public String getShortDescription() { @Override public AssignmentPolicyRuleEvaluationContext clone() { return new AssignmentPolicyRuleEvaluationContext<>(policyRule, evaluatedAssignment, inPlus, inZero, inMinus, - isDirect, lensContext, evaluatedAssignmentTriple, task); + isDirect, lensContext, evaluatedAssignmentTriple, task, globalCtx); } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/ObjectPolicyRuleEvaluationContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/ObjectPolicyRuleEvaluationContext.java index 43957ddd5fb..19da2f325c5 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/ObjectPolicyRuleEvaluationContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/ObjectPolicyRuleEvaluationContext.java @@ -31,18 +31,18 @@ */ public class ObjectPolicyRuleEvaluationContext extends PolicyRuleEvaluationContext { - public ObjectPolicyRuleEvaluationContext(@NotNull EvaluatedPolicyRule policyRule, LensContext context, Task task) { - this(policyRule, context, task, ObjectState.AFTER); + public ObjectPolicyRuleEvaluationContext(@NotNull EvaluatedPolicyRule policyRule, RulesEvaluationContext globalCtx, LensContext context, Task task) { + this(policyRule, globalCtx, context, task, ObjectState.AFTER); } - public ObjectPolicyRuleEvaluationContext(@NotNull EvaluatedPolicyRule policyRule, LensContext context, Task task, + public ObjectPolicyRuleEvaluationContext(@NotNull EvaluatedPolicyRule policyRule, RulesEvaluationContext globalCtx, LensContext context, Task task, ObjectState state) { - super(policyRule, context, task, state); + super(policyRule, context, task, globalCtx, state); } @Override public PolicyRuleEvaluationContext cloneWithStateConstraints(ObjectState state) { - return new ObjectPolicyRuleEvaluationContext<>(policyRule, lensContext, task, state); + return new ObjectPolicyRuleEvaluationContext<>(policyRule, globalCtx, lensContext, task, state); } @Override @@ -58,7 +58,6 @@ public String getShortDescription() { @SuppressWarnings({ "CloneDoesntDeclareCloneNotSupportedException", "MethodDoesntCallSuperMethod" }) @Override public ObjectPolicyRuleEvaluationContext clone() { - return new ObjectPolicyRuleEvaluationContext<>(policyRule, lensContext, task); + return new ObjectPolicyRuleEvaluationContext<>(policyRule, globalCtx, lensContext, task); } - } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleEvaluationContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleEvaluationContext.java index 2442c2cb190..8e8b87a3caf 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleEvaluationContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleEvaluationContext.java @@ -37,18 +37,15 @@ public abstract class PolicyRuleEvaluationContext implement @NotNull public final LensFocusContext focusContext; @NotNull public final Task task; @NotNull public final ObjectState state; + @NotNull public final RulesEvaluationContext globalCtx; public PolicyRuleEvaluationContext(@NotNull EvaluatedPolicyRule policyRule, @NotNull LensContext context, - @NotNull Task task) { - this(policyRule, context, task, null); - } - - public PolicyRuleEvaluationContext(@NotNull EvaluatedPolicyRule policyRule, @NotNull LensContext context, - @NotNull Task task, @NotNull ObjectState state) { + @NotNull Task task, @NotNull RulesEvaluationContext globalCtx, @NotNull ObjectState state) { this.policyRule = policyRule; this.lensContext = context; this.focusContext = context.getFocusContext(); this.task = task; + this.globalCtx = globalCtx; if (focusContext == null) { throw new IllegalStateException("No focus context"); } @@ -72,4 +69,8 @@ public boolean isApplicableToState() { } public abstract String getShortDescription(); + + public void record() { + globalCtx.rulesToRecord.add(policyRule); + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java index f53e12fed3e..a04d3df97f0 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java @@ -25,7 +25,6 @@ import com.evolveum.midpoint.prism.delta.ContainerDelta; import com.evolveum.midpoint.prism.delta.DeltaSetTriple; import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; -import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.repo.common.expression.ExpressionUtil; import com.evolveum.midpoint.repo.common.expression.ObjectDeltaObject; @@ -70,7 +69,7 @@ public class PolicyRuleProcessor { @Autowired @Qualifier("cacheRepositoryService") private RepositoryService repositoryService; @Autowired private MappingFactory mappingFactory; @Autowired private MappingEvaluator mappingEvaluator; - @Autowired private MatchingRuleRegistry matchingRuleRegistry; + @Autowired private PolicySituationUpdater situationUpdater; @Autowired private AssignmentConstraintEvaluator assignmentConstraintEvaluator; @Autowired private HasAssignmentConstraintEvaluator hasAssignmentConstraintEvaluator; @@ -98,6 +97,8 @@ public void evaluateAssignmentPolicyRules(LensContext c throws PolicyViolationException, SchemaException, ExpressionEvaluationException, ObjectNotFoundException { for (EvaluatedAssignmentImpl evaluatedAssignment : evaluatedAssignmentTriple.union()) { + RulesEvaluationContext globalCtx = new RulesEvaluationContext(); + boolean inPlus = evaluatedAssignmentTriple.presentInPlusSet(evaluatedAssignment); boolean inMinus = evaluatedAssignmentTriple.presentInMinusSet(evaluatedAssignment); boolean inZero = evaluatedAssignmentTriple.presentInZeroSet(evaluatedAssignment); @@ -116,7 +117,8 @@ public void evaluateAssignmentPolicyRules(LensContext c if (!hasSituationConstraint(policyRule)) { if (checkApplicabilityToAssignment(policyRule)) { evaluateRule(new AssignmentPolicyRuleEvaluationContext<>(policyRule, - evaluatedAssignment, inPlus, inZero, inMinus, true, context, evaluatedAssignmentTriple, task), result); + evaluatedAssignment, inPlus, inZero, inMinus, true, context, + evaluatedAssignmentTriple, task, globalCtx), result); } } } @@ -124,7 +126,8 @@ public void evaluateAssignmentPolicyRules(LensContext c if (!hasSituationConstraint(policyRule)) { if (checkApplicabilityToAssignment(policyRule)) { evaluateRule(new AssignmentPolicyRuleEvaluationContext<>(policyRule, - evaluatedAssignment, inPlus, inZero, inMinus, false, context, evaluatedAssignmentTriple, task), result); + evaluatedAssignment, inPlus, inZero, inMinus, false, context, + evaluatedAssignmentTriple, task, globalCtx), result); } } } @@ -132,7 +135,8 @@ public void evaluateAssignmentPolicyRules(LensContext c if (hasSituationConstraint(policyRule)) { if (checkApplicabilityToAssignment(policyRule)) { evaluateRule(new AssignmentPolicyRuleEvaluationContext<>(policyRule, - evaluatedAssignment, inPlus, inZero, inMinus, true, context, evaluatedAssignmentTriple, task), result); + evaluatedAssignment, inPlus, inZero, inMinus, true, context, + evaluatedAssignmentTriple, task, globalCtx), result); } } } @@ -140,10 +144,12 @@ public void evaluateAssignmentPolicyRules(LensContext c if (hasSituationConstraint(policyRule)) { if (checkApplicabilityToAssignment(policyRule)) { evaluateRule(new AssignmentPolicyRuleEvaluationContext<>(policyRule, - evaluatedAssignment, inPlus, inZero, inMinus, false, context, evaluatedAssignmentTriple, task), result); + evaluatedAssignment, inPlus, inZero, inMinus, false, context, + evaluatedAssignmentTriple, task, globalCtx), result); } } } + situationUpdater.applyAssignmentSituation(context, evaluatedAssignment, globalCtx.rulesToRecord); } exclusionConstraintEvaluator.checkExclusionsLegacy(context, evaluatedAssignmentTriple.getPlusSet(), @@ -176,6 +182,8 @@ public void evaluateObjectPolicyRules(LensContext conte return; } + RulesEvaluationContext globalCtx = new RulesEvaluationContext(); + List rules = new ArrayList<>(); collectFocusRulesFromAssignments(rules, context); collectGlobalObjectRules(rules, context, task, result); @@ -201,11 +209,12 @@ public void evaluateObjectPolicyRules(LensContext conte } for (EvaluatedPolicyRule rule : nonSituationRules) { - evaluateFocusRule(rule, context, task, result); + evaluateFocusRule(rule, context, globalCtx, task, result); } for (EvaluatedPolicyRule rule : situationRules) { - evaluateFocusRule(rule, context, task, result); + evaluateFocusRule(rule, context, globalCtx, task, result); } + situationUpdater.applyObjectSituation(context, globalCtx.rulesToRecord); } private Collection getAllGlobalRules(LensContext context) { @@ -214,9 +223,10 @@ private Collection getAllGlobalR : Collections.emptyList(); } - private void evaluateFocusRule(EvaluatedPolicyRule rule, LensContext context, Task task, OperationResult result) + private void evaluateFocusRule(EvaluatedPolicyRule rule, LensContext context, + RulesEvaluationContext globalCtx, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException { - evaluateRule(new ObjectPolicyRuleEvaluationContext<>(rule, context, task), result); + evaluateRule(new ObjectPolicyRuleEvaluationContext<>(rule, globalCtx, context, task), result); } private void collectFocusRulesFromAssignments(List rules, LensContext context) { @@ -309,9 +319,21 @@ private void evaluateRule(PolicyRuleEvaluationContext c } ctx.triggerRule(triggers); } + if (ctx.policyRule.getActions() != null && ctx.policyRule.getActions().getRecordSituation() != null) { + ctx.record(); + } traceRuleEvaluationResult(ctx.policyRule, ctx); } +// private void prepareSituationDeltas(PolicyRuleEvaluationContext ctx, +// RecordSituationPolicyActionType recordAction) { +// if (ctx instanceof AssignmentPolicyRuleEvaluationContext) { +// situationUpdater.prepareAssignmentSituationDeltas(); +// } else { +// situationUpdater.prepareObjectSituationDeltas(ctx.lensContext, recordAction); +// } +// } + // returns non-empty list if the constraints evaluated to true (if allMustApply, all of the constraints must apply; otherwise, at least one must apply) @SuppressWarnings("unchecked") @NotNull diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java index 5102a1869eb..ea46eb3e4be 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java @@ -276,4 +276,13 @@ private PropertyDelta createTriggerDelta(ItemPat return triggersDelta; } + public void applyAssignmentSituation(LensContext context, + EvaluatedAssignmentImpl evaluatedAssignment, + List rulesToRecord) { + // TODO + } + + public void applyObjectSituation(LensContext context, List rulesToRecord) { + + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/RulesEvaluationContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/RulesEvaluationContext.java new file mode 100644 index 00000000000..0ca6dc92085 --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/RulesEvaluationContext.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010-2017 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.model.impl.lens.projector.policy; + +import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author mederly + */ +public class RulesEvaluationContext { + + @NotNull final List rulesToRecord = new ArrayList<>(); // not private because it's final +} From 8c03cff38047503cc231f8a0dbb4ad280dfd3488 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Sat, 23 Sep 2017 13:47:43 +0200 Subject: [PATCH 02/19] Storing policy situations (new version). No optimizations yet. --- .../com/evolveum/midpoint/prism/Item.java | 7 + .../midpoint/prism/delta/ContainerDelta.java | 72 +++- .../prism/delta/builder/DeltaBuilder.java | 35 ++ .../prism/delta/builder/S_ValuesEntry.java | 5 +- .../model/impl/lens/ChangeExecutor.java | 5 - .../projector/AssignmentTripleEvaluator.java | 8 +- .../policy/PolicySituationUpdater.java | 342 +++++++----------- 7 files changed, 237 insertions(+), 237 deletions(-) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/Item.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/Item.java index 2ec49b934ce..4a92db4d7b4 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/Item.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/Item.java @@ -32,6 +32,7 @@ import java.lang.reflect.Constructor; import java.util.*; import java.util.function.Function; +import java.util.stream.Collectors; /** * Item is a common abstraction of Property and PropertyContainer. @@ -312,6 +313,12 @@ public PrismValue findValue(PrismValue value, boolean ignoreMetadata) { return null; } + public List findValuesIgnoreMetadata(PrismValue value) { + return getValues().stream() + .filter(v -> v.equalsComplex(value, true, false)) + .collect(Collectors.toList()); + } + /** * Returns value that is previous to the specified value. * Note that the order is semantically insignificant and this is used only diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java index 0f91ab239cb..1d593a1379d 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java @@ -27,6 +27,8 @@ import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.MiscUtil; import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import org.apache.commons.collections4.CollectionUtils; public class ContainerDelta extends ItemDelta,PrismContainerDefinition> implements PrismContainerable { @@ -183,19 +185,21 @@ private Collection findItemValues(Long id, ItemPath path, Collection void expand(PrismObject object) throws SchemaException { + public void expand(PrismObject object, Trace logger) throws SchemaException { + PrismContainer container = null; + ItemPath path = this.getPath(); + if (object != null) { + container = object.findContainer(path); + } if (valuesToDelete != null) { - ItemPath path = this.getPath(); - PrismContainer container = null; - if (object != null) { - container = object.findContainer(path); - } Iterator> iterator = valuesToDelete.iterator(); while (iterator.hasNext()) { PrismContainerValue deltaCVal = iterator.next(); - if ((deltaCVal.getItems() == null || deltaCVal.getItems().isEmpty())) { + if (CollectionUtils.isEmpty(deltaCVal.getItems())) { Long id = deltaCVal.getId(); if (id == null) { throw new IllegalArgumentException("No id and no items in value "+deltaCVal+" in delete set in "+this); @@ -206,17 +210,65 @@ public void expand(PrismObject object) throws SchemaEx for (Item containerItem: containerCVal.getItems()) { deltaCVal.add(containerItem.clone()); } - continue; } } // id-only value with ID that is not in the object any more: delete the value from delta iterator.remove(); + } else if (deltaCVal.getId() == null) { + if (container != null) { + @SuppressWarnings("unchecked") + List> containerCVals = + (List>) + container.findValuesIgnoreMetadata(deltaCVal); + if (containerCVals.size() > 1) { + logger.warn("More values to be deleted are matched by a single value in delete delta: values={}, delta value={}", + containerCVals, deltaCVal); + } else if (containerCVals.size() == 1) { + deltaCVal.setId(containerCVals.get(0).getId()); + } + // for the time being let's keep non-existent values in the delta + } } } } + if (valuesToAdd != null) { + assert valuesToReplace == null; + long maxId = getMaxId(container); + processIdentifiers(maxId, valuesToAdd); + } + if (valuesToReplace != null) { + assert valuesToAdd == null; + processIdentifiers(0, valuesToReplace); + } } - @Override + private void processIdentifiers(long maxId, Collection> values) { + for (PrismContainerValue value : values) { + if (value.getId() != null && value.getId() > maxId) { + maxId = value.getId(); + } + } + for (PrismContainerValue value : values) { + if (value.getId() == null) { + value.setId(++maxId); + } + } + } + + private long getMaxId(PrismContainer container) { + if (container == null) { + return 0; + } + long max = 0; + for (PrismContainerValue value : container.getValues()) { + if (value.getId() != null && value.getId() > max) { + max = value.getId(); + } + } + return max; + } + + @Override protected boolean isValueEquivalent(PrismContainerValue a, PrismContainerValue b) { if (!super.isValueEquivalent(a, b)) { return false; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java index 3c73ce36cb7..5cca1f15da8 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java @@ -185,6 +185,41 @@ public S_MaybeDelete add(Collection values) { return this; } + @Override + public S_ValuesEntry old(Object... realValues) { + return oldRealValues(Arrays.asList(realValues)); + } + + @Override + public S_ValuesEntry oldRealValues(Collection realValues) { + for (Object v : realValues) { + if (v != null) { + currentDelta.addEstimatedOldValue(toPrismValue(currentDelta, v)); + } + } + return this; + } + + @Override + public S_ValuesEntry old(PrismValue... values) { + for (PrismValue v : values) { + if (v != null) { + currentDelta.addEstimatedOldValue(v); + } + } + return this; + } + + @Override + public S_ValuesEntry old(Collection values) { + for (PrismValue v : values) { + if (v != null) { + currentDelta.addEstimatedOldValue(v); + } + } + return this; + } + @Override public S_ItemEntry delete(Object... realValues) { return deleteRealValues(Arrays.asList(realValues)); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java index 3ab8f9de9d0..25237c86a6d 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java @@ -42,5 +42,8 @@ public interface S_ValuesEntry { S_ItemEntry replaceRealValues(Collection realValues); S_ItemEntry replace(PrismValue... values); S_ItemEntry replace(Collection values); - + S_ValuesEntry old(Object... realValues); + S_ValuesEntry oldRealValues(Collection realValues); + S_ValuesEntry old(PrismValue... values); + S_ValuesEntry old(Collection values); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java index 6fc341b5c85..0b8bc1efbcd 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java @@ -155,11 +155,6 @@ public boolean executeChanges(LensContext context, Tas } focusContext.clearPendingPolicySituationModifications(); - if (!focusContext.isDelete()) { - focusDelta = policySituationUpdater.applyAssignmentSituation(context, focusDelta); - policySituationUpdater.storeFocusPolicySituation(context); - } - if (focusDelta != null) { ObjectPolicyConfigurationType objectPolicyConfigurationType = focusContext diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentTripleEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentTripleEvaluator.java index 075f78d5768..812273c3c60 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentTripleEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentTripleEvaluator.java @@ -140,7 +140,13 @@ public DeltaSetTriple> processAllAssignments() throws ObjectDelta focusDelta = focusContext.getDelta(); ContainerDelta assignmentDelta = getExecutionWaveAssignmentDelta(focusContext); - assignmentDelta.expand(focusContext.getObjectCurrent()); + assignmentDelta.expand(focusContext.getObjectCurrent(), LOGGER); + + // Now we should have IDs for all assignments except for some borderline ones used in delete deltas + // (if the value to be deleted is not in object or if the value is ambiguous). This could have some negative + // impact on policy rules; namely, if there are some policy situations determined for such assignments, + // and the processing ends prematurely, it is possible that these situations will not be recorded. + // TODO determine if it's really this case LOGGER.trace("Assignment delta:\n{}", assignmentDelta.debugDump()); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java index ea46eb3e4be..a14da94f58c 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java @@ -32,11 +32,11 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.collections4.CollectionUtils; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.*; +import java.util.Objects; /** * Takes care of updating policySituation for focus and assignments. (Originally was a part of PolicyRuleProcessor.) @@ -51,238 +51,140 @@ public class PolicySituationUpdater { @Autowired private PrismContext prismContext; - public ObjectDelta applyAssignmentSituation(LensContext context, ObjectDelta focusDelta) - throws SchemaException { - if (context.getFocusClass() == null || !FocusType.class.isAssignableFrom(context.getFocusClass())) { - return focusDelta; - } - LensContext contextOfFocus = (LensContext) context; - if (focusDelta != null && focusDelta.isAdd()) { - applyAssignmentSituationOnAdd(contextOfFocus, (PrismObject) focusDelta.getObjectToAdd()); - return focusDelta; - } else if (focusDelta == null || focusDelta.isModify()) { - return applyAssignmentSituationOnModify(contextOfFocus, focusDelta); - } else { - return focusDelta; +// private List getTriggers(EvaluatedAssignmentImpl evaluatedAssignment) { +// List rv = new ArrayList<>(); +// for (EvaluatedPolicyRule policyRule : evaluatedAssignment.getAllTargetsPolicyRules()) { +// for (EvaluatedPolicyRuleTrigger trigger : policyRule.getTriggers()) { +// EvaluatedPolicyRuleTriggerType triggerType = trigger.toEvaluatedPolicyRuleTriggerType(policyRule, false).clone(); +// simplifyTrigger(triggerType); +// rv.add(triggerType); +// } +// } +// return rv; +// } +// +// private void simplifyTrigger(EvaluatedPolicyRuleTriggerType trigger) { +// deleteAssignments(trigger.getAssignmentPath()); +// if (trigger instanceof EvaluatedExclusionTriggerType) { +// EvaluatedExclusionTriggerType exclusionTrigger = (EvaluatedExclusionTriggerType) trigger; +// deleteAssignments(exclusionTrigger.getConflictingObjectPath()); +// exclusionTrigger.setConflictingAssignment(null); +// } else if (trigger instanceof EvaluatedSituationTriggerType) { +// for (EvaluatedPolicyRuleType sourceRule : ((EvaluatedSituationTriggerType) trigger).getSourceRule()) { +// for (EvaluatedPolicyRuleTriggerType sourceTrigger : sourceRule.getTrigger()) { +// simplifyTrigger(sourceTrigger); +// } +// } +// } +// } + +// private void deleteAssignments(AssignmentPathType path) { +// if (path == null) { +// return; +// } +// for (AssignmentPathSegmentType segment : path.getSegment()) { +// segment.setAssignment(null); +// } +// } + +// private boolean shouldSituationBeUpdated(EvaluatedAssignment evaluatedAssignment, +// List triggers) { +// if (PolicyRuleTypeUtil.canBePacked(evaluatedAssignment.getAssignmentType().getTrigger())) { +// return true; +// } +// Set currentSituations = new HashSet<>(evaluatedAssignment.getAssignmentType().getPolicySituation()); +// List currentTriggersUnpacked = PolicyRuleTypeUtil.unpack(evaluatedAssignment.getAssignmentType().getTrigger()); +// // if the current situations different from the ones in the old assignment => update +// // (provided that the situations in the assignment were _not_ changed directly via a delta!!!) TODO check this +// if (!currentSituations.equals(new HashSet<>(evaluatedAssignment.getPolicySituations()))) { +// LOGGER.trace("computed policy situations are different from the current ones"); +// return true; +// } +// if (!PolicyRuleTypeUtil.triggerCollectionsEqual(triggers, currentTriggersUnpacked)) { +// LOGGER.trace("computed policy rules triggers are different from the current ones"); +// return true; +// } +// return false; +// } + + + public void applyObjectSituation(LensContext context, List rulesToRecord) throws SchemaException { + // compute policySituation and triggeredPolicyRules and compare it with the expected state + // note that we use the new state for the comparison, because if values match we do not need to do anything + LensFocusContext focusContext = context.getFocusContext(); + F objectNew = focusContext.getObjectNew().asObjectable(); + ComputationResult cr = compute(rulesToRecord, objectNew.getPolicySituation(), objectNew.getTriggeredPolicyRule()); + if (cr.situationsNeedUpdate) { + focusContext.addToPendingPolicySituationModifications(DeltaBuilder.deltaFor(ObjectType.class, prismContext) + .item(ObjectType.F_POLICY_SITUATION) + .oldRealValues(cr.oldPolicySituations) + .replaceRealValues(cr.newPolicySituations) + .asItemDelta()); + } + if (cr.rulesNeedUpdate) { + focusContext.addToPendingPolicySituationModifications(DeltaBuilder.deltaFor(ObjectType.class, prismContext) + .item(ObjectType.F_TRIGGERED_POLICY_RULE) + .oldRealValues(cr.oldTriggeredRules) + .replaceRealValues(cr.newTriggeredRules) + .asItemDelta()); } } - private void applyAssignmentSituationOnAdd(LensContext context, - PrismObject objectToAdd) throws SchemaException { - if (context.getEvaluatedAssignmentTriple() == null) { - return; - } - T focus = objectToAdd.asObjectable(); - for (EvaluatedAssignmentImpl evaluatedAssignment : context.getEvaluatedAssignmentTriple().getNonNegativeValues()) { - LOGGER.trace("Applying assignment situation on object ADD for {}", evaluatedAssignment); - List triggers = getTriggers(evaluatedAssignment); - if (!shouldSituationBeUpdated(evaluatedAssignment, triggers)) { - continue; - } - AssignmentType assignment = evaluatedAssignment.getAssignmentType(); - if (assignment.getId() != null) { - ItemDelta.applyTo(getAssignmentModificationDelta(evaluatedAssignment, triggers), objectToAdd); + public void applyAssignmentSituation(LensContext context, + EvaluatedAssignmentImpl evaluatedAssignment, List rulesToRecord) throws SchemaException { + LensFocusContext focusContext = context.getFocusContext(); + AssignmentType assignment = evaluatedAssignment.getAssignmentType(false); + Long id = assignment.getId(); + ComputationResult cr = compute(rulesToRecord, assignment.getPolicySituation(), assignment.getTriggeredPolicyRule()); + boolean missedUpdate = false; + if (cr.situationsNeedUpdate) { + if (id != null) { + focusContext.addToPendingPolicySituationModifications(DeltaBuilder.deltaFor(ObjectType.class, prismContext) + .item(FocusType.F_ASSIGNMENT, id, AssignmentType.F_POLICY_SITUATION) + .oldRealValues(cr.oldPolicySituations) + .replaceRealValues(cr.newPolicySituations) + .asItemDelta()); } else { - int i = focus.getAssignment().indexOf(assignment); - if (i < 0) { - throw new IllegalStateException("Assignment to be replaced not found in an object to add: " + assignment + " / " + objectToAdd); - } - copyPolicyData(focus.getAssignment().get(i), evaluatedAssignment, triggers); + missedUpdate = true; } } - } - - private ObjectDelta applyAssignmentSituationOnModify(LensContext context, - ObjectDelta objectDelta) throws SchemaException { - if (context.getEvaluatedAssignmentTriple() == null) { - return objectDelta; - } - for (EvaluatedAssignmentImpl evaluatedAssignment : context.getEvaluatedAssignmentTriple().getNonNegativeValues()) { - LOGGER.trace("Applying assignment situation on object MODIFY for {}", evaluatedAssignment); - List triggers = getTriggers(evaluatedAssignment); - if (!shouldSituationBeUpdated(evaluatedAssignment, triggers)) { - continue; - } - AssignmentType assignment = evaluatedAssignment.getAssignmentType(); - if (assignment.getId() != null) { - objectDelta = swallow(context, objectDelta, getAssignmentModificationDelta(evaluatedAssignment, triggers)); + if (cr.rulesNeedUpdate) { + if (id != null) { + focusContext.addToPendingPolicySituationModifications(DeltaBuilder.deltaFor(ObjectType.class, prismContext) + .item(FocusType.F_ASSIGNMENT, id, AssignmentType.F_TRIGGERED_POLICY_RULE) + .oldRealValues(cr.oldTriggeredRules) + .replaceRealValues(cr.newTriggeredRules) + .asItemDelta()); } else { - if (objectDelta == null) { - throw new IllegalStateException("No object delta!"); - } - ContainerDelta assignmentDelta = objectDelta.findContainerDelta(FocusType.F_ASSIGNMENT); - if (assignmentDelta == null) { - throw new IllegalStateException("Unnumbered assignment (" + assignment - + ") couldn't be found in object delta (no assignment modification): " + objectDelta); - } - PrismContainerValue assignmentInDelta = assignmentDelta.findValueToAddOrReplace(assignment.asPrismContainerValue()); - if (assignmentInDelta == null) { - throw new IllegalStateException("Unnumbered assignment (" + assignment - + ") couldn't be found in object delta (no corresponding assignment value): " + objectDelta); - } - copyPolicyData(assignmentInDelta.asContainerable(), evaluatedAssignment, triggers); - } - } - return objectDelta; - } - - @NotNull - private List> getAssignmentModificationDelta( - EvaluatedAssignmentImpl evaluatedAssignment, List triggers) throws SchemaException { - Long id = evaluatedAssignment.getAssignmentType().getId(); - if (id == null) { - throw new IllegalArgumentException("Assignment with no ID: " + evaluatedAssignment); - } - List> deltas = new ArrayList<>(); - Set currentSituations = new HashSet<>(evaluatedAssignment.getAssignmentType().getPolicySituation()); - Set newSituations = new HashSet<>(evaluatedAssignment.getPolicySituations()); - CollectionUtils.addIgnoreNull(deltas, createSituationDelta( - new ItemPath(FocusType.F_ASSIGNMENT, id, AssignmentType.F_POLICY_SITUATION), currentSituations, newSituations)); - Set currentTriggers = new HashSet<>(evaluatedAssignment.getAssignmentType().getTrigger()); - Set newTriggers = new HashSet<>(PolicyRuleTypeUtil.pack(triggers)); - CollectionUtils.addIgnoreNull(deltas, createTriggerDelta( - new ItemPath(FocusType.F_ASSIGNMENT, id, AssignmentType.F_TRIGGER), currentTriggers, newTriggers)); - return deltas; - } - - private ObjectDelta swallow(LensContext context, ObjectDelta objectDelta, - List> deltas) throws SchemaException { - if (deltas.isEmpty()) { - return objectDelta; - } - if (objectDelta == null) { - if (context.getFocusClass() == null) { - throw new IllegalStateException("No focus class in " + context); - } - if (context.getFocusContext() == null) { - throw new IllegalStateException("No focus context in " + context); + missedUpdate = true; } - objectDelta = (ObjectDelta) new ObjectDelta(context.getFocusClass(), ChangeType.MODIFY, prismContext); - objectDelta.setOid(context.getFocusContext().getOid()); } - objectDelta.swallow(deltas); - return objectDelta; - } - - private List getTriggers(EvaluatedAssignmentImpl evaluatedAssignment) { - List rv = new ArrayList<>(); - for (EvaluatedPolicyRule policyRule : evaluatedAssignment.getAllTargetsPolicyRules()) { - for (EvaluatedPolicyRuleTrigger trigger : policyRule.getTriggers()) { - EvaluatedPolicyRuleTriggerType triggerType = trigger.toEvaluatedPolicyRuleTriggerType(policyRule, false).clone(); - simplifyTrigger(triggerType); - rv.add(triggerType); - } + if (missedUpdate) { + LOGGER.warn("Policy situation/rules for assignment cannot be updated, because it has no ID; assignment = {}, in object {}", + assignment, focusContext.getObjectAny()); } - return rv; } - private void simplifyTrigger(EvaluatedPolicyRuleTriggerType trigger) { - deleteAssignments(trigger.getAssignmentPath()); - if (trigger instanceof EvaluatedExclusionTriggerType) { - EvaluatedExclusionTriggerType exclusionTrigger = (EvaluatedExclusionTriggerType) trigger; - deleteAssignments(exclusionTrigger.getConflictingObjectPath()); - exclusionTrigger.setConflictingAssignment(null); - } else if (trigger instanceof EvaluatedSituationTriggerType) { - for (EvaluatedPolicyRuleType sourceRule : ((EvaluatedSituationTriggerType) trigger).getSourceRule()) { - for (EvaluatedPolicyRuleTriggerType sourceTrigger : sourceRule.getTrigger()) { - simplifyTrigger(sourceTrigger); - } - } - } + private ComputationResult compute(@NotNull List rulesToRecord, @NotNull List existingPolicySituation, + @NotNull List existingTriggeredPolicyRule) { + ComputationResult cr = new ComputationResult(); + for (EvaluatedPolicyRule rule : rulesToRecord) { + cr.newPolicySituations.add(rule.getPolicySituation()); + cr.newTriggeredRules.add(rule.toEvaluatedPolicyRuleType(true)); + } + cr.oldPolicySituations.addAll(existingPolicySituation); + cr.oldTriggeredRules.addAll(existingTriggeredPolicyRule); + cr.situationsNeedUpdate = !Objects.equals(cr.oldPolicySituations, cr.newPolicySituations); + cr.rulesNeedUpdate = !Objects.equals(cr.oldTriggeredRules, cr.newTriggeredRules); + return cr; } - private void deleteAssignments(AssignmentPathType path) { - if (path == null) { - return; - } - for (AssignmentPathSegmentType segment : path.getSegment()) { - segment.setAssignment(null); - } - } - - private void copyPolicyData(AssignmentType targetAssignment, EvaluatedAssignmentImpl evaluatedAssignment, - List triggers) { - targetAssignment.getPolicySituation().clear(); - targetAssignment.getPolicySituation().addAll(evaluatedAssignment.getPolicySituations()); - targetAssignment.getTrigger().clear(); - targetAssignment.getTrigger().addAll(PolicyRuleTypeUtil.pack(triggers)); - } - - private boolean shouldSituationBeUpdated(EvaluatedAssignment evaluatedAssignment, - List triggers) { - if (PolicyRuleTypeUtil.canBePacked(evaluatedAssignment.getAssignmentType().getTrigger())) { - return true; - } - Set currentSituations = new HashSet<>(evaluatedAssignment.getAssignmentType().getPolicySituation()); - List currentTriggersUnpacked = PolicyRuleTypeUtil.unpack(evaluatedAssignment.getAssignmentType().getTrigger()); - // if the current situations different from the ones in the old assignment => update - // (provided that the situations in the assignment were _not_ changed directly via a delta!!!) TODO check this - if (!currentSituations.equals(new HashSet<>(evaluatedAssignment.getPolicySituations()))) { - LOGGER.trace("computed policy situations are different from the current ones"); - return true; - } - if (!PolicyRuleTypeUtil.triggerCollectionsEqual(triggers, currentTriggersUnpacked)) { - LOGGER.trace("computed policy rules triggers are different from the current ones"); - return true; - } - return false; - } - - public void storeFocusPolicySituation(LensContext context) - throws SchemaException { - if (context.getFocusContext() == null || context.getFocusClass() == null || !FocusType.class.isAssignableFrom(context.getFocusClass())) { - return; - } - @SuppressWarnings({"raw", "unchecked"}) - LensFocusContext focusContext = (LensFocusContext) context.getFocusContext(); - Set currentSituations = focusContext.getObjectCurrent() != null ? - new HashSet<>(focusContext.getObjectCurrent().asObjectable().getPolicySituation()) : Collections.emptySet(); - Set newSituations = new HashSet<>(focusContext.getPolicySituations()); - PropertyDelta situationsDelta = createSituationDelta( - new ItemPath(FocusType.F_POLICY_SITUATION), currentSituations, newSituations); - if (situationsDelta != null) { - focusContext.swallowToProjectionWaveSecondaryDelta(situationsDelta); - } - } - - @Nullable - private PropertyDelta createSituationDelta(ItemPath path, Set currentSituations, Set newSituations) - throws SchemaException { - if (newSituations.equals(currentSituations)) { - return null; - } - @SuppressWarnings({ "unchecked", "raw" }) - PropertyDelta situationsDelta = (PropertyDelta) DeltaBuilder.deltaFor(FocusType.class, prismContext) - .item(path) - .add(CollectionUtils.subtract(newSituations, currentSituations).toArray()) - .delete(CollectionUtils.subtract(currentSituations, newSituations).toArray()) - .asItemDelta(); - situationsDelta.setEstimatedOldValues(PrismPropertyValue.wrap(currentSituations)); - return situationsDelta; - } - - private PropertyDelta createTriggerDelta(ItemPath path, Set currentTriggers, Set newTriggers) - throws SchemaException { - if (newTriggers.equals(currentTriggers)) { - return null; - } - @SuppressWarnings({ "unchecked", "raw" }) - PropertyDelta triggersDelta = (PropertyDelta) - DeltaBuilder.deltaFor(FocusType.class, prismContext) - .item(path) - .replace(newTriggers.toArray()) // TODO or add + delete? - .asItemDelta(); - triggersDelta.setEstimatedOldValues(PrismPropertyValue.wrap(currentTriggers)); - return triggersDelta; - } - - public void applyAssignmentSituation(LensContext context, - EvaluatedAssignmentImpl evaluatedAssignment, - List rulesToRecord) { - // TODO - } - - public void applyObjectSituation(LensContext context, List rulesToRecord) { - + private class ComputationResult { + final Set oldPolicySituations = new HashSet<>(); + final Set newPolicySituations = new HashSet<>(); + final Set oldTriggeredRules = new HashSet<>(); + final Set newTriggeredRules = new HashSet<>(); + boolean situationsNeedUpdate; + boolean rulesNeedUpdate; } } From 1dd3970dba8eb6a0de372423cd6c066688dbdfcb Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Sat, 23 Sep 2017 13:56:01 +0200 Subject: [PATCH 03/19] Fixed "privileged" flag. --- .../model/impl/scripting/ExecutionContext.java | 9 +++------ .../impl/scripting/ScriptingExpressionEvaluator.java | 11 +++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ExecutionContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ExecutionContext.java index d00c56ef2f9..314f3dc1709 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ExecutionContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ExecutionContext.java @@ -38,7 +38,7 @@ public class ExecutionContext { private static final Trace LOGGER = TraceManager.getTrace(ExecutionContext.class); - private boolean privileged; + private final boolean privileged; private final ScriptingExpressionEvaluationOptionsType options; private final Task task; private final ScriptingExpressionEvaluator scriptingExpressionEvaluator; @@ -49,10 +49,11 @@ public class ExecutionContext { public ExecutionContext(ScriptingExpressionEvaluationOptionsType options, Task task, ScriptingExpressionEvaluator scriptingExpressionEvaluator, - Map initialVariables) { + boolean privileged, Map initialVariables) { this.options = options; this.task = task; this.scriptingExpressionEvaluator = scriptingExpressionEvaluator; + this.privileged = privileged; this.initialVariables = initialVariables; } @@ -143,8 +144,4 @@ public PrismContext getPrismContext() { public boolean isPrivileged() { return privileged; } - - public void setPrivileged(boolean privileged) { - this.privileged = privileged; - } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java index 97c4d86ff13..18fe3454a20 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java @@ -141,7 +141,7 @@ public void evaluateExpressionInBackground(ExecuteScriptType executeScriptComman */ public ExecutionContext evaluateExpression(ScriptingExpressionType expression, Task task, OperationResult result) throws ScriptExecutionException { - ExecutionContext context = evaluateExpression(expression, PipelineData.createEmpty(), null, emptyMap(), task, result); + ExecutionContext context = evaluateExpression(expression, PipelineData.createEmpty(), null, emptyMap(), false, task, result); context.computeResults(); return context; } @@ -155,7 +155,7 @@ public ExecutionContext evaluateExpression(@NotNull ExecuteScriptType executeScr public ExecutionContext evaluateExpression(@NotNull ExecuteScriptType executeScript, @NotNull Map initialVariables, Task task, OperationResult result) throws ScriptExecutionException { Validate.notNull(executeScript.getScriptingExpression(), "Scripting expression must be present"); ExecutionContext context = evaluateExpression(executeScript.getScriptingExpression().getValue(), - PipelineData.parseFrom(executeScript.getInput(), initialVariables, prismContext), executeScript.getOptions(), initialVariables, task, result); + PipelineData.parseFrom(executeScript.getInput(), initialVariables, prismContext), executeScript.getOptions(), initialVariables, false, task, result); context.computeResults(); return context; } @@ -164,8 +164,7 @@ public ExecutionContext evaluateExpression(@NotNull ExecuteScriptType executeScr public ExecutionContext evaluateExpressionPrivileged(@NotNull ExecuteScriptType executeScript, @NotNull Map initialVariables, Task task, OperationResult result) throws ScriptExecutionException { Validate.notNull(executeScript.getScriptingExpression(), "Scripting expression must be present"); ExecutionContext context = evaluateExpression(executeScript.getScriptingExpression().getValue(), - PipelineData.parseFrom(executeScript.getInput(), initialVariables, prismContext), executeScript.getOptions(), initialVariables, task, result); - context.setPrivileged(true); + PipelineData.parseFrom(executeScript.getInput(), initialVariables, prismContext), executeScript.getOptions(), initialVariables, true, task, result); context.computeResults(); return context; } @@ -173,8 +172,8 @@ public ExecutionContext evaluateExpressionPrivileged(@NotNull ExecuteScriptType // main entry point from the outside private ExecutionContext evaluateExpression(ScriptingExpressionType expression, PipelineData data, ScriptingExpressionEvaluationOptionsType options, Map initialVariables, - Task task, OperationResult result) throws ScriptExecutionException { - ExecutionContext context = new ExecutionContext(options, task, this, initialVariables); + boolean privileged, Task task, OperationResult result) throws ScriptExecutionException { + ExecutionContext context = new ExecutionContext(options, task, this, privileged, initialVariables); PipelineData output; try { output = evaluateExpression(expression, data, context, result); From 84c6889cf3b9db99b5ce37d76423c36fc15af92d Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 25 Sep 2017 13:35:50 +0200 Subject: [PATCH 04/19] Storing policy state works for most basic scenarios. --- .../midpoint/prism/PrismContainerValue.java | 4 + .../midpoint/prism/delta/ContainerDelta.java | 37 +--- .../midpoint/prism/delta/ItemDelta.java | 6 + .../midpoint/prism/path/ItemPath.java | 26 +-- .../public/common/common-model-context-3.xsd | 2 +- .../com/evolveum/midpoint/util/MiscUtil.java | 2 +- .../model/api/context/AssignmentPath.java | 2 +- .../api/context/AssignmentPathSegment.java | 2 +- .../context/EvaluatedCompositeTrigger.java | 7 +- .../context/EvaluatedExclusionTrigger.java | 10 +- .../EvaluatedHasAssignmentTrigger.java | 4 +- .../context/EvaluatedModificationTrigger.java | 4 +- .../context/EvaluatedMultiplicityTrigger.java | 4 +- .../api/context/EvaluatedPolicyRule.java | 2 +- .../context/EvaluatedPolicyRuleTrigger.java | 16 +- .../context/EvaluatedSituationTrigger.java | 6 +- .../api/context/EvaluatedStateTrigger.java | 4 +- .../context/EvaluatedTimeValidityTrigger.java | 4 +- .../context/EvaluatedTransitionTrigger.java | 6 +- .../impl/hooks/PolicyRuleEnforcerHook.java | 3 +- .../model/impl/lens/AssignmentPathImpl.java | 5 +- .../impl/lens/AssignmentPathSegmentImpl.java | 6 +- .../model/impl/lens/AssignmentSpec.java | 60 ++++++ .../model/impl/lens/ChangeExecutor.java | 100 +++++++-- .../impl/lens/EvaluatedAssignmentImpl.java | 15 +- .../impl/lens/EvaluatedPolicyRuleImpl.java | 12 +- .../model/impl/lens/LensElementContext.java | 53 ++++- .../model/impl/lens/LensFocusContext.java | 25 +++ .../projector/AssignmentTripleEvaluator.java | 6 - .../impl/lens/projector/FocusProcessor.java | 3 +- .../projector/policy/PolicyRuleProcessor.java | 17 +- .../policy/PolicySituationUpdater.java | 190 ------------------ .../projector/policy/PolicyStateUpdater.java | 127 ++++++++++++ .../model/impl/lens/TestPolicyMetadata.java | 2 +- .../model/impl/lens/TestPolicyRules2.java | 26 +-- .../lens/role-judge-situation-only.xml | 3 +- .../lens/role-pirate-situation-only.xml | 1 + .../src/test/resources/lens/role-thief.xml | 5 +- .../intest/rbac/TestSegregationOfDuties.java | 2 +- .../primary/policy/ApprovalSchemaBuilder.java | 2 +- 40 files changed, 461 insertions(+), 350 deletions(-) create mode 100644 model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentSpec.java delete mode 100644 model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java create mode 100644 model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java index 8293d9db067..fb8d0623d82 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java @@ -1648,6 +1648,10 @@ public static List asContainerables(List c.asContainerable()).collect(Collectors.toList()); } + public static Collection asContainerables(Collection> pcvs) { + return pcvs.stream().map(c -> c.asContainerable()).collect(Collectors.toList()); + } + /** * Set origin type to all values and subvalues */ diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java index 1d593a1379d..eb092c43e75 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java @@ -187,7 +187,7 @@ private Collection findItemValues(Long id, ItemPath path, Collection void expand(PrismObject object, Trace logger) throws SchemaException { PrismContainer container = null; @@ -231,41 +231,6 @@ public void expand(PrismObject object, Trace logger) t } } } - if (valuesToAdd != null) { - assert valuesToReplace == null; - long maxId = getMaxId(container); - processIdentifiers(maxId, valuesToAdd); - } - if (valuesToReplace != null) { - assert valuesToAdd == null; - processIdentifiers(0, valuesToReplace); - } - } - - private void processIdentifiers(long maxId, Collection> values) { - for (PrismContainerValue value : values) { - if (value.getId() != null && value.getId() > maxId) { - maxId = value.getId(); - } - } - for (PrismContainerValue value : values) { - if (value.getId() == null) { - value.setId(++maxId); - } - } - } - - private long getMaxId(PrismContainer container) { - if (container == null) { - return 0; - } - long max = 0; - for (PrismContainerValue value : container.getValues()) { - if (value.getId() != null && value.getId() > max) { - max = value.getId(); - } - } - return max; } @Override diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java index 2d74a08b5b2..eac837d965b 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java @@ -1500,6 +1500,12 @@ private void filterValuesSet(Collection set, Function function) { public abstract ItemDelta clone(); + public ItemDelta cloneWithChangedParentPath(ItemPath newParentPath) { + ItemDelta clone = clone(); + clone.setParentPath(newParentPath); + return clone; + } + protected void copyValues(ItemDelta clone) { clone.definition = this.definition; clone.elementName = this.elementName; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index 6a95532dc20..0522eefa0ca 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -72,19 +72,21 @@ public ItemPath(String... names) { } } - public ItemPath(Object... namesOrIds) { - this.segments = new ArrayList<>(namesOrIds.length); - for (Object nameOrId : namesOrIds) { - if (nameOrId instanceof QName) { - add((QName) nameOrId); - } else if (nameOrId instanceof String) { - add(stringToQName((String) nameOrId)); - } else if (nameOrId instanceof Long) { - this.segments.add(new IdItemPathSegment((Long) nameOrId)); - } else if (nameOrId instanceof Integer) { - this.segments.add(new IdItemPathSegment(((Integer) nameOrId).longValue())); + public ItemPath(Object... namesOrIdsOrSegments) { + this.segments = new ArrayList<>(namesOrIdsOrSegments.length); + for (Object nameOrIdOrSegment : namesOrIdsOrSegments) { + if (nameOrIdOrSegment instanceof ItemPathSegment) { + add((ItemPathSegment) nameOrIdOrSegment); + } else if (nameOrIdOrSegment instanceof QName) { + add((QName) nameOrIdOrSegment); + } else if (nameOrIdOrSegment instanceof String) { + add(stringToQName((String) nameOrIdOrSegment)); + } else if (nameOrIdOrSegment instanceof Long) { + this.segments.add(new IdItemPathSegment((Long) nameOrIdOrSegment)); + } else if (nameOrIdOrSegment instanceof Integer) { + this.segments.add(new IdItemPathSegment(((Integer) nameOrIdOrSegment).longValue())); } else { - throw new IllegalArgumentException("Invalid item path segment value: " + nameOrId); + throw new IllegalArgumentException("Invalid item path segment value: " + nameOrIdOrSegment); } } } diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd index 0e306f80e99..f84179a5633 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd @@ -650,7 +650,7 @@ - + diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/MiscUtil.java b/infra/util/src/main/java/com/evolveum/midpoint/util/MiscUtil.java index 39adf59534b..4decf24e6f4 100644 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/MiscUtil.java +++ b/infra/util/src/main/java/com/evolveum/midpoint/util/MiscUtil.java @@ -610,7 +610,7 @@ public static String nullIfEmpty(String s) { } /** - * Returns true if the collection contains at leat one pair of equals elements. + * Returns true if the collection contains at least one pair of equals elements. */ public static boolean hasDuplicates(Collection collection) { Set set = new HashSet<>(); diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/AssignmentPath.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/AssignmentPath.java index 2b0a4e008dd..1257f81954c 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/AssignmentPath.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/AssignmentPath.java @@ -68,5 +68,5 @@ public interface AssignmentPath extends DebugDumpable, ShortDumpable { @NotNull List getFirstOrderChain(); - AssignmentPathType toAssignmentPathType(); + AssignmentPathType toAssignmentPathType(boolean includeAssignmentsContent); } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/AssignmentPathSegment.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/AssignmentPathSegment.java index b71bd153eb3..4dd8af1a9ad 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/AssignmentPathSegment.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/AssignmentPathSegment.java @@ -74,5 +74,5 @@ public interface AssignmentPathSegment extends DebugDumpable, ShortDumpable { boolean isDelegation(); @NotNull - AssignmentPathSegmentType toAssignmentPathSegmentType(); + AssignmentPathSegmentType toAssignmentPathSegmentType(boolean includeAssignmentsContent); } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedCompositeTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedCompositeTrigger.java index ecfef70a89e..2f0207eda4d 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedCompositeTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedCompositeTrigger.java @@ -77,11 +77,12 @@ protected void debugDumpSpecific(StringBuilder sb, int indent) { } @Override - public EvaluatedLogicalTriggerType toEvaluatedPolicyRuleTriggerType(EvaluatedPolicyRule owningRule, boolean respectFinalFlag) { + public EvaluatedLogicalTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, + boolean respectFinalFlag) { EvaluatedLogicalTriggerType rv = new EvaluatedLogicalTriggerType(); - fillCommonContent(rv, owningRule); + fillCommonContent(rv); if (!respectFinalFlag || !isFinal()) { - innerTriggers.forEach(t -> rv.getEmbedded().add(t.toEvaluatedPolicyRuleTriggerType(owningRule, respectFinalFlag))); + innerTriggers.forEach(t -> rv.getEmbedded().add(t.toEvaluatedPolicyRuleTriggerType(includeAssignmentsContent, respectFinalFlag))); } return rv; } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java index ef6efd09109..cf3bbc72048 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java @@ -77,16 +77,18 @@ protected void debugDumpSpecific(StringBuilder sb, int indent) { } @Override - public EvaluatedExclusionTriggerType toEvaluatedPolicyRuleTriggerType(EvaluatedPolicyRule owningRule, + public EvaluatedExclusionTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, boolean respectFinalFlag) { EvaluatedExclusionTriggerType rv = new EvaluatedExclusionTriggerType(); - fillCommonContent(rv, owningRule); + fillCommonContent(rv); rv.setConflictingObjectRef(ObjectTypeUtil.createObjectRef(conflictingTarget)); rv.setConflictingObjectDisplayName(ObjectTypeUtil.getDisplayName(conflictingTarget)); if (conflictingPath != null) { - rv.setConflictingObjectPath(conflictingPath.toAssignmentPathType()); + rv.setConflictingObjectPath(conflictingPath.toAssignmentPathType(includeAssignmentsContent)); + } + if (includeAssignmentsContent && conflictingAssignment.getAssignmentType() != null) { + rv.setConflictingAssignment(conflictingAssignment.getAssignmentType().clone()); } - rv.setConflictingAssignment(conflictingAssignment.getAssignmentType()); return rv; } } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedHasAssignmentTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedHasAssignmentTrigger.java index 922eb62974f..18a2c178595 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedHasAssignmentTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedHasAssignmentTrigger.java @@ -31,10 +31,10 @@ public EvaluatedHasAssignmentTrigger(@NotNull PolicyConstraintKindType kind, @No } @Override - public EvaluatedHasAssignmentTriggerType toEvaluatedPolicyRuleTriggerType(EvaluatedPolicyRule owningRule, + public EvaluatedHasAssignmentTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, boolean respectFinalFlag) { EvaluatedHasAssignmentTriggerType rv = new EvaluatedHasAssignmentTriggerType(); - fillCommonContent(rv, owningRule); + fillCommonContent(rv); return rv; } } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedModificationTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedModificationTrigger.java index 9264e15378a..c89b4de5a0a 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedModificationTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedModificationTrigger.java @@ -31,10 +31,10 @@ public EvaluatedModificationTrigger(@NotNull PolicyConstraintKindType kind, @Not } @Override - public EvaluatedModificationTriggerType toEvaluatedPolicyRuleTriggerType(EvaluatedPolicyRule owningRule, + public EvaluatedModificationTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, boolean respectFinalFlag) { EvaluatedModificationTriggerType rv = new EvaluatedModificationTriggerType(); - fillCommonContent(rv, owningRule); + fillCommonContent(rv); return rv; } } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedMultiplicityTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedMultiplicityTrigger.java index f4f0bd9a047..3c4bc09bb1c 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedMultiplicityTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedMultiplicityTrigger.java @@ -31,10 +31,10 @@ public EvaluatedMultiplicityTrigger(@NotNull PolicyConstraintKindType kind, @Not } @Override - public EvaluatedMultiplicityTriggerType toEvaluatedPolicyRuleTriggerType(EvaluatedPolicyRule owningRule, + public EvaluatedMultiplicityTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, boolean respectFinalFlag) { EvaluatedMultiplicityTriggerType rv = new EvaluatedMultiplicityTriggerType(); - fillCommonContent(rv, owningRule); + fillCommonContent(rv); return rv; } } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java index c9399e27b9b..04c4eaf7ba3 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java @@ -66,7 +66,7 @@ default boolean isTriggered() { Collection getPolicyExceptions(); - EvaluatedPolicyRuleType toEvaluatedPolicyRuleType(boolean respectFinalFlag); + EvaluatedPolicyRuleType toEvaluatedPolicyRuleType(boolean includeAssignmentsContent, boolean respectFinalFlag); boolean isGlobal(); diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRuleTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRuleTrigger.java index 96b4ba6d6e8..4ee911c2a0f 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRuleTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRuleTrigger.java @@ -16,7 +16,6 @@ package com.evolveum.midpoint.model.api.context; import com.evolveum.midpoint.schema.util.LocalizationUtil; -import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.schema.util.PolicyRuleTypeUtil; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.DebugUtil; @@ -131,26 +130,17 @@ public String toDiagShortcut() { return PolicyRuleTypeUtil.toDiagShortcut(constraintKind); } - public EvaluatedPolicyRuleTriggerType toEvaluatedPolicyRuleTriggerType(EvaluatedPolicyRule owningRule, + public EvaluatedPolicyRuleTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, boolean respectFinalFlag) { EvaluatedPolicyRuleTriggerType rv = new EvaluatedPolicyRuleTriggerType(); - fillCommonContent(rv, owningRule); + fillCommonContent(rv); return rv; } - protected void fillCommonContent(EvaluatedPolicyRuleTriggerType tt, EvaluatedPolicyRule owningRule) { - tt.setRuleName(owningRule.getName()); + protected void fillCommonContent(EvaluatedPolicyRuleTriggerType tt) { tt.setConstraintKind(constraintKind); //tt.setConstraint(constraint); tt.setMessage(LocalizationUtil.createLocalizableMessageType(message)); - if (owningRule.getAssignmentPath() != null) { - tt.setAssignmentPath(owningRule.getAssignmentPath().toAssignmentPathType()); - } - ObjectType directOwner = owningRule.getDirectOwner(); - if (directOwner != null) { - tt.setDirectOwnerRef(ObjectTypeUtil.createObjectRef(directOwner)); - tt.setDirectOwnerDisplayName(ObjectTypeUtil.getDisplayName(directOwner)); - } PolicyConstraintPresentationType presentation = constraint.getPresentation(); if (presentation != null) { tt.setFinal(presentation.isFinal()); diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java index 950a6f41098..855bc15b062 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java @@ -103,12 +103,12 @@ protected void debugDumpSpecific(StringBuilder sb, int indent) { } @Override - public EvaluatedSituationTriggerType toEvaluatedPolicyRuleTriggerType(EvaluatedPolicyRule owningRule, + public EvaluatedSituationTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, boolean respectFinalFlag) { EvaluatedSituationTriggerType rv = new EvaluatedSituationTriggerType(); - fillCommonContent(rv, owningRule); + fillCommonContent(rv); if (!respectFinalFlag || !isFinal()) { - sourceRules.forEach(r -> rv.getSourceRule().add(r.toEvaluatedPolicyRuleType(false))); + sourceRules.forEach(r -> rv.getSourceRule().add(r.toEvaluatedPolicyRuleType(false, false))); } return rv; } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedStateTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedStateTrigger.java index b4c12197d4a..9b9ec499f4b 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedStateTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedStateTrigger.java @@ -33,9 +33,9 @@ public EvaluatedStateTrigger(@NotNull PolicyConstraintKindType kind, @NotNull St } @Override - public EvaluatedStateTriggerType toEvaluatedPolicyRuleTriggerType(EvaluatedPolicyRule owningRule, boolean respectFinalFlag) { + public EvaluatedStateTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, boolean respectFinalFlag) { EvaluatedStateTriggerType rv = new EvaluatedStateTriggerType(); - fillCommonContent(rv, owningRule); + fillCommonContent(rv); return rv; } } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTimeValidityTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTimeValidityTrigger.java index 2c29cab8aa4..4fce27c3fdf 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTimeValidityTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTimeValidityTrigger.java @@ -31,10 +31,10 @@ public EvaluatedTimeValidityTrigger(@NotNull PolicyConstraintKindType kind, @Not } @Override - public EvaluatedTimeValidityTriggerType toEvaluatedPolicyRuleTriggerType(EvaluatedPolicyRule owningRule, + public EvaluatedTimeValidityTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, boolean respectFinalFlag) { EvaluatedTimeValidityTriggerType rv = new EvaluatedTimeValidityTriggerType(); - fillCommonContent(rv, owningRule); + fillCommonContent(rv); return rv; } } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTransitionTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTransitionTrigger.java index ed0ab738e3b..6aa4ad9cc07 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTransitionTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTransitionTrigger.java @@ -75,12 +75,12 @@ protected void debugDumpSpecific(StringBuilder sb, int indent) { } @Override - public EvaluatedTransitionTriggerType toEvaluatedPolicyRuleTriggerType(EvaluatedPolicyRule owningRule, + public EvaluatedTransitionTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, boolean respectFinalFlag) { EvaluatedTransitionTriggerType rv = new EvaluatedTransitionTriggerType(); - fillCommonContent(rv, owningRule); + fillCommonContent(rv); if (!respectFinalFlag || !isFinal()) { - innerTriggers.forEach(t -> rv.getEmbedded().add(t.toEvaluatedPolicyRuleTriggerType(owningRule, respectFinalFlag))); + innerTriggers.forEach(t -> rv.getEmbedded().add(t.toEvaluatedPolicyRuleTriggerType(includeAssignmentsContent, respectFinalFlag))); } return rv; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java index 6b654e07fbc..5c9da6cc42e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java @@ -135,7 +135,8 @@ private void enforceTriggeredRules(EvaluationContext evalC continue; } - evalCtx.rules.add(policyRule.toEvaluatedPolicyRuleType(true)); + // TODO really include assignments content? + evalCtx.rules.add(policyRule.toEvaluatedPolicyRuleType(true, true)); for (EvaluatedPolicyRuleTrigger trigger: triggers) { if (trigger.getMessage() != null) { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPathImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPathImpl.java index 27227c86b58..a4bf880030e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPathImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPathImpl.java @@ -23,7 +23,6 @@ import com.evolveum.midpoint.model.api.context.AssignmentPath; import com.evolveum.midpoint.model.api.context.AssignmentPathSegment; -import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentPathType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; @@ -205,9 +204,9 @@ public void shortDump(StringBuilder sb) { } @Override - public AssignmentPathType toAssignmentPathType() { + public AssignmentPathType toAssignmentPathType(boolean includeAssignmentsContent) { AssignmentPathType rv = new AssignmentPathType(); - segments.forEach(seg -> rv.getSegment().add(seg.toAssignmentPathSegmentType())); + segments.forEach(seg -> rv.getSegment().add(seg.toAssignmentPathSegmentType(includeAssignmentsContent))); return rv; } } 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 8e8742b8953..4e973d96ca2 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 @@ -595,11 +595,13 @@ public String debugDump(int indent) { @NotNull @Override - public AssignmentPathSegmentType toAssignmentPathSegmentType() { + public AssignmentPathSegmentType toAssignmentPathSegmentType(boolean includeAssignmentsContent) { AssignmentPathSegmentType rv = new AssignmentPathSegmentType(); AssignmentType assignment = getAssignment(evaluatedForOld); // a bit of hack, but probably ok for now if (assignment != null) { - rv.setAssignment(assignment); + if (includeAssignmentsContent) { + rv.setAssignment(assignment.clone()); + } rv.setAssignmentId(assignment.getId()); } if (source != null) { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentSpec.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentSpec.java new file mode 100644 index 00000000000..713c04f4d3e --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentSpec.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010-2017 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.model.impl.lens; + +import com.evolveum.midpoint.prism.delta.PlusMinusZero; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import org.jetbrains.annotations.NotNull; + +import java.io.Serializable; +import java.util.Objects; + +/** + * A key for assignment:mode => modifications map (for policy state). + * + * @author mederly + */ +public class AssignmentSpec implements Serializable { + + @NotNull public final AssignmentType assignment; + @NotNull public final PlusMinusZero mode; + + public AssignmentSpec(@NotNull AssignmentType assignment, @NotNull PlusMinusZero mode) { + this.assignment = assignment; + this.mode = mode; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof AssignmentSpec)) + return false; + AssignmentSpec that = (AssignmentSpec) o; + return Objects.equals(assignment, that.assignment) && mode == that.mode; + } + + @Override + public int hashCode() { + return Objects.hash(assignment, mode); + } + + @Override + public String toString() { + return mode + ":" + assignment; + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java index 0b8bc1efbcd..9ea71d25a54 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java @@ -19,11 +19,13 @@ import static com.evolveum.midpoint.model.api.ProgressInformation.ActivityType.FOCUS_OPERATION; import static com.evolveum.midpoint.model.api.ProgressInformation.ActivityType.RESOURCE_OBJECT_OPERATION; import static com.evolveum.midpoint.model.api.ProgressInformation.StateType.ENTERING; +import static com.evolveum.midpoint.prism.PrismContainerValue.asContainerables; import static com.evolveum.midpoint.schema.internals.InternalsConfig.consistencyChecks; import com.evolveum.midpoint.common.Clock; import com.evolveum.midpoint.common.SynchronizationUtils; -import com.evolveum.midpoint.model.impl.lens.projector.policy.PolicySituationUpdater; +import com.evolveum.midpoint.model.impl.lens.projector.policy.PolicyStateUpdater; +import com.evolveum.midpoint.prism.delta.*; import com.evolveum.midpoint.repo.api.ConflictWatcher; import com.evolveum.midpoint.repo.common.expression.Expression; import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; @@ -42,12 +44,6 @@ import com.evolveum.midpoint.model.impl.util.Utils; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.crypto.EncryptionException; -import com.evolveum.midpoint.prism.delta.ChangeType; -import com.evolveum.midpoint.prism.delta.ItemDelta; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; -import com.evolveum.midpoint.prism.delta.PropertyDelta; -import com.evolveum.midpoint.prism.delta.ReferenceDelta; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.xnode.PrimitiveXNode; import com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions; @@ -88,6 +84,7 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.annotation.PostConstruct; import javax.xml.bind.JAXBElement; @@ -119,7 +116,7 @@ public class ChangeExecutor { @Autowired private Clock clock; @Autowired private ModelObjectResolver objectResolver; @Autowired private OperationalDataManager metadataManager; - @Autowired private PolicySituationUpdater policySituationUpdater; + @Autowired private PolicyStateUpdater policyStateUpdater; @Autowired private CredentialsProcessor credentialsProcessor; private PrismObjectDefinition userDefinition = null; @@ -150,10 +147,8 @@ public boolean executeChanges(LensContext context, Tas if (focusContext != null) { ObjectDelta focusDelta = focusContext.getWaveExecutableDelta(context.getExecutionWave()); - for (ItemDelta itemDelta : focusContext.getPendingPolicySituationModifications()) { - focusContext.swallowToSecondaryDelta(itemDelta); - } - focusContext.clearPendingPolicySituationModifications(); + focusDelta = applyPendingObjectPolicyStateModifications(focusContext, focusDelta); + applyPendingAssignmentPolicyStateModifications(focusContext, focusDelta); if (focusDelta != null) { @@ -371,6 +366,87 @@ public boolean executeChanges(LensContext context, Tas } + private ObjectDelta applyPendingObjectPolicyStateModifications(LensFocusContext focusContext, + ObjectDelta focusDelta) throws SchemaException { + for (ItemDelta itemDelta : focusContext.getPendingObjectPolicyStateModifications()) { + focusDelta = focusContext.swallowToDelta(focusDelta, itemDelta); + } + focusContext.clearPendingObjectPolicyStateModifications(); + return focusDelta; + } + + private void applyPendingAssignmentPolicyStateModifications(LensFocusContext focusContext, ObjectDelta focusDelta) + throws SchemaException { + if (focusDelta != null) { + for (Map.Entry>> entry : focusContext + .getPendingAssignmentPolicyStateModifications().entrySet()) { + PlusMinusZero mode = entry.getKey().mode; + if (mode == PlusMinusZero.MINUS) { + continue; // this assignment is being thrown out anyway, so let's ignore it + } + AssignmentType assignmentToFind = entry.getKey().assignment; + List> modifications = entry.getValue(); + if (modifications.isEmpty()) { + continue; + } + LOGGER.trace("Applying policy state modifications for {} ({}):\n{}", assignmentToFind, mode, + DebugUtil.debugDumpLazily(modifications)); + if (mode == PlusMinusZero.ZERO) { + if (assignmentToFind.getId() == null) { + throw new IllegalStateException("Existing assignment with null id: " + assignmentToFind); + } + for (ItemDelta modification : modifications) { + focusContext.swallowToDelta(focusDelta, modification); + } + } else { + assert mode == PlusMinusZero.PLUS; + if (focusDelta.isAdd()) { + swallowIntoValues(((FocusType) focusDelta.getObjectToAdd().asObjectable()).getAssignment(), + assignmentToFind, modifications); + } else { + ContainerDelta assignmentDelta = focusDelta.findContainerDelta(FocusType.F_ASSIGNMENT); + if (assignmentDelta == null) { + throw new IllegalStateException( + "We have 'plus' assignment to modify but there's no assignment delta. Assignment=" + + assignmentToFind + ", objectDelta=" + focusDelta); + } + if (assignmentDelta.isReplace()) { + swallowIntoValues(asContainerables(assignmentDelta.getValuesToReplace()), assignmentToFind, + modifications); + } else if (assignmentDelta.isAdd()) { + swallowIntoValues(asContainerables(assignmentDelta.getValuesToAdd()), assignmentToFind, + modifications); + } else { + throw new IllegalStateException( + "We have 'plus' assignment to modify but there're no values to add or replace in assignment delta. Assignment=" + + assignmentToFind + ", objectDelta=" + focusDelta); + } + } + } + } + } + focusContext.clearPendingAssignmentPolicyStateModifications(); + } + + private void swallowIntoValues(Collection assignments, AssignmentType assignmentToFind, List> modifications) + throws SchemaException { + for (AssignmentType assignment : assignments) { + PrismContainerValue pcv = assignment.asPrismContainerValue(); + PrismContainerValue pcvToFind = assignmentToFind.asPrismContainerValue(); + if (pcv.representsSameValue(pcvToFind, false) || pcv.equalsRealValue(pcvToFind)) { + // TODO what if ID of the assignment being added is changed in repo? Hopefully it will be not. + for (ItemDelta modification : modifications) { + ItemPath newParentPath = modification.getParentPath().rest().rest(); // killing assignment + ID + ItemDelta pathRelativeModification = modification.cloneWithChangedParentPath(newParentPath); + pathRelativeModification.applyTo(pcv); + } + return; + } + } + // TODO change to warning + throw new IllegalStateException("We have 'plus' assignment to modify but it couldn't be found in assignment delta. Assignment=" + assignmentToFind + ", new assignments=" + assignments); + } + private boolean shouldBeDeleted(ObjectDelta accDelta, LensProjectionContext accCtx) { return (accDelta == null || accDelta.isEmpty()) && (accCtx.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.DELETE diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java index 634c4f168b9..0f2193aaeee 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java @@ -512,9 +512,9 @@ public String toString() { public String toHumanReadableString() { if (target != null) { return "EvaluatedAssignment(" + target + ")"; - } else if (constructionTriple != null && !constructionTriple.isEmpty()) { + } else if (!constructionTriple.isEmpty()) { return "EvaluatedAssignment(" + constructionTriple + ")"; - } else if (personaConstructionTriple != null && !personaConstructionTriple.isEmpty()) { + } else if (!personaConstructionTriple.isEmpty()) { return "EvaluatedAssignment(" + personaConstructionTriple + ")"; } else { return toString(); @@ -527,4 +527,15 @@ public List getNonNegativeTargets() { rv.addAll(roles.getPlusSet()); return rv; } + + @NotNull + public PlusMinusZero getMode() { + if (assignmentIdi.getItemOld() == null) { + return PlusMinusZero.PLUS; + } else if (assignmentIdi.getItemNew() == null) { + return PlusMinusZero.MINUS; + } else { + return PlusMinusZero.ZERO; + } + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java index 0795f421ad8..67391dac922 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java @@ -312,10 +312,18 @@ private void createMessageTreeNode(TreeNode root, EvaluatedP */ @Override - public EvaluatedPolicyRuleType toEvaluatedPolicyRuleType(boolean respectFinalFlag) { + public EvaluatedPolicyRuleType toEvaluatedPolicyRuleType(boolean includeAssignmentsContent, boolean respectFinalFlag) { EvaluatedPolicyRuleType rv = new EvaluatedPolicyRuleType(); //rv.setPolicyRule(policyRuleType); // DO NOT use this, in order to avoid large data in assignments - triggers.forEach(t -> rv.getTrigger().add(t.toEvaluatedPolicyRuleTriggerType(this, respectFinalFlag))); + rv.setRuleName(getName()); + if (assignmentPath != null) { + rv.setAssignmentPath(assignmentPath.toAssignmentPathType(includeAssignmentsContent)); + } + if (directOwner != null) { + rv.setDirectOwnerRef(ObjectTypeUtil.createObjectRef(directOwner)); + rv.setDirectOwnerDisplayName(ObjectTypeUtil.getDisplayName(directOwner)); + } + triggers.forEach(t -> rv.getTrigger().add(t.toEvaluatedPolicyRuleTriggerType(includeAssignmentsContent, respectFinalFlag))); return rv; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java index fee71efd96c..ad8ea5e5071 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java @@ -15,12 +15,11 @@ */ package com.evolveum.midpoint.model.impl.lens; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.*; import com.evolveum.midpoint.prism.ConsistencyCheckScope; import com.evolveum.midpoint.prism.Objectable; +import com.evolveum.midpoint.prism.delta.PlusMinusZero; import com.evolveum.midpoint.schema.DeltaConvertor; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; @@ -74,12 +73,17 @@ public abstract class LensElementContext implements ModelE private String iterationToken; /** - * These are policy situation modifications that should be applied regardless of how the clockwork is exited + * These are policy state modifications that should be applied regardless of how the clockwork is exited * (e.g. in primary state, in final state, with an exception). * * Currently implemented only for focus, not for projections. */ - @NotNull private transient final List> pendingPolicySituationModifications = new ArrayList<>(); + @NotNull private transient final List> pendingObjectPolicyStateModifications = new ArrayList<>(); + + /** + * Policy state modifications for assignments. + */ + @NotNull private transient final Map>> pendingAssignmentPolicyStateModifications = new HashMap<>(); /** * Initial intent regarding the account. It indicated what the initiator of the operation WANTS TO DO with the @@ -258,16 +262,43 @@ public void swallowToPrimaryDelta(ItemDelta itemDelta) throws SchemaExcepti public abstract void swallowToSecondaryDelta(ItemDelta itemDelta) throws SchemaException; - public List> getPendingPolicySituationModifications() { - return pendingPolicySituationModifications; + // TODO deduplicate with swallowToSecondaryDelta in LensFocusContext + public ObjectDelta swallowToDelta(ObjectDelta originalDelta, ItemDelta propDelta) throws SchemaException { + if (originalDelta == null) { + originalDelta = new ObjectDelta(getObjectTypeClass(), ChangeType.MODIFY, getPrismContext()); + originalDelta.setOid(getOid()); + } else if (originalDelta.containsModification(propDelta, true, true)) { + return originalDelta; + } + originalDelta.swallow(propDelta); + return originalDelta; + } + + @NotNull + public List> getPendingObjectPolicyStateModifications() { + return pendingObjectPolicyStateModifications; + } + + public void clearPendingObjectPolicyStateModifications() { + pendingObjectPolicyStateModifications.clear(); + } + + public void addToPendingObjectPolicyStateModifications(ItemDelta modification) { + pendingObjectPolicyStateModifications.add(modification); + } + + @NotNull + public Map>> getPendingAssignmentPolicyStateModifications() { + return pendingAssignmentPolicyStateModifications; } - public void clearPendingPolicySituationModifications() { - pendingPolicySituationModifications.clear(); + public void clearPendingAssignmentPolicyStateModifications() { + pendingAssignmentPolicyStateModifications.clear(); } - public void addToPendingPolicySituationModifications(ItemDelta modification) { - pendingPolicySituationModifications.add(modification); + public void addToPendingAssignmentPolicyStateModifications(@NotNull AssignmentType assignment, @NotNull PlusMinusZero mode, @NotNull ItemDelta modification) { + AssignmentSpec spec = new AssignmentSpec(assignment, mode); + pendingAssignmentPolicyStateModifications.computeIfAbsent(spec, k -> new ArrayList<>()).add(modification); } public boolean isAdd() { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensFocusContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensFocusContext.java index 7c661c2697e..00b44390cb2 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensFocusContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensFocusContext.java @@ -16,6 +16,8 @@ package com.evolveum.midpoint.model.impl.lens; import java.util.Collection; +import java.util.List; +import java.util.Map; import com.evolveum.midpoint.repo.common.expression.ObjectDeltaObject; import com.evolveum.midpoint.prism.Objectable; @@ -368,6 +370,29 @@ public String debugDump(int indent, boolean showTriples) { sb.append(secondaryDeltas.debugDump(indent + 2)); } + // pending policy state modifications (object + assignments) + sb.append("\n"); + DebugUtil.indentDebugDump(sb, indent + 1); + sb.append(getDebugDumpTitle("pending object policy state modifications")).append(":"); + if (getPendingObjectPolicyStateModifications().isEmpty()) { + sb.append(" empty"); + } else { + sb.append("\n"); + sb.append(DebugUtil.debugDump(getPendingObjectPolicyStateModifications(), indent + 2)); + } + + for (Map.Entry>> entry : getPendingAssignmentPolicyStateModifications().entrySet()) { + sb.append("\n"); + DebugUtil.indentDebugDump(sb, indent + 1); + sb.append(getDebugDumpTitle("pending assignment policy state modifications for ")).append(entry.getKey()).append(":"); + if (entry.getValue().isEmpty()) { + sb.append(" empty"); + } else { + sb.append("\n"); + sb.append(DebugUtil.debugDump(entry.getValue(), indent + 2)); + } + } + sb.append("\n"); DebugUtil.debugDumpWithLabel(sb, getDebugDumpTitle("executed deltas"), getExecutedDeltas(), indent+1); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentTripleEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentTripleEvaluator.java index 812273c3c60..b5ee38a9fb6 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentTripleEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentTripleEvaluator.java @@ -142,12 +142,6 @@ public DeltaSetTriple> processAllAssignments() throws ContainerDelta assignmentDelta = getExecutionWaveAssignmentDelta(focusContext); assignmentDelta.expand(focusContext.getObjectCurrent(), LOGGER); - // Now we should have IDs for all assignments except for some borderline ones used in delete deltas - // (if the value to be deleted is not in object or if the value is ambiguous). This could have some negative - // impact on policy rules; namely, if there are some policy situations determined for such assignments, - // and the processing ends prematurely, it is possible that these situations will not be recorded. - // TODO determine if it's really this case - LOGGER.trace("Assignment delta:\n{}", assignmentDelta.debugDump()); SmartAssignmentCollection assignmentCollection = new SmartAssignmentCollection<>(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java index a72191f2adc..394435a633f 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java @@ -260,7 +260,8 @@ private void processFocusFocus(LensContext context, Str // ASSIGNMENTS - focusContext.clearPendingPolicySituationModifications(); + focusContext.clearPendingObjectPolicyStateModifications(); + focusContext.clearPendingAssignmentPolicyStateModifications(); LensUtil.partialExecute("assignments", () -> assignmentProcessor.processAssignmentsProjections(context, now, task, result), diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java index a04d3df97f0..a56794de0eb 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java @@ -69,7 +69,7 @@ public class PolicyRuleProcessor { @Autowired @Qualifier("cacheRepositoryService") private RepositoryService repositoryService; @Autowired private MappingFactory mappingFactory; @Autowired private MappingEvaluator mappingEvaluator; - @Autowired private PolicySituationUpdater situationUpdater; + @Autowired private PolicyStateUpdater policyStateUpdater; @Autowired private AssignmentConstraintEvaluator assignmentConstraintEvaluator; @Autowired private HasAssignmentConstraintEvaluator hasAssignmentConstraintEvaluator; @@ -149,7 +149,7 @@ public void evaluateAssignmentPolicyRules(LensContext c } } } - situationUpdater.applyAssignmentSituation(context, evaluatedAssignment, globalCtx.rulesToRecord); + policyStateUpdater.applyAssignmentState(context, evaluatedAssignment, globalCtx.rulesToRecord); } exclusionConstraintEvaluator.checkExclusionsLegacy(context, evaluatedAssignmentTriple.getPlusSet(), @@ -214,7 +214,7 @@ public void evaluateObjectPolicyRules(LensContext conte for (EvaluatedPolicyRule rule : situationRules) { evaluateFocusRule(rule, context, globalCtx, task, result); } - situationUpdater.applyObjectSituation(context, globalCtx.rulesToRecord); + policyStateUpdater.applyObjectState(context, globalCtx.rulesToRecord); } private Collection getAllGlobalRules(LensContext context) { @@ -319,21 +319,12 @@ private void evaluateRule(PolicyRuleEvaluationContext c } ctx.triggerRule(triggers); } - if (ctx.policyRule.getActions() != null && ctx.policyRule.getActions().getRecordSituation() != null) { + if (ctx.policyRule.isTriggered() && ctx.policyRule.getActions() != null && ctx.policyRule.getActions().getRecordSituation() != null) { ctx.record(); } traceRuleEvaluationResult(ctx.policyRule, ctx); } -// private void prepareSituationDeltas(PolicyRuleEvaluationContext ctx, -// RecordSituationPolicyActionType recordAction) { -// if (ctx instanceof AssignmentPolicyRuleEvaluationContext) { -// situationUpdater.prepareAssignmentSituationDeltas(); -// } else { -// situationUpdater.prepareObjectSituationDeltas(ctx.lensContext, recordAction); -// } -// } - // returns non-empty list if the constraints evaluated to true (if allMustApply, all of the constraints must apply; otherwise, at least one must apply) @SuppressWarnings("unchecked") @NotNull diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java deleted file mode 100644 index a14da94f58c..00000000000 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicySituationUpdater.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2010-2017 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.evolveum.midpoint.model.impl.lens.projector.policy; - -import com.evolveum.midpoint.model.api.context.EvaluatedAssignment; -import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule; -import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRuleTrigger; -import com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl; -import com.evolveum.midpoint.model.impl.lens.LensContext; -import com.evolveum.midpoint.model.impl.lens.LensFocusContext; -import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.delta.*; -import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.schema.util.PolicyRuleTypeUtil; -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 org.apache.commons.collections4.CollectionUtils; -import org.jetbrains.annotations.NotNull; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.*; -import java.util.Objects; - -/** - * Takes care of updating policySituation for focus and assignments. (Originally was a part of PolicyRuleProcessor.) - * - * @author semancik - * @author mederly - */ -@Component -public class PolicySituationUpdater { - - private static final Trace LOGGER = TraceManager.getTrace(PolicySituationUpdater.class); - - @Autowired private PrismContext prismContext; - -// private List getTriggers(EvaluatedAssignmentImpl evaluatedAssignment) { -// List rv = new ArrayList<>(); -// for (EvaluatedPolicyRule policyRule : evaluatedAssignment.getAllTargetsPolicyRules()) { -// for (EvaluatedPolicyRuleTrigger trigger : policyRule.getTriggers()) { -// EvaluatedPolicyRuleTriggerType triggerType = trigger.toEvaluatedPolicyRuleTriggerType(policyRule, false).clone(); -// simplifyTrigger(triggerType); -// rv.add(triggerType); -// } -// } -// return rv; -// } -// -// private void simplifyTrigger(EvaluatedPolicyRuleTriggerType trigger) { -// deleteAssignments(trigger.getAssignmentPath()); -// if (trigger instanceof EvaluatedExclusionTriggerType) { -// EvaluatedExclusionTriggerType exclusionTrigger = (EvaluatedExclusionTriggerType) trigger; -// deleteAssignments(exclusionTrigger.getConflictingObjectPath()); -// exclusionTrigger.setConflictingAssignment(null); -// } else if (trigger instanceof EvaluatedSituationTriggerType) { -// for (EvaluatedPolicyRuleType sourceRule : ((EvaluatedSituationTriggerType) trigger).getSourceRule()) { -// for (EvaluatedPolicyRuleTriggerType sourceTrigger : sourceRule.getTrigger()) { -// simplifyTrigger(sourceTrigger); -// } -// } -// } -// } - -// private void deleteAssignments(AssignmentPathType path) { -// if (path == null) { -// return; -// } -// for (AssignmentPathSegmentType segment : path.getSegment()) { -// segment.setAssignment(null); -// } -// } - -// private boolean shouldSituationBeUpdated(EvaluatedAssignment evaluatedAssignment, -// List triggers) { -// if (PolicyRuleTypeUtil.canBePacked(evaluatedAssignment.getAssignmentType().getTrigger())) { -// return true; -// } -// Set currentSituations = new HashSet<>(evaluatedAssignment.getAssignmentType().getPolicySituation()); -// List currentTriggersUnpacked = PolicyRuleTypeUtil.unpack(evaluatedAssignment.getAssignmentType().getTrigger()); -// // if the current situations different from the ones in the old assignment => update -// // (provided that the situations in the assignment were _not_ changed directly via a delta!!!) TODO check this -// if (!currentSituations.equals(new HashSet<>(evaluatedAssignment.getPolicySituations()))) { -// LOGGER.trace("computed policy situations are different from the current ones"); -// return true; -// } -// if (!PolicyRuleTypeUtil.triggerCollectionsEqual(triggers, currentTriggersUnpacked)) { -// LOGGER.trace("computed policy rules triggers are different from the current ones"); -// return true; -// } -// return false; -// } - - - public void applyObjectSituation(LensContext context, List rulesToRecord) throws SchemaException { - // compute policySituation and triggeredPolicyRules and compare it with the expected state - // note that we use the new state for the comparison, because if values match we do not need to do anything - LensFocusContext focusContext = context.getFocusContext(); - F objectNew = focusContext.getObjectNew().asObjectable(); - ComputationResult cr = compute(rulesToRecord, objectNew.getPolicySituation(), objectNew.getTriggeredPolicyRule()); - if (cr.situationsNeedUpdate) { - focusContext.addToPendingPolicySituationModifications(DeltaBuilder.deltaFor(ObjectType.class, prismContext) - .item(ObjectType.F_POLICY_SITUATION) - .oldRealValues(cr.oldPolicySituations) - .replaceRealValues(cr.newPolicySituations) - .asItemDelta()); - } - if (cr.rulesNeedUpdate) { - focusContext.addToPendingPolicySituationModifications(DeltaBuilder.deltaFor(ObjectType.class, prismContext) - .item(ObjectType.F_TRIGGERED_POLICY_RULE) - .oldRealValues(cr.oldTriggeredRules) - .replaceRealValues(cr.newTriggeredRules) - .asItemDelta()); - } - } - - public void applyAssignmentSituation(LensContext context, - EvaluatedAssignmentImpl evaluatedAssignment, List rulesToRecord) throws SchemaException { - LensFocusContext focusContext = context.getFocusContext(); - AssignmentType assignment = evaluatedAssignment.getAssignmentType(false); - Long id = assignment.getId(); - ComputationResult cr = compute(rulesToRecord, assignment.getPolicySituation(), assignment.getTriggeredPolicyRule()); - boolean missedUpdate = false; - if (cr.situationsNeedUpdate) { - if (id != null) { - focusContext.addToPendingPolicySituationModifications(DeltaBuilder.deltaFor(ObjectType.class, prismContext) - .item(FocusType.F_ASSIGNMENT, id, AssignmentType.F_POLICY_SITUATION) - .oldRealValues(cr.oldPolicySituations) - .replaceRealValues(cr.newPolicySituations) - .asItemDelta()); - } else { - missedUpdate = true; - } - } - if (cr.rulesNeedUpdate) { - if (id != null) { - focusContext.addToPendingPolicySituationModifications(DeltaBuilder.deltaFor(ObjectType.class, prismContext) - .item(FocusType.F_ASSIGNMENT, id, AssignmentType.F_TRIGGERED_POLICY_RULE) - .oldRealValues(cr.oldTriggeredRules) - .replaceRealValues(cr.newTriggeredRules) - .asItemDelta()); - } else { - missedUpdate = true; - } - } - if (missedUpdate) { - LOGGER.warn("Policy situation/rules for assignment cannot be updated, because it has no ID; assignment = {}, in object {}", - assignment, focusContext.getObjectAny()); - } - } - - private ComputationResult compute(@NotNull List rulesToRecord, @NotNull List existingPolicySituation, - @NotNull List existingTriggeredPolicyRule) { - ComputationResult cr = new ComputationResult(); - for (EvaluatedPolicyRule rule : rulesToRecord) { - cr.newPolicySituations.add(rule.getPolicySituation()); - cr.newTriggeredRules.add(rule.toEvaluatedPolicyRuleType(true)); - } - cr.oldPolicySituations.addAll(existingPolicySituation); - cr.oldTriggeredRules.addAll(existingTriggeredPolicyRule); - cr.situationsNeedUpdate = !Objects.equals(cr.oldPolicySituations, cr.newPolicySituations); - cr.rulesNeedUpdate = !Objects.equals(cr.oldTriggeredRules, cr.newTriggeredRules); - return cr; - } - - private class ComputationResult { - final Set oldPolicySituations = new HashSet<>(); - final Set newPolicySituations = new HashSet<>(); - final Set oldTriggeredRules = new HashSet<>(); - final Set newTriggeredRules = new HashSet<>(); - boolean situationsNeedUpdate; - boolean rulesNeedUpdate; - } -} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java new file mode 100644 index 00000000000..6c859f7479c --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2010-2017 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.evolveum.midpoint.model.impl.lens.projector.policy; + +import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule; +import com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl; +import com.evolveum.midpoint.model.impl.lens.LensContext; +import com.evolveum.midpoint.model.impl.lens.LensFocusContext; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.delta.PlusMinusZero; +import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; +import com.evolveum.midpoint.prism.path.IdItemPathSegment; +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 org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.Objects; + +/** + * Takes care of updating policySituation and triggered rules for focus and assignments. (Originally was a part of PolicyRuleProcessor.) + * + * @author semancik + * @author mederly + */ +@Component +public class PolicyStateUpdater { + + private static final Trace LOGGER = TraceManager.getTrace(PolicyStateUpdater.class); + + @Autowired private PrismContext prismContext; + + public void applyObjectState(LensContext context, List rulesToRecord) throws SchemaException { + // compute policySituation and triggeredPolicyRules and compare it with the expected state + // note that we use the new state for the comparison, because if values match we do not need to do anything + LensFocusContext focusContext = context.getFocusContext(); + F objectNew = focusContext.getObjectNew().asObjectable(); + ComputationResult cr = compute(rulesToRecord, objectNew.getPolicySituation(), objectNew.getTriggeredPolicyRule()); + if (cr.situationsNeedUpdate) { + focusContext.addToPendingObjectPolicyStateModifications(DeltaBuilder.deltaFor(ObjectType.class, prismContext) + .item(ObjectType.F_POLICY_SITUATION) + .oldRealValues(cr.oldPolicySituations) + .replaceRealValues(cr.newPolicySituations) + .asItemDelta()); + } + if (cr.rulesNeedUpdate) { + focusContext.addToPendingObjectPolicyStateModifications(DeltaBuilder.deltaFor(ObjectType.class, prismContext) + .item(ObjectType.F_TRIGGERED_POLICY_RULE) + .oldRealValues(cr.oldTriggeredRules) + .replaceRealValues(cr.newTriggeredRules) + .asItemDelta()); + } + } + + public void applyAssignmentState(LensContext context, + EvaluatedAssignmentImpl evaluatedAssignment, List rulesToRecord) throws SchemaException { + LensFocusContext focusContext = context.getFocusContext(); + AssignmentType assignmentNew = evaluatedAssignment.getAssignmentType(false); + AssignmentType assignmentOld = evaluatedAssignment.getAssignmentType(true); + if (assignmentOld == null && assignmentNew == null) { + throw new IllegalStateException("Policy situation/rules for assignment cannot be updated, because the " + + "assignment itself is missing in "+evaluatedAssignment+", in object "+focusContext.getObjectAny()); + } + // this value is to be used to find correct assignment in objectDelta to apply the modifications (if no ID is present) + @NotNull AssignmentType assignmentToMatch = assignmentOld != null ? assignmentOld : assignmentNew; + // this value is used to compute policy situation/rules modifications + @NotNull AssignmentType assignmentToCompute = assignmentNew != null ? assignmentNew : assignmentOld; + @NotNull PlusMinusZero mode = evaluatedAssignment.getMode(); + + Long id = assignmentToMatch.getId(); + ComputationResult cr = compute(rulesToRecord, assignmentToCompute.getPolicySituation(), assignmentToCompute.getTriggeredPolicyRule()); + if (cr.situationsNeedUpdate) { + focusContext.addToPendingAssignmentPolicyStateModifications(assignmentToMatch, mode, DeltaBuilder.deltaFor(FocusType.class, prismContext) + .item(FocusType.F_ASSIGNMENT, new IdItemPathSegment(id), AssignmentType.F_POLICY_SITUATION) + .oldRealValues(cr.oldPolicySituations) + .replaceRealValues(cr.newPolicySituations) + .asItemDelta()); + } + if (cr.rulesNeedUpdate) { + focusContext.addToPendingAssignmentPolicyStateModifications(assignmentToMatch, mode, DeltaBuilder.deltaFor(FocusType.class, prismContext) + .item(FocusType.F_ASSIGNMENT, new IdItemPathSegment(id), AssignmentType.F_TRIGGERED_POLICY_RULE) + .oldRealValues(cr.oldTriggeredRules) + .replaceRealValues(cr.newTriggeredRules) + .asItemDelta()); + } + } + + private ComputationResult compute(@NotNull List rulesToRecord, @NotNull List existingPolicySituation, + @NotNull List existingTriggeredPolicyRule) { + ComputationResult cr = new ComputationResult(); + for (EvaluatedPolicyRule rule : rulesToRecord) { + cr.newPolicySituations.add(rule.getPolicySituation()); + cr.newTriggeredRules.add(rule.toEvaluatedPolicyRuleType(false, true)); + } + cr.oldPolicySituations.addAll(existingPolicySituation); + cr.oldTriggeredRules.addAll(existingTriggeredPolicyRule); + cr.situationsNeedUpdate = !Objects.equals(cr.oldPolicySituations, cr.newPolicySituations); + cr.rulesNeedUpdate = !Objects.equals(cr.oldTriggeredRules, cr.newTriggeredRules); + return cr; + } + + private class ComputationResult { + final Set oldPolicySituations = new HashSet<>(); + final Set newPolicySituations = new HashSet<>(); + final Set oldTriggeredRules = new HashSet<>(); + final Set newTriggeredRules = new HashSet<>(); + boolean situationsNeedUpdate; + boolean rulesNeedUpdate; + } +} diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyMetadata.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyMetadata.java index 96a5ceb46a8..7b74f60330f 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyMetadata.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyMetadata.java @@ -90,7 +90,7 @@ public void test100JackAssignRoleJudge() throws Exception { assertAssignedRole(USER_JACK_OID, ROLE_JUDGE_OID, task, result); assertEquals("Wrong # of assignments", 1, jack.getAssignment().size()); assertEquals("Wrong policy situations", - Collections.singletonList(SchemaConstants.MODEL_POLICY_SITUATION_ASSIGNMENT_MODIFIED), + Collections.emptyList(), jack.getAssignment().get(0).getPolicySituation()); } diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java index f71ba11242d..26865e22941 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java @@ -314,13 +314,13 @@ public void test130JackMoveTo1900AndAssignRoleStudent() throws Exception { assertFocusTriggers(context, PolicyConstraintKindType.HAS_NO_ASSIGNMENT, 1); assertFocusTriggers(context, PolicyConstraintKindType.TRANSITION, 3); - assertAssignmentPolicySituation(context, roleStudentOid, - SchemaConstants.MODEL_POLICY_SITUATION_ASSIGNMENT_MODIFIED, - SchemaConstants.MODEL_POLICY_SITUATION_OBJECT_STATE); - assertFocusPolicySituation(context, - SchemaConstants.MODEL_POLICY_SITUATION_OBJECT_STATE, - SchemaConstants.MODEL_POLICY_SITUATION_HAS_ASSIGNMENT, - SchemaConstants.MODEL_POLICY_SITUATION_HAS_NO_ASSIGNMENT); +// assertAssignmentPolicySituation(context, roleStudentOid, +// SchemaConstants.MODEL_POLICY_SITUATION_ASSIGNMENT_MODIFIED, +// SchemaConstants.MODEL_POLICY_SITUATION_OBJECT_STATE); +// assertFocusPolicySituation(context, +// SchemaConstants.MODEL_POLICY_SITUATION_OBJECT_STATE, +// SchemaConstants.MODEL_POLICY_SITUATION_HAS_ASSIGNMENT, +// SchemaConstants.MODEL_POLICY_SITUATION_HAS_NO_ASSIGNMENT); } @Test @@ -560,12 +560,12 @@ public void test170AddPeter() throws Exception { // instead of "false-true" and "false-any" situations! // adapt the test after fixing MID-4126 - assertAssignmentPolicySituation(context, roleStudentOid, - SchemaConstants.MODEL_POLICY_SITUATION_OBJECT_STATE); - assertFocusPolicySituation(context, - SchemaConstants.MODEL_POLICY_SITUATION_OBJECT_STATE, - SchemaConstants.MODEL_POLICY_SITUATION_HAS_ASSIGNMENT, - SchemaConstants.MODEL_POLICY_SITUATION_HAS_NO_ASSIGNMENT); +// assertAssignmentPolicySituation(context, roleStudentOid, +// SchemaConstants.MODEL_POLICY_SITUATION_OBJECT_STATE); +// assertFocusPolicySituation(context, +// SchemaConstants.MODEL_POLICY_SITUATION_OBJECT_STATE, +// SchemaConstants.MODEL_POLICY_SITUATION_HAS_ASSIGNMENT, +// SchemaConstants.MODEL_POLICY_SITUATION_HAS_NO_ASSIGNMENT); } /** diff --git a/model/model-impl/src/test/resources/lens/role-judge-situation-only.xml b/model/model-impl/src/test/resources/lens/role-judge-situation-only.xml index 8f31d72ffca..5be082f4bac 100644 --- a/model/model-impl/src/test/resources/lens/role-judge-situation-only.xml +++ b/model/model-impl/src/test/resources/lens/role-judge-situation-only.xml @@ -30,7 +30,8 @@ - + + diff --git a/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml b/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml index c1920e3c60e..6926f03edb6 100644 --- a/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml +++ b/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml @@ -31,6 +31,7 @@ + diff --git a/model/model-impl/src/test/resources/lens/role-thief.xml b/model/model-impl/src/test/resources/lens/role-thief.xml index e9c2b997a4c..b10a9fbbc2c 100644 --- a/model/model-impl/src/test/resources/lens/role-thief.xml +++ b/model/model-impl/src/test/resources/lens/role-thief.xml @@ -26,7 +26,10 @@ - + + + + diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestSegregationOfDuties.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestSegregationOfDuties.java index afa8a531d2d..de47a44faef 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestSegregationOfDuties.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestSegregationOfDuties.java @@ -1340,7 +1340,7 @@ public void test822GuybrushAssignRoleMinister() throws Exception { assertAssignedRole(userAfter, ROLE_CRIMINAL_OID); assertAssignedRole(userAfter, ROLE_MINISTER_OID); - assertPolicySituation(userAfter, ROLE_MINISTER_OID, SchemaConstants.MODEL_POLICY_SITUATION_EXCLUSION_VIOLATION); + //assertPolicySituation(userAfter, ROLE_MINISTER_OID, SchemaConstants.MODEL_POLICY_SITUATION_EXCLUSION_VIOLATION); } @Test diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java index 152e3babf3c..eb45daa88cb 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java @@ -208,7 +208,7 @@ private void processFragmentGroup(List fragments, ApprovalSchemaType r SchemaAttachedPolicyRuleType attachedRule = new SchemaAttachedPolicyRuleType(); attachedRule.setStageMin(from); attachedRule.setStageMax(i - 1); - attachedRule.setRule(firstFragment.policyRule.toEvaluatedPolicyRuleType(false)); + attachedRule.setRule(firstFragment.policyRule.toEvaluatedPolicyRuleType(false, true)); attachedRules.getEntry().add(attachedRule); } } From ef245d7b27ca1b8085d8bb92a9e491939372cdc4 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 25 Sep 2017 13:51:13 +0200 Subject: [PATCH 05/19] Renamed recordSituation->record and fixed schema tests. --- .../resources/xml/ns/public/common/common-policy-3.xsd | 4 ++-- .../com/evolveum/midpoint/schema/util/SchemaTestUtil.java | 2 +- .../src/test/resources/complex/system-configuration.xml | 8 ++++---- .../impl/lens/projector/policy/PolicyRuleProcessor.java | 2 +- .../{TestPolicyMetadata.java => TestPolicyState.java} | 8 ++++---- .../src/test/resources/lens/role-judge-situation-only.xml | 2 +- .../test/resources/lens/role-pirate-situation-only.xml | 2 +- model/model-impl/src/test/resources/lens/role-thief.xml | 2 +- model/model-impl/testng-unit.xml | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) rename model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/{TestPolicyMetadata.java => TestPolicyState.java} (93%) diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd index 534cb7687dd..25810227239 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd @@ -1014,7 +1014,7 @@ - + Record action. The operation will proceed. Policy situation will be recorded for @@ -1375,7 +1375,7 @@ - + TODO diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/util/SchemaTestUtil.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/util/SchemaTestUtil.java index 5b108c5c15e..fe27db9d7e5 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/util/SchemaTestUtil.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/util/SchemaTestUtil.java @@ -86,7 +86,7 @@ public static void assertFocusDefinition(ComplexTypeDefinition complexTypeDefini PrismContainerDefinition assignmentContainer = complexTypeDefinition.findContainerDefinition(UserType.F_ASSIGNMENT); PrismAsserts.assertDefinition(assignmentContainer, UserType.F_ASSIGNMENT, AssignmentType.COMPLEX_TYPE, 0, -1); assertFalse("Assignment is runtime", assignmentContainer.isRuntimeSchema()); - assertEquals("Assignment definition size", 21, assignmentContainer.getDefinitions().size()); + assertEquals("Assignment definition size", 22, assignmentContainer.getDefinitions().size()); PrismContainerDefinition constructionContainer = assignmentContainer.findContainerDefinition(AssignmentType.F_CONSTRUCTION); PrismAsserts.assertDefinition(constructionContainer, AssignmentType.F_CONSTRUCTION, ConstructionType.COMPLEX_TYPE, 0, 1); diff --git a/model/certification-impl/src/test/resources/complex/system-configuration.xml b/model/certification-impl/src/test/resources/complex/system-configuration.xml index 8c8cd007d65..ac1cbdb3a3d 100644 --- a/model/certification-impl/src/test/resources/complex/system-configuration.xml +++ b/model/certification-impl/src/test/resources/complex/system-configuration.xml @@ -394,9 +394,9 @@ http://sample.org/situations#incomplete-role-c1-to-c4 - + full - + RoleType @@ -412,9 +412,9 @@ http://sample.org/situations#active-role-with-no-identifier - + none - + RoleType diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java index a56794de0eb..5fb0be2dc03 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java @@ -319,7 +319,7 @@ private void evaluateRule(PolicyRuleEvaluationContext c } ctx.triggerRule(triggers); } - if (ctx.policyRule.isTriggered() && ctx.policyRule.getActions() != null && ctx.policyRule.getActions().getRecordSituation() != null) { + if (ctx.policyRule.isTriggered() && ctx.policyRule.getActions() != null && ctx.policyRule.getActions().getRecord() != null) { ctx.record(); } traceRuleEvaluationResult(ctx.policyRule, ctx); diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyMetadata.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyState.java similarity index 93% rename from model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyMetadata.java rename to model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyState.java index 7b74f60330f..b5fbff1586d 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyMetadata.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyState.java @@ -43,7 +43,7 @@ */ @ContextConfiguration(locations = {"classpath:ctx-model-test-main.xml"}) @DirtiesContext(classMode = ClassMode.AFTER_CLASS) -public class TestPolicyMetadata extends AbstractLensTest { +public class TestPolicyState extends AbstractLensTest { private static final String ROLE_JUDGE_POLICY_RULE_EXCLUSION_NAME = "criminal exclusion"; @@ -73,7 +73,7 @@ public void test100JackAssignRoleJudge() throws Exception { TestUtil.displayTestTitle(this, TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestPolicyMetadata.class.getName() + "." + TEST_NAME); + Task task = taskManager.createTaskInstance(TestPolicyState.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); // WHEN @@ -100,7 +100,7 @@ public void test110JackAssignRolePirate() throws Exception { TestUtil.displayTestTitle(this, TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestPolicyMetadata.class.getName() + "." + TEST_NAME); + Task task = taskManager.createTaskInstance(TestPolicyState.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); // WHEN @@ -130,7 +130,7 @@ public void test120RecomputeJack() throws Exception { TestUtil.displayTestTitle(this, TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestPolicyMetadata.class.getName() + "." + TEST_NAME); + Task task = taskManager.createTaskInstance(TestPolicyState.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); // WHEN diff --git a/model/model-impl/src/test/resources/lens/role-judge-situation-only.xml b/model/model-impl/src/test/resources/lens/role-judge-situation-only.xml index 5be082f4bac..59d5135c804 100644 --- a/model/model-impl/src/test/resources/lens/role-judge-situation-only.xml +++ b/model/model-impl/src/test/resources/lens/role-judge-situation-only.xml @@ -30,7 +30,7 @@ - + diff --git a/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml b/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml index 6926f03edb6..2fd1c58578e 100644 --- a/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml +++ b/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml @@ -31,7 +31,7 @@ - + diff --git a/model/model-impl/src/test/resources/lens/role-thief.xml b/model/model-impl/src/test/resources/lens/role-thief.xml index b10a9fbbc2c..ce91c6dd203 100644 --- a/model/model-impl/src/test/resources/lens/role-thief.xml +++ b/model/model-impl/src/test/resources/lens/role-thief.xml @@ -28,7 +28,7 @@ - + diff --git a/model/model-impl/testng-unit.xml b/model/model-impl/testng-unit.xml index 1e2d2b012fd..b6c29d43ecc 100644 --- a/model/model-impl/testng-unit.xml +++ b/model/model-impl/testng-unit.xml @@ -72,7 +72,7 @@ - + From 64d50bd3b715604613ef1b5bf42c10e8562a2c14 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 25 Sep 2017 14:17:47 +0200 Subject: [PATCH 06/19] Implemented triggerStorageStrategy. --- .../context/EvaluatedCompositeTrigger.java | 7 +-- .../context/EvaluatedExclusionTrigger.java | 21 ++++--- .../EvaluatedHasAssignmentTrigger.java | 3 +- .../context/EvaluatedModificationTrigger.java | 3 +- .../context/EvaluatedMultiplicityTrigger.java | 3 +- .../api/context/EvaluatedPolicyRule.java | 2 +- .../context/EvaluatedPolicyRuleTrigger.java | 4 +- .../context/EvaluatedSituationTrigger.java | 7 +-- .../api/context/EvaluatedStateTrigger.java | 2 +- .../context/EvaluatedTimeValidityTrigger.java | 3 +- .../context/EvaluatedTransitionTrigger.java | 7 +-- .../PolicyRuleExternalizationOptions.java | 58 +++++++++++++++++++ .../impl/hooks/PolicyRuleEnforcerHook.java | 4 +- .../impl/lens/EvaluatedPolicyRuleImpl.java | 15 +++-- .../projector/policy/PolicyStateUpdater.java | 6 +- .../lens/role-pirate-situation-only.xml | 4 +- .../primary/policy/ApprovalSchemaBuilder.java | 4 +- 17 files changed, 109 insertions(+), 44 deletions(-) create mode 100644 model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/PolicyRuleExternalizationOptions.java diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedCompositeTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedCompositeTrigger.java index 2f0207eda4d..d2cdc1b0798 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedCompositeTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedCompositeTrigger.java @@ -77,12 +77,11 @@ protected void debugDumpSpecific(StringBuilder sb, int indent) { } @Override - public EvaluatedLogicalTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, - boolean respectFinalFlag) { + public EvaluatedLogicalTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRuleExternalizationOptions options) { EvaluatedLogicalTriggerType rv = new EvaluatedLogicalTriggerType(); fillCommonContent(rv); - if (!respectFinalFlag || !isFinal()) { - innerTriggers.forEach(t -> rv.getEmbedded().add(t.toEvaluatedPolicyRuleTriggerType(includeAssignmentsContent, respectFinalFlag))); + if (!options.isRespectFinalFlag() || !isFinal()) { + innerTriggers.forEach(t -> rv.getEmbedded().add(t.toEvaluatedPolicyRuleTriggerType(options))); } return rv; } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java index cf3bbc72048..1b364bd9f94 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java @@ -24,6 +24,8 @@ import java.util.Objects; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType.FULL; + /** * @author mederly */ @@ -77,17 +79,18 @@ protected void debugDumpSpecific(StringBuilder sb, int indent) { } @Override - public EvaluatedExclusionTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, - boolean respectFinalFlag) { + public EvaluatedExclusionTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRuleExternalizationOptions options) { EvaluatedExclusionTriggerType rv = new EvaluatedExclusionTriggerType(); fillCommonContent(rv); - rv.setConflictingObjectRef(ObjectTypeUtil.createObjectRef(conflictingTarget)); - rv.setConflictingObjectDisplayName(ObjectTypeUtil.getDisplayName(conflictingTarget)); - if (conflictingPath != null) { - rv.setConflictingObjectPath(conflictingPath.toAssignmentPathType(includeAssignmentsContent)); - } - if (includeAssignmentsContent && conflictingAssignment.getAssignmentType() != null) { - rv.setConflictingAssignment(conflictingAssignment.getAssignmentType().clone()); + if (options.getTriggerStorageStrategy() == FULL) { + rv.setConflictingObjectRef(ObjectTypeUtil.createObjectRef(conflictingTarget)); + rv.setConflictingObjectDisplayName(ObjectTypeUtil.getDisplayName(conflictingTarget)); + if (conflictingPath != null) { + rv.setConflictingObjectPath(conflictingPath.toAssignmentPathType(options.isIncludeAssignmentsContent())); + } + if (options.isIncludeAssignmentsContent() && conflictingAssignment.getAssignmentType() != null) { + rv.setConflictingAssignment(conflictingAssignment.getAssignmentType().clone()); + } } return rv; } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedHasAssignmentTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedHasAssignmentTrigger.java index 18a2c178595..b2634123bd9 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedHasAssignmentTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedHasAssignmentTrigger.java @@ -31,8 +31,7 @@ public EvaluatedHasAssignmentTrigger(@NotNull PolicyConstraintKindType kind, @No } @Override - public EvaluatedHasAssignmentTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, - boolean respectFinalFlag) { + public EvaluatedHasAssignmentTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRuleExternalizationOptions options) { EvaluatedHasAssignmentTriggerType rv = new EvaluatedHasAssignmentTriggerType(); fillCommonContent(rv); return rv; diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedModificationTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedModificationTrigger.java index c89b4de5a0a..bf47c26488d 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedModificationTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedModificationTrigger.java @@ -31,8 +31,7 @@ public EvaluatedModificationTrigger(@NotNull PolicyConstraintKindType kind, @Not } @Override - public EvaluatedModificationTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, - boolean respectFinalFlag) { + public EvaluatedModificationTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRuleExternalizationOptions options) { EvaluatedModificationTriggerType rv = new EvaluatedModificationTriggerType(); fillCommonContent(rv); return rv; diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedMultiplicityTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedMultiplicityTrigger.java index 3c4bc09bb1c..9e1ee567672 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedMultiplicityTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedMultiplicityTrigger.java @@ -31,8 +31,7 @@ public EvaluatedMultiplicityTrigger(@NotNull PolicyConstraintKindType kind, @Not } @Override - public EvaluatedMultiplicityTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, - boolean respectFinalFlag) { + public EvaluatedMultiplicityTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRuleExternalizationOptions options) { EvaluatedMultiplicityTriggerType rv = new EvaluatedMultiplicityTriggerType(); fillCommonContent(rv); return rv; diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java index 04c4eaf7ba3..8ef51b2759d 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java @@ -66,7 +66,7 @@ default boolean isTriggered() { Collection getPolicyExceptions(); - EvaluatedPolicyRuleType toEvaluatedPolicyRuleType(boolean includeAssignmentsContent, boolean respectFinalFlag); + EvaluatedPolicyRuleType toEvaluatedPolicyRuleType(PolicyRuleExternalizationOptions options); boolean isGlobal(); diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRuleTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRuleTrigger.java index 4ee911c2a0f..31ebe4b4c6c 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRuleTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRuleTrigger.java @@ -130,8 +130,7 @@ public String toDiagShortcut() { return PolicyRuleTypeUtil.toDiagShortcut(constraintKind); } - public EvaluatedPolicyRuleTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, - boolean respectFinalFlag) { + public EvaluatedPolicyRuleTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRuleExternalizationOptions options) { EvaluatedPolicyRuleTriggerType rv = new EvaluatedPolicyRuleTriggerType(); fillCommonContent(rv); return rv; @@ -139,7 +138,6 @@ public EvaluatedPolicyRuleTriggerType toEvaluatedPolicyRuleTriggerType(boolean i protected void fillCommonContent(EvaluatedPolicyRuleTriggerType tt) { tt.setConstraintKind(constraintKind); - //tt.setConstraint(constraint); tt.setMessage(LocalizationUtil.createLocalizableMessageType(message)); PolicyConstraintPresentationType presentation = constraint.getPresentation(); if (presentation != null) { diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java index 855bc15b062..063c358ec05 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java @@ -103,12 +103,11 @@ protected void debugDumpSpecific(StringBuilder sb, int indent) { } @Override - public EvaluatedSituationTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, - boolean respectFinalFlag) { + public EvaluatedSituationTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRuleExternalizationOptions options) { EvaluatedSituationTriggerType rv = new EvaluatedSituationTriggerType(); fillCommonContent(rv); - if (!respectFinalFlag || !isFinal()) { - sourceRules.forEach(r -> rv.getSourceRule().add(r.toEvaluatedPolicyRuleType(false, false))); + if (!options.isRespectFinalFlag() || !isFinal()) { + sourceRules.forEach(r -> rv.getSourceRule().add(r.toEvaluatedPolicyRuleType(options))); } return rv; } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedStateTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedStateTrigger.java index 9b9ec499f4b..36a44eff9c6 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedStateTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedStateTrigger.java @@ -33,7 +33,7 @@ public EvaluatedStateTrigger(@NotNull PolicyConstraintKindType kind, @NotNull St } @Override - public EvaluatedStateTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, boolean respectFinalFlag) { + public EvaluatedStateTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRuleExternalizationOptions options) { EvaluatedStateTriggerType rv = new EvaluatedStateTriggerType(); fillCommonContent(rv); return rv; diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTimeValidityTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTimeValidityTrigger.java index 4fce27c3fdf..9dbc954b8fb 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTimeValidityTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTimeValidityTrigger.java @@ -31,8 +31,7 @@ public EvaluatedTimeValidityTrigger(@NotNull PolicyConstraintKindType kind, @Not } @Override - public EvaluatedTimeValidityTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, - boolean respectFinalFlag) { + public EvaluatedTimeValidityTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRuleExternalizationOptions options) { EvaluatedTimeValidityTriggerType rv = new EvaluatedTimeValidityTriggerType(); fillCommonContent(rv); return rv; diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTransitionTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTransitionTrigger.java index 6aa4ad9cc07..82c8fdb506f 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTransitionTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedTransitionTrigger.java @@ -75,12 +75,11 @@ protected void debugDumpSpecific(StringBuilder sb, int indent) { } @Override - public EvaluatedTransitionTriggerType toEvaluatedPolicyRuleTriggerType(boolean includeAssignmentsContent, - boolean respectFinalFlag) { + public EvaluatedTransitionTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRuleExternalizationOptions options) { EvaluatedTransitionTriggerType rv = new EvaluatedTransitionTriggerType(); fillCommonContent(rv); - if (!respectFinalFlag || !isFinal()) { - innerTriggers.forEach(t -> rv.getEmbedded().add(t.toEvaluatedPolicyRuleTriggerType(includeAssignmentsContent, respectFinalFlag))); + if (!options.isRespectFinalFlag() || !isFinal()) { + innerTriggers.forEach(t -> rv.getEmbedded().add(t.toEvaluatedPolicyRuleTriggerType(options))); } return rv; } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/PolicyRuleExternalizationOptions.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/PolicyRuleExternalizationOptions.java new file mode 100644 index 00000000000..2e8ac2a4f47 --- /dev/null +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/PolicyRuleExternalizationOptions.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010-2017 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.model.api.context; + +import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType; +import org.jetbrains.annotations.NotNull; + +import java.io.Serializable; + +import static com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType.FULL; + +/** + * @author mederly + */ +public class PolicyRuleExternalizationOptions implements Serializable { + + @NotNull private PolicyTriggerStorageStrategyType triggerStorageStrategy; + private boolean includeAssignmentsContent; + private boolean respectFinalFlag; + + public PolicyRuleExternalizationOptions() { + this(FULL, false, true); + } + + public PolicyRuleExternalizationOptions(PolicyTriggerStorageStrategyType triggerStorageStrategy, + boolean includeAssignmentsContent, boolean respectFinalFlag) { + this.triggerStorageStrategy = triggerStorageStrategy != null ? triggerStorageStrategy : FULL; + this.includeAssignmentsContent = includeAssignmentsContent; + this.respectFinalFlag = respectFinalFlag; + } + + @NotNull + public PolicyTriggerStorageStrategyType getTriggerStorageStrategy() { + return triggerStorageStrategy; + } + + public boolean isIncludeAssignmentsContent() { + return includeAssignmentsContent; + } + + public boolean isRespectFinalFlag() { + return respectFinalFlag; + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java index 5c9da6cc42e..e9f4e234f8f 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java @@ -40,6 +40,8 @@ import java.util.Collections; import java.util.List; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType.FULL; + /** * Hook used to enforce the policy rules that have the enforce action. * @@ -136,7 +138,7 @@ private void enforceTriggeredRules(EvaluationContext evalC } // TODO really include assignments content? - evalCtx.rules.add(policyRule.toEvaluatedPolicyRuleType(true, true)); + evalCtx.rules.add(policyRule.toEvaluatedPolicyRuleType(new PolicyRuleExternalizationOptions(FULL, true, true))); for (EvaluatedPolicyRuleTrigger trigger: triggers) { if (trigger.getMessage() != null) { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java index 67391dac922..40308f52e06 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java @@ -31,6 +31,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType.FULL; + /** * @author semancik * @@ -309,21 +311,22 @@ private void createMessageTreeNode(TreeNode root, EvaluatedP /** * Honors "final" but not "hidden" flag. + * @param options */ @Override - public EvaluatedPolicyRuleType toEvaluatedPolicyRuleType(boolean includeAssignmentsContent, boolean respectFinalFlag) { + public EvaluatedPolicyRuleType toEvaluatedPolicyRuleType(PolicyRuleExternalizationOptions options) { EvaluatedPolicyRuleType rv = new EvaluatedPolicyRuleType(); - //rv.setPolicyRule(policyRuleType); // DO NOT use this, in order to avoid large data in assignments rv.setRuleName(getName()); - if (assignmentPath != null) { - rv.setAssignmentPath(assignmentPath.toAssignmentPathType(includeAssignmentsContent)); + boolean isFull = options.getTriggerStorageStrategy() == FULL; + if (isFull && assignmentPath != null) { + rv.setAssignmentPath(assignmentPath.toAssignmentPathType(options.isIncludeAssignmentsContent())); } - if (directOwner != null) { + if (isFull && directOwner != null) { rv.setDirectOwnerRef(ObjectTypeUtil.createObjectRef(directOwner)); rv.setDirectOwnerDisplayName(ObjectTypeUtil.getDisplayName(directOwner)); } - triggers.forEach(t -> rv.getTrigger().add(t.toEvaluatedPolicyRuleTriggerType(includeAssignmentsContent, respectFinalFlag))); + triggers.forEach(t -> rv.getTrigger().add(t.toEvaluatedPolicyRuleTriggerType(options))); return rv; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java index 6c859f7479c..63330d650e5 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.model.impl.lens.projector.policy; import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule; +import com.evolveum.midpoint.model.api.context.PolicyRuleExternalizationOptions; import com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl; import com.evolveum.midpoint.model.impl.lens.LensContext; import com.evolveum.midpoint.model.impl.lens.LensFocusContext; @@ -107,7 +108,10 @@ private ComputationResult compute(@NotNull List rulesToReco ComputationResult cr = new ComputationResult(); for (EvaluatedPolicyRule rule : rulesToRecord) { cr.newPolicySituations.add(rule.getPolicySituation()); - cr.newTriggeredRules.add(rule.toEvaluatedPolicyRuleType(false, true)); + RecordPolicyActionType recordAction = rule.getActions().getRecord(); + if (recordAction.getTriggerStorageStrategy() != PolicyTriggerStorageStrategyType.NONE) { + cr.newTriggeredRules.add(rule.toEvaluatedPolicyRuleType(new PolicyRuleExternalizationOptions(recordAction.getTriggerStorageStrategy(), false, true))); + } } cr.oldPolicySituations.addAll(existingPolicySituation); cr.oldTriggeredRules.addAll(existingTriggeredPolicyRule); diff --git a/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml b/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml index 2fd1c58578e..b936eeab0e2 100644 --- a/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml +++ b/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml @@ -31,7 +31,9 @@ - + + messageOnly + diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java index eb45daa88cb..14a86b8f7a6 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.wf.impl.processors.primary.policy; import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule; +import com.evolveum.midpoint.model.api.context.PolicyRuleExternalizationOptions; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.util.CloneUtil; @@ -33,6 +34,7 @@ import javax.xml.namespace.QName; import java.util.*; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType.FULL; import static java.util.Comparator.naturalOrder; /** @@ -208,7 +210,7 @@ private void processFragmentGroup(List fragments, ApprovalSchemaType r SchemaAttachedPolicyRuleType attachedRule = new SchemaAttachedPolicyRuleType(); attachedRule.setStageMin(from); attachedRule.setStageMax(i - 1); - attachedRule.setRule(firstFragment.policyRule.toEvaluatedPolicyRuleType(false, true)); + attachedRule.setRule(firstFragment.policyRule.toEvaluatedPolicyRuleType(new PolicyRuleExternalizationOptions(FULL, false, true))); attachedRules.getEntry().add(attachedRule); } } From 353b5ee93c81f88c89300570ce6156443895c8ec Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 25 Sep 2017 14:42:00 +0200 Subject: [PATCH 07/19] Migrated from assignment.trigger to assignment.triggeredPolicyRule --- .../dto/CertCaseOrWorkItemDto.java | 28 ++++++++-------- .../test/TestSoDCertification.java | 32 ++++++++++--------- .../midpoint/model/impl/lens/Clockwork.java | 1 + 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrWorkItemDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrWorkItemDto.java index ddc4cd3e817..45e1fd239f3 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrWorkItemDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrWorkItemDto.java @@ -208,19 +208,21 @@ public String getConflictingTargets() { return ""; } Set exclusions = new TreeSet<>(); - for (EvaluatedPolicyRuleTriggerType trigger : assignmentCase.getAssignment().getTrigger()) { - if (!(trigger instanceof EvaluatedExclusionTriggerType)) { - continue; - } - EvaluatedExclusionTriggerType exclusionTrigger = (EvaluatedExclusionTriggerType) trigger; - ObjectReferenceType conflicting = exclusionTrigger.getConflictingObjectRef(); - if (conflicting == null) { - continue; - } - if (conflicting.getTargetName() != null) { - exclusions.add(conflicting.getTargetName().getOrig()); - } else { - exclusions.add(conflicting.getOid()); // TODO try to resolve? + for (EvaluatedPolicyRuleType rule : assignmentCase.getAssignment().getTriggeredPolicyRule()) { + for (EvaluatedPolicyRuleTriggerType trigger : rule.getTrigger()) { + if (!(trigger instanceof EvaluatedExclusionTriggerType)) { + continue; + } + EvaluatedExclusionTriggerType exclusionTrigger = (EvaluatedExclusionTriggerType) trigger; + ObjectReferenceType conflicting = exclusionTrigger.getConflictingObjectRef(); + if (conflicting == null) { + continue; + } + if (conflicting.getTargetName() != null) { + exclusions.add(conflicting.getTargetName().getOrig()); + } else { + exclusions.add(conflicting.getOid()); // TODO try to resolve? + } } } return StringUtils.join(exclusions, ", "); diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java index e81f15618e0..073bfcab529 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java @@ -128,23 +128,25 @@ public void test001Triggers() throws Exception { private void assertPacked(AssignmentType assignment, int exclusionExpected, int situationExpected) { int exclusion = 0, situation = 0; - for (EvaluatedPolicyRuleTriggerType trigger : assignment.getTrigger()) { - assertNotNull("Identifier not null in base trigger: " + trigger, trigger.getTriggerId()); - if (trigger instanceof EvaluatedSituationTriggerType) { - EvaluatedSituationTriggerType situationTrigger = (EvaluatedSituationTriggerType) trigger; - int sourceTriggers = 0; - for (EvaluatedPolicyRuleType sourceRule : situationTrigger.getSourceRule()) { - for (EvaluatedPolicyRuleTriggerType sourceTrigger : sourceRule.getTrigger()) { - sourceTriggers++; - assertNotNull("Ref not null in situation source trigger: " + sourceTrigger, sourceTrigger.getRef()); + for (EvaluatedPolicyRuleType rule : assignment.getTriggeredPolicyRule()) { + for (EvaluatedPolicyRuleTriggerType trigger : rule.getTrigger()) { + assertNotNull("Identifier not null in base trigger: " + trigger, trigger.getTriggerId()); + if (trigger instanceof EvaluatedSituationTriggerType) { + EvaluatedSituationTriggerType situationTrigger = (EvaluatedSituationTriggerType) trigger; + int sourceTriggers = 0; + for (EvaluatedPolicyRuleType sourceRule : situationTrigger.getSourceRule()) { + for (EvaluatedPolicyRuleTriggerType sourceTrigger : sourceRule.getTrigger()) { + sourceTriggers++; + assertNotNull("Ref not null in situation source trigger: " + sourceTrigger, sourceTrigger.getRef()); + } } + assertEquals("Wrong # of exclusion triggers in situation trigger", exclusionExpected, sourceTriggers); + situation++; + } else if (trigger instanceof EvaluatedExclusionTriggerType) { + exclusion++; + } else { + fail("Unexpected trigger: " + trigger); } - assertEquals("Wrong # of exclusion triggers in situation trigger", exclusionExpected, sourceTriggers); - situation++; - } else if (trigger instanceof EvaluatedExclusionTriggerType) { - exclusion++; - } else { - fail("Unexpected trigger: " + trigger); } } assertEquals("Wrong # of exclusion triggers", exclusionExpected, exclusion); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java index 2d54d66706c..cd679cbff0a 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java @@ -1428,6 +1428,7 @@ private void authorizeAssignmentRequ assignActionUrl.substring(assignActionUrl.lastIndexOf('#') + 1)); } securityEnforcer.failAuthorization("with assignment", getRequestAuthorizationPhase(context), object, null, null, result); + assert false; // just to keep static checkers happy } // We do not worry about performance here too much. The target was already evaluated. This will be retrieved from repo cache anyway. PrismObject target = objectResolver.resolve(targetRef.asReferenceValue(), "resolving assignment target", task, result); From fbfcea081aa7bfe8a10e76644ca80fa493171011 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 25 Sep 2017 15:31:49 +0200 Subject: [PATCH 08/19] Migrating TestSoDCertification --- .../certification/test/TestSoDCertification.java | 16 ++++++++-------- .../resources/common/system-configuration.xml | 1 + .../src/test/resources/sod/a-test-2a.xml | 2 ++ .../src/test/resources/sod/a-test-2b.xml | 2 ++ .../src/test/resources/sod/a-test-2c.xml | 2 ++ .../src/test/resources/sod/a-test-3x.xml | 1 + .../src/test/resources/sod/a-test-3y.xml | 1 + 7 files changed, 17 insertions(+), 8 deletions(-) diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java index 073bfcab529..582b87d6791 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java @@ -111,33 +111,33 @@ public void test001Triggers() throws Exception { // THEN AssignmentType a2a = findAssignmentByTargetRequired(jack, roleATest2aOid); display("assignment 2a", a2a); - assertPacked(a2a, 2, 1); + assertTriggers(a2a, 2, 1); AssignmentType a2b = findAssignmentByTargetRequired(jack, roleATest2bOid); display("assignment 2b", a2b); - assertPacked(a2b, 2, 1); + assertTriggers(a2b, 2, 1); AssignmentType a2c = findAssignmentByTargetRequired(jack, roleATest2cOid); display("assignment 2c", a2c); - assertPacked(a2c, 2, 1); + assertTriggers(a2c, 2, 1); AssignmentType a3a = findAssignmentByTargetRequired(jack, roleATest3aOid); display("assignment 3a", a3a); - assertPacked(a3a, 1, 1); + assertTriggers(a3a, 1, 1); AssignmentType a3b = findAssignmentByTargetRequired(jack, roleATest3bOid); display("assignment 3b", a3b); - assertPacked(a3b, 1, 1); + assertTriggers(a3b, 1, 1); } - private void assertPacked(AssignmentType assignment, int exclusionExpected, int situationExpected) { + private void assertTriggers(AssignmentType assignment, int exclusionExpected, int situationExpected) { int exclusion = 0, situation = 0; for (EvaluatedPolicyRuleType rule : assignment.getTriggeredPolicyRule()) { for (EvaluatedPolicyRuleTriggerType trigger : rule.getTrigger()) { - assertNotNull("Identifier not null in base trigger: " + trigger, trigger.getTriggerId()); + //assertNotNull("Identifier not null in base trigger: " + trigger, trigger.getTriggerId()); if (trigger instanceof EvaluatedSituationTriggerType) { EvaluatedSituationTriggerType situationTrigger = (EvaluatedSituationTriggerType) trigger; int sourceTriggers = 0; for (EvaluatedPolicyRuleType sourceRule : situationTrigger.getSourceRule()) { for (EvaluatedPolicyRuleTriggerType sourceTrigger : sourceRule.getTrigger()) { sourceTriggers++; - assertNotNull("Ref not null in situation source trigger: " + sourceTrigger, sourceTrigger.getRef()); + //assertNotNull("Ref not null in situation source trigger: " + sourceTrigger, sourceTrigger.getRef()); } } assertEquals("Wrong # of exclusion triggers in situation trigger", exclusionExpected, sourceTriggers); diff --git a/model/certification-impl/src/test/resources/common/system-configuration.xml b/model/certification-impl/src/test/resources/common/system-configuration.xml index c2d374ee66e..d5ecbe90516 100644 --- a/model/certification-impl/src/test/resources/common/system-configuration.xml +++ b/model/certification-impl/src/test/resources/common/system-configuration.xml @@ -53,6 +53,7 @@ + diff --git a/model/certification-impl/src/test/resources/sod/a-test-2a.xml b/model/certification-impl/src/test/resources/sod/a-test-2a.xml index f7d38b463a4..9c9fdb325e0 100644 --- a/model/certification-impl/src/test/resources/sod/a-test-2a.xml +++ b/model/certification-impl/src/test/resources/sod/a-test-2a.xml @@ -28,6 +28,7 @@ + @@ -39,6 +40,7 @@ + diff --git a/model/certification-impl/src/test/resources/sod/a-test-2b.xml b/model/certification-impl/src/test/resources/sod/a-test-2b.xml index 0410d03a913..93a12df6277 100644 --- a/model/certification-impl/src/test/resources/sod/a-test-2b.xml +++ b/model/certification-impl/src/test/resources/sod/a-test-2b.xml @@ -28,6 +28,7 @@ + @@ -39,6 +40,7 @@ + diff --git a/model/certification-impl/src/test/resources/sod/a-test-2c.xml b/model/certification-impl/src/test/resources/sod/a-test-2c.xml index 3a8b9d59679..9d3585debc6 100644 --- a/model/certification-impl/src/test/resources/sod/a-test-2c.xml +++ b/model/certification-impl/src/test/resources/sod/a-test-2c.xml @@ -28,6 +28,7 @@ + @@ -39,6 +40,7 @@ + diff --git a/model/certification-impl/src/test/resources/sod/a-test-3x.xml b/model/certification-impl/src/test/resources/sod/a-test-3x.xml index cc4229f71d3..72a34577f2c 100644 --- a/model/certification-impl/src/test/resources/sod/a-test-3x.xml +++ b/model/certification-impl/src/test/resources/sod/a-test-3x.xml @@ -28,6 +28,7 @@ + diff --git a/model/certification-impl/src/test/resources/sod/a-test-3y.xml b/model/certification-impl/src/test/resources/sod/a-test-3y.xml index e0168ef0670..fa582b7db0d 100644 --- a/model/certification-impl/src/test/resources/sod/a-test-3y.xml +++ b/model/certification-impl/src/test/resources/sod/a-test-3y.xml @@ -28,6 +28,7 @@ + From 8175271056b0aeab291e98993ef2e6e7eb2a168f Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 26 Sep 2017 09:17:17 +0200 Subject: [PATCH 09/19] Minor improvements in handling of indirectly present exclusion triggers. --- .../dto/CertCaseOrWorkItemDto.java | 28 +- .../schema/util/PolicyRuleTypeUtil.java | 28 ++ .../test/TestSoDCertification.java | 8 +- .../src/test/resources/sod/a-test-2a.xml | 6 - .../src/test/resources/sod/a-test-2b.xml | 6 - .../src/test/resources/sod/a-test-2c.xml | 6 - .../src/test/resources/sod/a-test-3x.xml | 3 - .../src/test/resources/sod/a-test-3y.xml | 3 - .../midpoint/model/impl/lens/Clockwork.java | 2 +- .../model/impl/lens/TestPolicyState.java | 158 ----------- .../impl/lens/TestPolicyStateRecording.java | 259 ++++++++++++++++++ .../resources/lens/policy/state/a-test-2a.xml | 44 +++ .../resources/lens/policy/state/a-test-2b.xml | 44 +++ .../resources/lens/policy/state/a-test-2c.xml | 44 +++ .../resources/lens/policy/state/a-test-3a.xml | 29 ++ .../resources/lens/policy/state/a-test-3b.xml | 29 ++ .../resources/lens/policy/state/a-test-3x.xml | 35 +++ .../resources/lens/policy/state/a-test-3y.xml | 35 +++ .../policy/state/metarole-common-rules.xml | 34 +++ .../resources/lens/policy/state/user-bob.xml | 23 ++ model/model-impl/testng-unit.xml | 2 +- 21 files changed, 626 insertions(+), 200 deletions(-) delete mode 100644 model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyState.java create mode 100644 model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java create mode 100644 model/model-impl/src/test/resources/lens/policy/state/a-test-2a.xml create mode 100644 model/model-impl/src/test/resources/lens/policy/state/a-test-2b.xml create mode 100644 model/model-impl/src/test/resources/lens/policy/state/a-test-2c.xml create mode 100644 model/model-impl/src/test/resources/lens/policy/state/a-test-3a.xml create mode 100644 model/model-impl/src/test/resources/lens/policy/state/a-test-3b.xml create mode 100644 model/model-impl/src/test/resources/lens/policy/state/a-test-3x.xml create mode 100644 model/model-impl/src/test/resources/lens/policy/state/a-test-3y.xml create mode 100644 model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml create mode 100644 model/model-impl/src/test/resources/lens/policy/state/user-bob.xml diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrWorkItemDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrWorkItemDto.java index 45e1fd239f3..55e148c43d3 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrWorkItemDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrWorkItemDto.java @@ -20,6 +20,7 @@ import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.schema.util.CertCampaignTypeUtil; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.schema.util.PolicyRuleTypeUtil; import com.evolveum.midpoint.web.component.util.Selectable; import com.evolveum.midpoint.web.page.admin.certification.CertDecisionHelper; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; @@ -208,21 +209,18 @@ public String getConflictingTargets() { return ""; } Set exclusions = new TreeSet<>(); - for (EvaluatedPolicyRuleType rule : assignmentCase.getAssignment().getTriggeredPolicyRule()) { - for (EvaluatedPolicyRuleTriggerType trigger : rule.getTrigger()) { - if (!(trigger instanceof EvaluatedExclusionTriggerType)) { - continue; - } - EvaluatedExclusionTriggerType exclusionTrigger = (EvaluatedExclusionTriggerType) trigger; - ObjectReferenceType conflicting = exclusionTrigger.getConflictingObjectRef(); - if (conflicting == null) { - continue; - } - if (conflicting.getTargetName() != null) { - exclusions.add(conflicting.getTargetName().getOrig()); - } else { - exclusions.add(conflicting.getOid()); // TODO try to resolve? - } + List allExclusionTriggers = PolicyRuleTypeUtil + .getAllExclusionTriggers(assignmentCase.getAssignment().getTriggeredPolicyRule()); + + for (EvaluatedExclusionTriggerType trigger : allExclusionTriggers) { + ObjectReferenceType conflicting = trigger.getConflictingObjectRef(); + if (conflicting == null) { + continue; + } + if (conflicting.getTargetName() != null) { + exclusions.add(conflicting.getTargetName().getOrig()); + } else { + exclusions.add(conflicting.getOid()); // TODO try to resolve? } } return StringUtils.join(exclusions, ", "); diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/PolicyRuleTypeUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/PolicyRuleTypeUtil.java index 9bf9fe5bebd..7f182da81c4 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/PolicyRuleTypeUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/PolicyRuleTypeUtil.java @@ -633,4 +633,32 @@ private static Supplier getAllExclusionTriggers(List rules) { + List rv = new ArrayList<>(); + getExclusionTriggersFromRules(rv, rules); + return rv; + } + + private static void getExclusionTriggersFromRules(List rv, List rules) { + for (EvaluatedPolicyRuleType rule : rules) { + getExclusionTriggersFromRule(rv, rule); + } + } + + private static void getExclusionTriggersFromRule(List rv, EvaluatedPolicyRuleType rule) { + getExclusionTriggersFromTriggers(rv, rule.getTrigger()); + } + + private static void getExclusionTriggersFromTriggers(List rv, List triggers) { + for (EvaluatedPolicyRuleTriggerType trigger : triggers) { + if (trigger instanceof EvaluatedExclusionTriggerType) { + rv.add((EvaluatedExclusionTriggerType) trigger); + } else if (trigger instanceof EvaluatedEmbeddingTriggerType) { + getExclusionTriggersFromTriggers(rv, ((EvaluatedEmbeddingTriggerType) trigger).getEmbedded()); + } else if (trigger instanceof EvaluatedSituationTriggerType) { + getExclusionTriggersFromRules(rv, ((EvaluatedSituationTriggerType) trigger).getSourceRule()); + } + } + } } diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java index 582b87d6791..b7eb388b72d 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.CertCampaignTypeUtil; +import com.evolveum.midpoint.schema.util.PolicyRuleTypeUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.DebugUtil; @@ -149,8 +150,13 @@ private void assertTriggers(AssignmentType assignment, int exclusionExpected, in } } } - assertEquals("Wrong # of exclusion triggers", exclusionExpected, exclusion); + assertEquals("Wrong # of exclusion triggers", 0, exclusion); assertEquals("Wrong # of situation triggers", situationExpected, situation); + + List exclusionTriggers = PolicyRuleTypeUtil + .getAllExclusionTriggers(assignment.getTriggeredPolicyRule()); + display("Exclusion triggers for " + assignment, exclusionTriggers); + assertEquals("Wrong # of extracted exclusion triggers", exclusionExpected, exclusionTriggers.size()); } @Test diff --git a/model/certification-impl/src/test/resources/sod/a-test-2a.xml b/model/certification-impl/src/test/resources/sod/a-test-2a.xml index 9c9fdb325e0..b04d20ed5b8 100644 --- a/model/certification-impl/src/test/resources/sod/a-test-2a.xml +++ b/model/certification-impl/src/test/resources/sod/a-test-2a.xml @@ -27,9 +27,6 @@ - - - @@ -39,9 +36,6 @@ - - - diff --git a/model/certification-impl/src/test/resources/sod/a-test-2b.xml b/model/certification-impl/src/test/resources/sod/a-test-2b.xml index 93a12df6277..cf2b61f704a 100644 --- a/model/certification-impl/src/test/resources/sod/a-test-2b.xml +++ b/model/certification-impl/src/test/resources/sod/a-test-2b.xml @@ -27,9 +27,6 @@ - - - @@ -39,9 +36,6 @@ - - - \ No newline at end of file diff --git a/model/certification-impl/src/test/resources/sod/a-test-2c.xml b/model/certification-impl/src/test/resources/sod/a-test-2c.xml index 9d3585debc6..345cf283f3a 100644 --- a/model/certification-impl/src/test/resources/sod/a-test-2c.xml +++ b/model/certification-impl/src/test/resources/sod/a-test-2c.xml @@ -27,9 +27,6 @@ - - - @@ -39,9 +36,6 @@ - - - \ No newline at end of file diff --git a/model/certification-impl/src/test/resources/sod/a-test-3x.xml b/model/certification-impl/src/test/resources/sod/a-test-3x.xml index 72a34577f2c..33d7e2f8eb3 100644 --- a/model/certification-impl/src/test/resources/sod/a-test-3x.xml +++ b/model/certification-impl/src/test/resources/sod/a-test-3x.xml @@ -27,9 +27,6 @@ - - - \ No newline at end of file diff --git a/model/certification-impl/src/test/resources/sod/a-test-3y.xml b/model/certification-impl/src/test/resources/sod/a-test-3y.xml index fa582b7db0d..ca73b1e7c6d 100644 --- a/model/certification-impl/src/test/resources/sod/a-test-3y.xml +++ b/model/certification-impl/src/test/resources/sod/a-test-3y.xml @@ -27,9 +27,6 @@ - - - \ No newline at end of file diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java index cd679cbff0a..0c17da9269e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java @@ -1434,7 +1434,7 @@ private void authorizeAssignmentRequ PrismObject target = objectResolver.resolve(targetRef.asReferenceValue(), "resolving assignment target", task, result); if (prohibitPolicies) { - if (changedAssignment.getPolicyRule() != null || !changedAssignment.getPolicyException().isEmpty() || !changedAssignment.getPolicySituation().isEmpty()) { + if (changedAssignment.getPolicyRule() != null || !changedAssignment.getPolicyException().isEmpty() || !changedAssignment.getPolicySituation().isEmpty() || !changedAssignment.getTriggeredPolicyRule().isEmpty()) { securityEnforcer.failAuthorization("with assignment because of policies in the assignment", getRequestAuthorizationPhase(context), object, null, target, result); } } diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyState.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyState.java deleted file mode 100644 index b5fbff1586d..00000000000 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyState.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2010-2017 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.evolveum.midpoint.model.impl.lens; - -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.internals.InternalMonitor; -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.util.DebugUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentPolicyEnforcementType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -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 java.util.Collections; - -import static com.evolveum.midpoint.test.IntegrationTestTools.display; -import static org.testng.AssertJUnit.assertEquals; - -/** - * Tests recording of policy situations into objects and assignments. - * - * @author mederly - * - */ -@ContextConfiguration(locations = {"classpath:ctx-model-test-main.xml"}) -@DirtiesContext(classMode = ClassMode.AFTER_CLASS) -public class TestPolicyState extends AbstractLensTest { - - private static final String ROLE_JUDGE_POLICY_RULE_EXCLUSION_NAME = "criminal exclusion"; - - @Override - public void initSystem(Task initTask, OperationResult initResult) throws Exception { - super.initSystem(initTask, initResult); - setDefaultUserTemplate(USER_TEMPLATE_OID); - - addObject(ROLE_PIRATE_SITUATION_ONLY_FILE); - addObject(ROLE_MUTINIER_FILE); - addObject(ROLE_JUDGE_SITUATION_ONLY_FILE); - addObject(ROLE_CONSTABLE_FILE); - addObject(ROLE_THIEF_FILE); - - addObjects(ROLE_CORP_FILES); - - assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); - - InternalMonitor.reset(); - - DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); - } - - @Test - public void test100JackAssignRoleJudge() throws Exception { - final String TEST_NAME = "test100JackAssignRoleJudge"; - TestUtil.displayTestTitle(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestPolicyState.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - assignRole(USER_JACK_OID, ROLE_JUDGE_OID, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - UserType jack = getUser(USER_JACK_OID).asObjectable(); - display("jack", jack); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertAssignedRole(USER_JACK_OID, ROLE_JUDGE_OID, task, result); - assertEquals("Wrong # of assignments", 1, jack.getAssignment().size()); - assertEquals("Wrong policy situations", - Collections.emptyList(), - jack.getAssignment().get(0).getPolicySituation()); - } - - @Test - public void test110JackAssignRolePirate() throws Exception { - final String TEST_NAME = "test110JackAssignRolePirate"; - TestUtil.displayTestTitle(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestPolicyState.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - assignRole(USER_JACK_OID, ROLE_PIRATE_OID, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - UserType jack = getUser(USER_JACK_OID).asObjectable(); - display("jack", jack); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertAssignedRole(USER_JACK_OID, ROLE_PIRATE_OID, task, result); - assertEquals("Wrong # of assignments", 2, jack.getAssignment().size()); - for (AssignmentType assignment : jack.getAssignment()) { - assertEquals("Wrong policy situations", - Collections.singletonList(SchemaConstants.MODEL_POLICY_SITUATION_EXCLUSION_VIOLATION), - assignment.getPolicySituation()); - } - } - - // should keep the situation for both assignments - @Test - public void test120RecomputeJack() throws Exception { - final String TEST_NAME = "test120RecomputeJack"; - TestUtil.displayTestTitle(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestPolicyState.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); - - // WHEN - TestUtil.displayWhen(TEST_NAME); - recomputeUser(USER_JACK_OID, task, result); - - // THEN - TestUtil.displayThen(TEST_NAME); - UserType jack = getUser(USER_JACK_OID).asObjectable(); - display("jack", jack); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertEquals("Wrong # of assignments", 2, jack.getAssignment().size()); - for (AssignmentType assignment : jack.getAssignment()) { - assertEquals("Wrong policy situations", - Collections.singletonList(SchemaConstants.MODEL_POLICY_SITUATION_EXCLUSION_VIOLATION), - assignment.getPolicySituation()); - } - } - - - - -} diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java new file mode 100644 index 00000000000..062fddae56b --- /dev/null +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2010-2017 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.evolveum.midpoint.model.impl.lens; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.internals.InternalMonitor; +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.util.DebugUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentPolicyEnforcementType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +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 java.io.File; +import java.util.Collections; + +import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createAssignmentTo; +import static org.testng.AssertJUnit.assertEquals; + +/** + * Tests recording of policy situations into objects and assignments. + * + * @author mederly + * + */ +@ContextConfiguration(locations = {"classpath:ctx-model-test-main.xml"}) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public class TestPolicyStateRecording extends AbstractLensTest { + + private static final String ROLE_JUDGE_POLICY_RULE_EXCLUSION_NAME = "criminal exclusion"; + + protected static final File TEST_DIR = new File(AbstractLensTest.TEST_DIR, "policy/state"); + + private static final File USER_BOB_FILE = new File(TEST_DIR, "user-bob.xml"); + private static String userBobOid; + private static final File ROLE_A_TEST_2A_FILE = new File(TEST_DIR, "a-test-2a.xml"); + private static String roleATest2aOid; + private static final File ROLE_A_TEST_2B_FILE = new File(TEST_DIR, "a-test-2b.xml"); + private static String roleATest2bOid; + private static final File ROLE_A_TEST_2C_FILE = new File(TEST_DIR, "a-test-2c.xml"); + private static String roleATest2cOid; + private static final File ROLE_A_TEST_3A_FILE = new File(TEST_DIR, "a-test-3a.xml"); + private static String roleATest3aOid; + private static final File ROLE_A_TEST_3B_FILE = new File(TEST_DIR, "a-test-3b.xml"); + private static String roleATest3bOid; + private static final File ROLE_A_TEST_3X_FILE = new File(TEST_DIR, "a-test-3x.xml"); + private static String roleATest3xOid; + private static final File ROLE_A_TEST_3Y_FILE = new File(TEST_DIR, "a-test-3y.xml"); + private static String roleATest3yOid; + private static final File METAROLE_COMMON_RULES_FILE = new File(TEST_DIR, "metarole-common-rules.xml"); + private static String metaroleCommonRulesOid; + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + setDefaultUserTemplate(USER_TEMPLATE_OID); + + addObject(ROLE_PIRATE_SITUATION_ONLY_FILE); + addObject(ROLE_JUDGE_SITUATION_ONLY_FILE); + + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); + + metaroleCommonRulesOid = addAndRecompute(METAROLE_COMMON_RULES_FILE, initTask, initResult); + roleATest2aOid = addAndRecompute(ROLE_A_TEST_2A_FILE, initTask, initResult); + roleATest2bOid = addAndRecompute(ROLE_A_TEST_2B_FILE, initTask, initResult); + roleATest2cOid = addAndRecompute(ROLE_A_TEST_2C_FILE, initTask, initResult); + roleATest3xOid = addAndRecompute(ROLE_A_TEST_3X_FILE, initTask, initResult); + roleATest3yOid = addAndRecompute(ROLE_A_TEST_3Y_FILE, initTask, initResult); + roleATest3aOid = addAndRecompute(ROLE_A_TEST_3A_FILE, initTask, initResult); + roleATest3bOid = addAndRecompute(ROLE_A_TEST_3B_FILE, initTask, initResult); + + userBobOid = addAndRecompute(USER_BOB_FILE, initTask, initResult); + + InternalMonitor.reset(); + + DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); + } + + @Test + public void test100JackAssignRoleJudge() throws Exception { + final String TEST_NAME = "test100JackAssignRoleJudge"; + TestUtil.displayTestTitle(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestPolicyStateRecording.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + assignRole(USER_JACK_OID, ROLE_JUDGE_OID, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + UserType jack = getUser(USER_JACK_OID).asObjectable(); + display("jack", jack); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertAssignedRole(USER_JACK_OID, ROLE_JUDGE_OID, task, result); + assertEquals("Wrong # of assignments", 1, jack.getAssignment().size()); + assertEquals("Wrong policy situations", + Collections.emptyList(), + jack.getAssignment().get(0).getPolicySituation()); + } + + @Test + public void test110JackAssignRolePirate() throws Exception { + final String TEST_NAME = "test110JackAssignRolePirate"; + TestUtil.displayTestTitle(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestPolicyStateRecording.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + assignRole(USER_JACK_OID, ROLE_PIRATE_OID, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + UserType jack = getUser(USER_JACK_OID).asObjectable(); + display("jack", jack); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertAssignedRole(USER_JACK_OID, ROLE_PIRATE_OID, task, result); + assertEquals("Wrong # of assignments", 2, jack.getAssignment().size()); + for (AssignmentType assignment : jack.getAssignment()) { + assertEquals("Wrong policy situations", + Collections.singletonList(SchemaConstants.MODEL_POLICY_SITUATION_EXCLUSION_VIOLATION), + assignment.getPolicySituation()); + } + } + + // should keep the situation for both assignments + @Test + public void test120RecomputeJack() throws Exception { + final String TEST_NAME = "test120RecomputeJack"; + TestUtil.displayTestTitle(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestPolicyStateRecording.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + recomputeUser(USER_JACK_OID, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + UserType jack = getUser(USER_JACK_OID).asObjectable(); + display("jack", jack); + result.computeStatus(); + TestUtil.assertSuccess(result); + + // TODO test that assignment IDs are filled in correctly (currently they are not) + assertEquals("Wrong # of assignments", 2, jack.getAssignment().size()); + for (AssignmentType assignment : jack.getAssignment()) { + assertEquals("Wrong policy situations", + Collections.singletonList(SchemaConstants.MODEL_POLICY_SITUATION_EXCLUSION_VIOLATION), + assignment.getPolicySituation()); + } + } + + @Test + public void test200BobAssign2a3a() throws Exception { + final String TEST_NAME = "test200BobAssign2a3a"; + TestUtil.displayTestTitle(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestPolicyStateRecording.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + ObjectDelta delta = DeltaBuilder.deltaFor(UserType.class, prismContext) + .item(UserType.F_ASSIGNMENT) + .add(createAssignmentTo(roleATest2aOid, ObjectTypes.ROLE, prismContext), + createAssignmentTo(roleATest3aOid, ObjectTypes.ROLE, prismContext)) + .asObjectDeltaCast(userBobOid); + executeChangesAssertSuccess(delta, null, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + UserType bob = getUser(userBobOid).asObjectable(); + display("bob", bob); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertAssignedRole(userBobOid, roleATest2aOid, task, result); + assertAssignedRole(userBobOid, roleATest3aOid, task, result); + assertEquals("Wrong # of assignments", 2, bob.getAssignment().size()); + assertEquals("Wrong policy situations for assignment 1", + Collections.emptyList(), + bob.getAssignment().get(0).getPolicySituation()); + assertEquals("Wrong policy situations for assignment 2", + Collections.emptyList(), + bob.getAssignment().get(1).getPolicySituation()); + } + + @Test + public void test200BobAssign2b3b() throws Exception { + final String TEST_NAME = "test200BobAssign2b3b"; + TestUtil.displayTestTitle(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestPolicyStateRecording.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + ObjectDelta delta = DeltaBuilder.deltaFor(UserType.class, prismContext) + .item(UserType.F_ASSIGNMENT) + .add(createAssignmentTo(roleATest2bOid, ObjectTypes.ROLE, prismContext), + createAssignmentTo(roleATest3bOid, ObjectTypes.ROLE, prismContext)) + .asObjectDeltaCast(userBobOid); + executeChangesAssertSuccess(delta, null, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + UserType bob = getUser(userBobOid).asObjectable(); + display("bob", bob); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertAssignedRole(userBobOid, roleATest2aOid, task, result); + assertAssignedRole(userBobOid, roleATest2bOid, task, result); + assertAssignedRole(userBobOid, roleATest3aOid, task, result); + assertAssignedRole(userBobOid, roleATest3bOid, task, result); + assertEquals("Wrong # of assignments", 4, bob.getAssignment().size()); + + // TODO policy state + } + + + +} diff --git a/model/model-impl/src/test/resources/lens/policy/state/a-test-2a.xml b/model/model-impl/src/test/resources/lens/policy/state/a-test-2a.xml new file mode 100644 index 00000000000..4890bdcca79 --- /dev/null +++ b/model/model-impl/src/test/resources/lens/policy/state/a-test-2a.xml @@ -0,0 +1,44 @@ + + + + a-test-2a + Exclusive with test-2b/2c + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/model/model-impl/src/test/resources/lens/policy/state/a-test-2b.xml b/model/model-impl/src/test/resources/lens/policy/state/a-test-2b.xml new file mode 100644 index 00000000000..7d810e87a69 --- /dev/null +++ b/model/model-impl/src/test/resources/lens/policy/state/a-test-2b.xml @@ -0,0 +1,44 @@ + + + + a-test-2b + Exclusive with test-2a/2c + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/model/model-impl/src/test/resources/lens/policy/state/a-test-2c.xml b/model/model-impl/src/test/resources/lens/policy/state/a-test-2c.xml new file mode 100644 index 00000000000..740b763c6cd --- /dev/null +++ b/model/model-impl/src/test/resources/lens/policy/state/a-test-2c.xml @@ -0,0 +1,44 @@ + + + + a-test-2c + Exclusive with test-2a/2b + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/model/model-impl/src/test/resources/lens/policy/state/a-test-3a.xml b/model/model-impl/src/test/resources/lens/policy/state/a-test-3a.xml new file mode 100644 index 00000000000..fac95988ee0 --- /dev/null +++ b/model/model-impl/src/test/resources/lens/policy/state/a-test-3a.xml @@ -0,0 +1,29 @@ + + + + a-test-3a + Testing SoD with induced role (test-3x) + + + + + + + \ No newline at end of file diff --git a/model/model-impl/src/test/resources/lens/policy/state/a-test-3b.xml b/model/model-impl/src/test/resources/lens/policy/state/a-test-3b.xml new file mode 100644 index 00000000000..9dea26df089 --- /dev/null +++ b/model/model-impl/src/test/resources/lens/policy/state/a-test-3b.xml @@ -0,0 +1,29 @@ + + + + a-test-3b + Testing SoD with induced role (test-3y) + + + + + + + \ No newline at end of file diff --git a/model/model-impl/src/test/resources/lens/policy/state/a-test-3x.xml b/model/model-impl/src/test/resources/lens/policy/state/a-test-3x.xml new file mode 100644 index 00000000000..26a15f21532 --- /dev/null +++ b/model/model-impl/src/test/resources/lens/policy/state/a-test-3x.xml @@ -0,0 +1,35 @@ + + + + a-test-3x + Embedded role, conflicting with 3y + + + + + + + + + + + + + \ No newline at end of file diff --git a/model/model-impl/src/test/resources/lens/policy/state/a-test-3y.xml b/model/model-impl/src/test/resources/lens/policy/state/a-test-3y.xml new file mode 100644 index 00000000000..f7bce8db1d0 --- /dev/null +++ b/model/model-impl/src/test/resources/lens/policy/state/a-test-3y.xml @@ -0,0 +1,35 @@ + + + + a-test-3y + Embedded role, conflicting with 3x + + + + + + + + + + + + + \ No newline at end of file diff --git a/model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml b/model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml new file mode 100644 index 00000000000..1bf5c1f09b2 --- /dev/null +++ b/model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml @@ -0,0 +1,34 @@ + + + + common-rules + + + + + http://midpoint.evolveum.com/xml/ns/public/model/policy/situation#exclusionViolation + + + + + + + + \ No newline at end of file diff --git a/model/model-impl/src/test/resources/lens/policy/state/user-bob.xml b/model/model-impl/src/test/resources/lens/policy/state/user-bob.xml new file mode 100644 index 00000000000..1fb0475364f --- /dev/null +++ b/model/model-impl/src/test/resources/lens/policy/state/user-bob.xml @@ -0,0 +1,23 @@ + + + + + bob + Bob + Bobovic + diff --git a/model/model-impl/testng-unit.xml b/model/model-impl/testng-unit.xml index b6c29d43ecc..90f316133bd 100644 --- a/model/model-impl/testng-unit.xml +++ b/model/model-impl/testng-unit.xml @@ -72,7 +72,7 @@ - + From aab94cd4c83174f4dddcf377ca9c3741c9d1a08e Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 26 Sep 2017 12:34:02 +0200 Subject: [PATCH 10/19] Fixed storing policy state. --- .../util/xml/DomAwareEqualsStrategy.java | 41 +++++++-- .../model/impl/lens/AssignmentSpec.java | 2 +- .../model/impl/lens/ChangeExecutor.java | 84 +++++++++---------- .../impl/lens/EvaluatedAssignmentImpl.java | 16 ++-- .../model/impl/lens/LensElementContext.java | 14 +++- .../projector/policy/PolicyStateUpdater.java | 5 +- .../model/impl/lens/AbstractLensTest.java | 4 +- .../impl/lens/TestPolicyStateRecording.java | 4 +- ...on-only.xml => role-judge-record-only.xml} | 0 ...n-only.xml => role-pirate-record-only.xml} | 0 10 files changed, 106 insertions(+), 64 deletions(-) rename model/model-impl/src/test/resources/lens/{role-judge-situation-only.xml => role-judge-record-only.xml} (100%) rename model/model-impl/src/test/resources/lens/{role-pirate-situation-only.xml => role-pirate-record-only.xml} (100%) diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/xml/DomAwareEqualsStrategy.java b/infra/util/src/main/java/com/evolveum/midpoint/util/xml/DomAwareEqualsStrategy.java index 45adb915377..358e6cb2a7a 100644 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/xml/DomAwareEqualsStrategy.java +++ b/infra/util/src/main/java/com/evolveum/midpoint/util/xml/DomAwareEqualsStrategy.java @@ -15,7 +15,7 @@ */ package com.evolveum.midpoint.util.xml; -import org.jvnet.jaxb2_commons.lang.EqualsStrategy; +import com.evolveum.midpoint.util.PrettyPrinter; import org.jvnet.jaxb2_commons.lang.JAXBEqualsStrategy; import org.jvnet.jaxb2_commons.locator.ObjectLocator; import org.w3c.dom.Element; @@ -31,23 +31,48 @@ */ public class DomAwareEqualsStrategy extends JAXBEqualsStrategy { - public static EqualsStrategy INSTANCE = new DomAwareEqualsStrategy(); + public static DomAwareEqualsStrategy INSTANCE = new DomAwareEqualsStrategy(); + + private static final boolean ENABLE_BRUTAL_DEBUGGING = false; // keep false to avoid unnecessary code execution + private boolean traceAll = false; + private boolean traceNotEqual = false; + + public boolean isTraceAll() { + return traceAll; + } + + public void setTraceAll(boolean traceAll) { + this.traceAll = traceAll; + } + + public boolean isTraceNotEqual() { + return traceNotEqual; + } + + public void setTraceNotEqual(boolean traceNotEqual) { + this.traceNotEqual = traceNotEqual; + } @Override protected boolean equalsInternal(ObjectLocator leftLocator, ObjectLocator rightLocator, Object lhs, Object rhs) { -// System.out.println("DomAwareEqualsStrategy: "+PrettyPrinter.prettyPrint(lhs)+"<=>"+PrettyPrinter.prettyPrint(rhs)); + if (ENABLE_BRUTAL_DEBUGGING && traceAll) { + System.out.println("DomAwareEqualsStrategy: "+ PrettyPrinter.prettyPrint(lhs)+"<=>"+PrettyPrinter.prettyPrint(rhs)); + } + boolean result; if (lhs instanceof String && rhs instanceof String) { - return DOMUtil.compareTextNodeValues((String)lhs, (String)rhs); + result = DOMUtil.compareTextNodeValues((String)lhs, (String)rhs); } else if (lhs instanceof Element && rhs instanceof Element) { final Element left = (Element) lhs; final Element right = (Element) rhs; - boolean result = DOMUtil.compareElement(left, right, false); -// System.out.println("cmp: "+PrettyPrinter.prettyPrint(left)+"<=>"+PrettyPrinter.prettyPrint(right)+": "+result); - return result; + result = DOMUtil.compareElement(left, right, false); } else { - return super.equalsInternal(leftLocator, rightLocator, lhs, rhs); + result = super.equalsInternal(leftLocator, rightLocator, lhs, rhs); + } + if (ENABLE_BRUTAL_DEBUGGING && (traceAll || traceNotEqual && !result)) { + System.out.println("cmp: "+PrettyPrinter.prettyPrint(lhs)+"<=>"+PrettyPrinter.prettyPrint(rhs)+": "+result); } + return result; } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentSpec.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentSpec.java index 713c04f4d3e..b9e384541bd 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentSpec.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentSpec.java @@ -31,7 +31,7 @@ public class AssignmentSpec implements Serializable { @NotNull public final AssignmentType assignment; - @NotNull public final PlusMinusZero mode; + @NotNull public final PlusMinusZero mode; // regarding the current object state (not the old one) public AssignmentSpec(@NotNull AssignmentType assignment, @NotNull PlusMinusZero mode) { this.assignment = assignment; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java index 64123a26558..4f146c66c70 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java @@ -148,7 +148,7 @@ public boolean executeChanges(LensContext context, Tas ObjectDelta focusDelta = focusContext.getWaveExecutableDelta(context.getExecutionWave()); focusDelta = applyPendingObjectPolicyStateModifications(focusContext, focusDelta); - applyPendingAssignmentPolicyStateModifications(focusContext, focusDelta); + focusDelta = applyPendingAssignmentPolicyStateModifications(focusContext, focusDelta); if (focusDelta != null) { @@ -375,57 +375,57 @@ private ObjectDelta applyPendingObjectPolicyStateModif return focusDelta; } - private void applyPendingAssignmentPolicyStateModifications(LensFocusContext focusContext, ObjectDelta focusDelta) + private ObjectDelta applyPendingAssignmentPolicyStateModifications(LensFocusContext focusContext, ObjectDelta focusDelta) throws SchemaException { - if (focusDelta != null) { - for (Map.Entry>> entry : focusContext - .getPendingAssignmentPolicyStateModifications().entrySet()) { - PlusMinusZero mode = entry.getKey().mode; - if (mode == PlusMinusZero.MINUS) { - continue; // this assignment is being thrown out anyway, so let's ignore it + for (Map.Entry>> entry : focusContext + .getPendingAssignmentPolicyStateModifications().entrySet()) { + PlusMinusZero mode = entry.getKey().mode; + if (mode == PlusMinusZero.MINUS) { + continue; // this assignment is being thrown out anyway, so let's ignore it + } + AssignmentType assignmentToFind = entry.getKey().assignment; + List> modifications = entry.getValue(); + if (modifications.isEmpty()) { + continue; + } + LOGGER.trace("Applying policy state modifications for {} ({}):\n{}", assignmentToFind, mode, + DebugUtil.debugDumpLazily(modifications)); + if (mode == PlusMinusZero.ZERO) { + if (assignmentToFind.getId() == null) { + throw new IllegalStateException("Existing assignment with null id: " + assignmentToFind); } - AssignmentType assignmentToFind = entry.getKey().assignment; - List> modifications = entry.getValue(); - if (modifications.isEmpty()) { - continue; + for (ItemDelta modification : modifications) { + focusDelta = focusContext.swallowToDelta(focusDelta, modification); } - LOGGER.trace("Applying policy state modifications for {} ({}):\n{}", assignmentToFind, mode, - DebugUtil.debugDumpLazily(modifications)); - if (mode == PlusMinusZero.ZERO) { - if (assignmentToFind.getId() == null) { - throw new IllegalStateException("Existing assignment with null id: " + assignmentToFind); - } - for (ItemDelta modification : modifications) { - focusContext.swallowToDelta(focusDelta, modification); - } + } else { + assert mode == PlusMinusZero.PLUS; + if (focusDelta != null && focusDelta.isAdd()) { + swallowIntoValues(((FocusType) focusDelta.getObjectToAdd().asObjectable()).getAssignment(), + assignmentToFind, modifications); } else { - assert mode == PlusMinusZero.PLUS; - if (focusDelta.isAdd()) { - swallowIntoValues(((FocusType) focusDelta.getObjectToAdd().asObjectable()).getAssignment(), - assignmentToFind, modifications); + ContainerDelta assignmentDelta = focusDelta != null ? + focusDelta.findContainerDelta(FocusType.F_ASSIGNMENT) : null; + if (assignmentDelta == null) { + throw new IllegalStateException( + "We have 'plus' assignment to modify but there's no assignment delta. Assignment=" + + assignmentToFind + ", objectDelta=" + focusDelta); + } + if (assignmentDelta.isReplace()) { + swallowIntoValues(asContainerables(assignmentDelta.getValuesToReplace()), assignmentToFind, + modifications); + } else if (assignmentDelta.isAdd()) { + swallowIntoValues(asContainerables(assignmentDelta.getValuesToAdd()), assignmentToFind, + modifications); } else { - ContainerDelta assignmentDelta = focusDelta.findContainerDelta(FocusType.F_ASSIGNMENT); - if (assignmentDelta == null) { - throw new IllegalStateException( - "We have 'plus' assignment to modify but there's no assignment delta. Assignment=" - + assignmentToFind + ", objectDelta=" + focusDelta); - } - if (assignmentDelta.isReplace()) { - swallowIntoValues(asContainerables(assignmentDelta.getValuesToReplace()), assignmentToFind, - modifications); - } else if (assignmentDelta.isAdd()) { - swallowIntoValues(asContainerables(assignmentDelta.getValuesToAdd()), assignmentToFind, - modifications); - } else { - throw new IllegalStateException( - "We have 'plus' assignment to modify but there're no values to add or replace in assignment delta. Assignment=" - + assignmentToFind + ", objectDelta=" + focusDelta); - } + throw new IllegalStateException( + "We have 'plus' assignment to modify but there're no values to add or replace in assignment delta. Assignment=" + + assignmentToFind + ", objectDelta=" + focusDelta); } } } } focusContext.clearPendingAssignmentPolicyStateModifications(); + return focusDelta; } private void swallowIntoValues(Collection assignments, AssignmentType assignmentToFind, List> modifications) diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java index 0f2193aaeee..3f6d751d075 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java @@ -44,6 +44,9 @@ import org.jetbrains.annotations.NotNull; import static com.evolveum.midpoint.prism.PrismContainerValue.asContainerable; +import static com.evolveum.midpoint.prism.delta.PlusMinusZero.MINUS; +import static com.evolveum.midpoint.prism.delta.PlusMinusZero.PLUS; +import static com.evolveum.midpoint.prism.delta.PlusMinusZero.ZERO; /** * Evaluated assignment that contains all constructions and authorizations from the assignment @@ -528,14 +531,17 @@ public List getNonNegativeTargets() { return rv; } + /** + * @return mode (adding, deleting, keeping) with respect to the *current* object (not the old one) + */ @NotNull public PlusMinusZero getMode() { - if (assignmentIdi.getItemOld() == null) { - return PlusMinusZero.PLUS; - } else if (assignmentIdi.getItemNew() == null) { - return PlusMinusZero.MINUS; + if (assignmentIdi.getItemNew() == null) { + return MINUS; + } else if (presentInCurrentObject) { + return ZERO; } else { - return PlusMinusZero.ZERO; + return PLUS; } } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java index ad8ea5e5071..e06c9609b68 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java @@ -73,15 +73,23 @@ public abstract class LensElementContext implements ModelE private String iterationToken; /** - * These are policy state modifications that should be applied regardless of how the clockwork is exited - * (e.g. in primary state, in final state, with an exception). + * These are policy state modifications that should be applied. + * Currently we apply them in ChangeExecutor.executeChanges only. * - * Currently implemented only for focus, not for projections. + * In the future we plan to be able to apply some state modifications even + * if the clockwork is exited in non-standard way (e.g. in primary state or with an exception). + * But we must be sure what policy state to store, because some constraints might be triggered + * because of expectation of future state (like conflicting assignment is added etc.) + * --- + * Although placed in LensElementContext, support for this data is currently implemented only for focus, not for projections. */ @NotNull private transient final List> pendingObjectPolicyStateModifications = new ArrayList<>(); /** * Policy state modifications for assignments. + * + * Although we put here also deltas for assignments that are to be deleted, we do not execute these + * (because we implement execution only for the standard exit-path from the clockwork). */ @NotNull private transient final Map>> pendingAssignmentPolicyStateModifications = new HashMap<>(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java index 63330d650e5..91490dc2f5b 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java @@ -24,6 +24,7 @@ import com.evolveum.midpoint.prism.delta.PlusMinusZero; import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; import com.evolveum.midpoint.prism.path.IdItemPathSegment; +import com.evolveum.midpoint.util.MiscUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -116,7 +117,9 @@ private ComputationResult compute(@NotNull List rulesToReco cr.oldPolicySituations.addAll(existingPolicySituation); cr.oldTriggeredRules.addAll(existingTriggeredPolicyRule); cr.situationsNeedUpdate = !Objects.equals(cr.oldPolicySituations, cr.newPolicySituations); - cr.rulesNeedUpdate = !Objects.equals(cr.oldTriggeredRules, cr.newTriggeredRules); + // we do not use this, because it uses hashCode, that is (for some reason) wrongly computed + //cr.rulesNeedUpdate = !Objects.equals(cr.oldTriggeredRules, cr.newTriggeredRules); + cr.rulesNeedUpdate = !MiscUtil.unorderedCollectionEquals(cr.oldTriggeredRules, cr.newTriggeredRules); return cr; } diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/AbstractLensTest.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/AbstractLensTest.java index b64dbade95e..b9a9432adf2 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/AbstractLensTest.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/AbstractLensTest.java @@ -92,14 +92,14 @@ public abstract class AbstractLensTest extends AbstractInternalModelIntegrationT "user-barbossa-modify-delete-assignment-account-dummy-attr.xml"); protected static final File ROLE_PIRATE_FILE = new File(TEST_DIR, "role-pirate.xml"); - protected static final File ROLE_PIRATE_SITUATION_ONLY_FILE = new File(TEST_DIR, "role-pirate-situation-only.xml"); + protected static final File ROLE_PIRATE_RECORD_ONLY_FILE = new File(TEST_DIR, "role-pirate-record-only.xml"); protected static final String ROLE_PIRATE_OID = "12345678-d34d-b33f-f00d-555555556666"; protected static final File ROLE_MUTINIER_FILE = new File(TEST_DIR, "role-mutinier.xml"); protected static final String ROLE_MUTINIER_OID = "12345678-d34d-b33f-f00d-555555556668"; protected static final File ROLE_JUDGE_FILE = new File(TEST_DIR, "role-judge.xml"); - protected static final File ROLE_JUDGE_SITUATION_ONLY_FILE = new File(TEST_DIR, "role-judge-situation-only.xml"); + protected static final File ROLE_JUDGE_RECORD_ONLY_FILE = new File(TEST_DIR, "role-judge-record-only.xml"); protected static final String ROLE_JUDGE_OID = "12345111-1111-2222-1111-121212111111"; protected static final File ROLE_CONSTABLE_FILE = new File(TEST_DIR, "role-constable.xml"); diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java index 062fddae56b..0a126381e4d 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java @@ -77,8 +77,8 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti super.initSystem(initTask, initResult); setDefaultUserTemplate(USER_TEMPLATE_OID); - addObject(ROLE_PIRATE_SITUATION_ONLY_FILE); - addObject(ROLE_JUDGE_SITUATION_ONLY_FILE); + addObject(ROLE_PIRATE_RECORD_ONLY_FILE); + addObject(ROLE_JUDGE_RECORD_ONLY_FILE); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); diff --git a/model/model-impl/src/test/resources/lens/role-judge-situation-only.xml b/model/model-impl/src/test/resources/lens/role-judge-record-only.xml similarity index 100% rename from model/model-impl/src/test/resources/lens/role-judge-situation-only.xml rename to model/model-impl/src/test/resources/lens/role-judge-record-only.xml diff --git a/model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml b/model/model-impl/src/test/resources/lens/role-pirate-record-only.xml similarity index 100% rename from model/model-impl/src/test/resources/lens/role-pirate-situation-only.xml rename to model/model-impl/src/test/resources/lens/role-pirate-record-only.xml From 5fe57aa2ae88f8d3f1a1ee57eab94362954066ac Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 26 Sep 2017 14:30:56 +0200 Subject: [PATCH 11/19] Support for multi-word full text queries. --- .../repo/sql/QueryInterpreter2Test.java | 34 +++++++++++++++++++ .../restriction/FullTextRestriction.java | 31 ++++++++++++++--- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 48c51d43a51..65a4a6d694e 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -3654,6 +3654,40 @@ public void test940FullTextSimple() throws Exception { } } + @Test + public void test945FullTextMulti() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .fullText("\t\nPeter\t\tMravec\t") + .build(); + + String real = getInterpretedQuery2(session, UserType.class, query); + String expected = "select\n" + + " u.oid,\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.textInfoItems t\n" + + " left join u.textInfoItems t2\n" + + "where\n" + + " (\n" + + " t.text like :text and\n" + + " t2.text like :text2\n" + + " )"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test public void testAdHoc100ProcessStartTimestamp() throws Exception { Session session = open(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java index 304d7c8cc0a..f4773519cbf 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java @@ -25,6 +25,13 @@ import org.apache.commons.lang3.StringUtils; import org.hibernate.criterion.MatchMode; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static java.util.stream.Collectors.toList; + /** * @author mederly */ @@ -37,16 +44,30 @@ public FullTextRestriction(InterpretationContext context, FullTextFilter filter, @Override public Condition interpret() throws QueryException { - String textInfoItemsAlias = getItemPathResolver().addTextInfoJoin(getBaseHqlEntity().getHqlPath()); - String textPath = textInfoItemsAlias + "." + RObjectTextInfo.F_TEXT; - // TODO implement multiple values if (filter.getValues().size() != 1) { throw new QueryException("FullText filter currently supports only a single string"); } String text = filter.getValues().iterator().next(); String normalized = getContext().getPrismContext().getDefaultPolyStringNormalizer().normalize(text); - normalized = StringUtils.normalizeSpace(normalized); - return getContext().getHibernateQuery().createLike(textPath, normalized, MatchMode.ANYWHERE, false); + String[] words = StringUtils.split(normalized); + if (words.length == 0) { + throw new QueryException("No words to query for using full-text search filter"); + } + List conditions = new ArrayList<>(words.length); + for (String word : words) { + conditions.add(createWordQuery(word)); + } + if (conditions.size() == 1) { + return conditions.get(0); + } else { + return getContext().getHibernateQuery().createAnd(conditions); + } } + + private Condition createWordQuery(String word) throws QueryException { + String textInfoItemsAlias = getItemPathResolver().addTextInfoJoin(getBaseHqlEntity().getHqlPath()); + String textPath = textInfoItemsAlias + "." + RObjectTextInfo.F_TEXT; + return getContext().getHibernateQuery().createLike(textPath, word, MatchMode.ANYWHERE, false); + } } From 8044097fd252271beead0229f354eb85e77e4f4a Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 26 Sep 2017 14:30:56 +0200 Subject: [PATCH 12/19] Support for multi-word full text queries. (cherry picked from commit 5fe57aa) --- .../repo/sql/QueryInterpreter2Test.java | 34 +++++++++++++++++++ .../restriction/FullTextRestriction.java | 31 ++++++++++++++--- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 48c51d43a51..65a4a6d694e 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -3654,6 +3654,40 @@ public void test940FullTextSimple() throws Exception { } } + @Test + public void test945FullTextMulti() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .fullText("\t\nPeter\t\tMravec\t") + .build(); + + String real = getInterpretedQuery2(session, UserType.class, query); + String expected = "select\n" + + " u.oid,\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.textInfoItems t\n" + + " left join u.textInfoItems t2\n" + + "where\n" + + " (\n" + + " t.text like :text and\n" + + " t2.text like :text2\n" + + " )"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test public void testAdHoc100ProcessStartTimestamp() throws Exception { Session session = open(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java index 304d7c8cc0a..f4773519cbf 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java @@ -25,6 +25,13 @@ import org.apache.commons.lang3.StringUtils; import org.hibernate.criterion.MatchMode; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static java.util.stream.Collectors.toList; + /** * @author mederly */ @@ -37,16 +44,30 @@ public FullTextRestriction(InterpretationContext context, FullTextFilter filter, @Override public Condition interpret() throws QueryException { - String textInfoItemsAlias = getItemPathResolver().addTextInfoJoin(getBaseHqlEntity().getHqlPath()); - String textPath = textInfoItemsAlias + "." + RObjectTextInfo.F_TEXT; - // TODO implement multiple values if (filter.getValues().size() != 1) { throw new QueryException("FullText filter currently supports only a single string"); } String text = filter.getValues().iterator().next(); String normalized = getContext().getPrismContext().getDefaultPolyStringNormalizer().normalize(text); - normalized = StringUtils.normalizeSpace(normalized); - return getContext().getHibernateQuery().createLike(textPath, normalized, MatchMode.ANYWHERE, false); + String[] words = StringUtils.split(normalized); + if (words.length == 0) { + throw new QueryException("No words to query for using full-text search filter"); + } + List conditions = new ArrayList<>(words.length); + for (String word : words) { + conditions.add(createWordQuery(word)); + } + if (conditions.size() == 1) { + return conditions.get(0); + } else { + return getContext().getHibernateQuery().createAnd(conditions); + } } + + private Condition createWordQuery(String word) throws QueryException { + String textInfoItemsAlias = getItemPathResolver().addTextInfoJoin(getBaseHqlEntity().getHqlPath()); + String textPath = textInfoItemsAlias + "." + RObjectTextInfo.F_TEXT; + return getContext().getHibernateQuery().createLike(textPath, word, MatchMode.ANYWHERE, false); + } } From 3241d5d89cd7bd53778dd7fc5a97fe3d098e44bd Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 26 Sep 2017 14:41:42 +0200 Subject: [PATCH 13/19] Removed exception when doing full-text search for no words. --- .../repo/sql/QueryInterpreter2Test.java | 30 +++++++++++++++++++ .../restriction/FullTextRestriction.java | 7 ++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 65a4a6d694e..6931a4aa462 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -3654,6 +3654,36 @@ public void test940FullTextSimple() throws Exception { } } + // adapt the test after query interpreter is optimized (when searching for empty text) + @Test + public void test941FullTextEmpty() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .fullText("\t\t\t") + .build(); + + String real = getInterpretedQuery2(session, UserType.class, query); + String expected = "select\n" + + " u.oid, u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.textInfoItems t\n" + + "where\n" + + " t.text like :text"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test public void test945FullTextMulti() throws Exception { Session session = open(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java index f4773519cbf..63a1fc0072e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java @@ -51,14 +51,13 @@ public Condition interpret() throws QueryException { String text = filter.getValues().iterator().next(); String normalized = getContext().getPrismContext().getDefaultPolyStringNormalizer().normalize(text); String[] words = StringUtils.split(normalized); - if (words.length == 0) { - throw new QueryException("No words to query for using full-text search filter"); - } List conditions = new ArrayList<>(words.length); for (String word : words) { conditions.add(createWordQuery(word)); } - if (conditions.size() == 1) { + if (conditions.isEmpty()) { + return createWordQuery(""); // original behavior -> match all records (TODO return something like 'empty condition') + } else if (conditions.size() == 1) { return conditions.get(0); } else { return getContext().getHibernateQuery().createAnd(conditions); From eeec5d944e86bbc1b055d41b0e84523f1bcf0d2b Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 26 Sep 2017 14:41:42 +0200 Subject: [PATCH 14/19] Removed exception when doing full-text search for no words. (cherry picked from commit 3241d5d) --- .../repo/sql/QueryInterpreter2Test.java | 30 +++++++++++++++++++ .../restriction/FullTextRestriction.java | 7 ++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 65a4a6d694e..6931a4aa462 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -3654,6 +3654,36 @@ public void test940FullTextSimple() throws Exception { } } + // adapt the test after query interpreter is optimized (when searching for empty text) + @Test + public void test941FullTextEmpty() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .fullText("\t\t\t") + .build(); + + String real = getInterpretedQuery2(session, UserType.class, query); + String expected = "select\n" + + " u.oid, u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.textInfoItems t\n" + + "where\n" + + " t.text like :text"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test public void test945FullTextMulti() throws Exception { Session session = open(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java index f4773519cbf..63a1fc0072e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java @@ -51,14 +51,13 @@ public Condition interpret() throws QueryException { String text = filter.getValues().iterator().next(); String normalized = getContext().getPrismContext().getDefaultPolyStringNormalizer().normalize(text); String[] words = StringUtils.split(normalized); - if (words.length == 0) { - throw new QueryException("No words to query for using full-text search filter"); - } List conditions = new ArrayList<>(words.length); for (String word : words) { conditions.add(createWordQuery(word)); } - if (conditions.size() == 1) { + if (conditions.isEmpty()) { + return createWordQuery(""); // original behavior -> match all records (TODO return something like 'empty condition') + } else if (conditions.size() == 1) { return conditions.get(0); } else { return getContext().getHibernateQuery().createAnd(conditions); From 1dbcc039519f65b18c3755927d6c51fe85bccf8b Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 26 Sep 2017 15:34:39 +0200 Subject: [PATCH 15/19] Fixed storing policy state, including situation triggers. --- .../xml/ns/public/common/common-policy-3.xsd | 60 ++++++++-- .../complex/system-configuration.xml | 4 +- .../context/EvaluatedExclusionTrigger.java | 4 +- .../api/context/EvaluatedPolicyRule.java | 2 +- .../context/EvaluatedSituationTrigger.java | 2 +- .../PolicyRuleExternalizationOptions.java | 14 +-- .../impl/hooks/PolicyRuleEnforcerHook.java | 4 +- .../model/impl/lens/ChangeExecutor.java | 3 +- .../impl/lens/EvaluatedPolicyRuleImpl.java | 33 ++++-- .../projector/policy/PolicyRuleProcessor.java | 6 +- ...eUpdater.java => PolicyStateRecorder.java} | 12 +- .../impl/lens/TestPolicyStateRecording.java | 112 +++++++++--------- .../policy/state/metarole-common-rules.xml | 3 + .../lens/role-pirate-record-only.xml | 2 +- .../test/AbstractModelIntegrationTest.java | 29 +++++ .../primary/policy/ApprovalSchemaBuilder.java | 17 ++- .../midpoint/test/DummyAuditService.java | 5 + 17 files changed, 205 insertions(+), 107 deletions(-) rename model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/{PolicyStateUpdater.java => PolicyStateRecorder.java} (93%) diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd index 25810227239..e90e0ff0231 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-policy-3.xsd @@ -412,10 +412,10 @@ - + - If triggers are to be stored, what level of details should be preserved? + How much information about triggered policy rules should be stored? EXPERIMENTAL @@ -427,7 +427,7 @@ - Triggers will not be stored. + Triggered policy rules will not be stored. @@ -447,7 +447,8 @@ - The triggers for the rule will be stored (including subtriggers). Hidden and final presentation settings are respected. + The triggers and other information for the rule will be stored (including subtriggers). + Hidden and final presentation settings are respected. @@ -457,6 +458,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1389,18 +1425,22 @@ - + - How should be triggers stored? + How much information about triggered policy rules should be stored? EXPERIMENTAL - - 3.7 - true - + + + + + + + + diff --git a/model/certification-impl/src/test/resources/complex/system-configuration.xml b/model/certification-impl/src/test/resources/complex/system-configuration.xml index ac1cbdb3a3d..1292597db67 100644 --- a/model/certification-impl/src/test/resources/complex/system-configuration.xml +++ b/model/certification-impl/src/test/resources/complex/system-configuration.xml @@ -395,7 +395,7 @@ http://sample.org/situations#incomplete-role-c1-to-c4 - full + full @@ -413,7 +413,7 @@ http://sample.org/situations#active-role-with-no-identifier - none + none diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java index 1b364bd9f94..80202a6d0c4 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedExclusionTrigger.java @@ -24,7 +24,7 @@ import java.util.Objects; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType.FULL; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.TriggeredPolicyRulesStorageStrategyType.FULL; /** * @author mederly @@ -82,7 +82,7 @@ protected void debugDumpSpecific(StringBuilder sb, int indent) { public EvaluatedExclusionTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRuleExternalizationOptions options) { EvaluatedExclusionTriggerType rv = new EvaluatedExclusionTriggerType(); fillCommonContent(rv); - if (options.getTriggerStorageStrategy() == FULL) { + if (options.getTriggeredRulesStorageStrategy() == FULL) { rv.setConflictingObjectRef(ObjectTypeUtil.createObjectRef(conflictingTarget)); rv.setConflictingObjectDisplayName(ObjectTypeUtil.getDisplayName(conflictingTarget)); if (conflictingPath != null) { diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java index 8ef51b2759d..183fd74bead 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedPolicyRule.java @@ -66,7 +66,7 @@ default boolean isTriggered() { Collection getPolicyExceptions(); - EvaluatedPolicyRuleType toEvaluatedPolicyRuleType(PolicyRuleExternalizationOptions options); + void addToEvaluatedPolicyRuleTypes(Collection rules, PolicyRuleExternalizationOptions options); boolean isGlobal(); diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java index 063c358ec05..f9f6d78190b 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedSituationTrigger.java @@ -107,7 +107,7 @@ public EvaluatedSituationTriggerType toEvaluatedPolicyRuleTriggerType(PolicyRule EvaluatedSituationTriggerType rv = new EvaluatedSituationTriggerType(); fillCommonContent(rv); if (!options.isRespectFinalFlag() || !isFinal()) { - sourceRules.forEach(r -> rv.getSourceRule().add(r.toEvaluatedPolicyRuleType(options))); + sourceRules.forEach(r -> r.addToEvaluatedPolicyRuleTypes(rv.getSourceRule(), options)); } return rv; } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/PolicyRuleExternalizationOptions.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/PolicyRuleExternalizationOptions.java index 2e8ac2a4f47..91b172afdfb 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/PolicyRuleExternalizationOptions.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/PolicyRuleExternalizationOptions.java @@ -16,19 +16,19 @@ package com.evolveum.midpoint.model.api.context; -import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggeredPolicyRulesStorageStrategyType; import org.jetbrains.annotations.NotNull; import java.io.Serializable; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType.FULL; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.TriggeredPolicyRulesStorageStrategyType.FULL; /** * @author mederly */ public class PolicyRuleExternalizationOptions implements Serializable { - @NotNull private PolicyTriggerStorageStrategyType triggerStorageStrategy; + @NotNull private TriggeredPolicyRulesStorageStrategyType triggeredRulesStorageStrategy; private boolean includeAssignmentsContent; private boolean respectFinalFlag; @@ -36,16 +36,16 @@ public PolicyRuleExternalizationOptions() { this(FULL, false, true); } - public PolicyRuleExternalizationOptions(PolicyTriggerStorageStrategyType triggerStorageStrategy, + public PolicyRuleExternalizationOptions(TriggeredPolicyRulesStorageStrategyType triggeredRulesStorageStrategy, boolean includeAssignmentsContent, boolean respectFinalFlag) { - this.triggerStorageStrategy = triggerStorageStrategy != null ? triggerStorageStrategy : FULL; + this.triggeredRulesStorageStrategy = triggeredRulesStorageStrategy != null ? triggeredRulesStorageStrategy : FULL; this.includeAssignmentsContent = includeAssignmentsContent; this.respectFinalFlag = respectFinalFlag; } @NotNull - public PolicyTriggerStorageStrategyType getTriggerStorageStrategy() { - return triggerStorageStrategy; + public TriggeredPolicyRulesStorageStrategyType getTriggeredRulesStorageStrategy() { + return triggeredRulesStorageStrategy; } public boolean isIncludeAssignmentsContent() { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java index e9f4e234f8f..9e364c29b89 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/hooks/PolicyRuleEnforcerHook.java @@ -40,7 +40,7 @@ import java.util.Collections; import java.util.List; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType.FULL; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.TriggeredPolicyRulesStorageStrategyType.FULL; /** * Hook used to enforce the policy rules that have the enforce action. @@ -138,7 +138,7 @@ private void enforceTriggeredRules(EvaluationContext evalC } // TODO really include assignments content? - evalCtx.rules.add(policyRule.toEvaluatedPolicyRuleType(new PolicyRuleExternalizationOptions(FULL, true, true))); + policyRule.addToEvaluatedPolicyRuleTypes(evalCtx.rules, new PolicyRuleExternalizationOptions(FULL, true, true)); for (EvaluatedPolicyRuleTrigger trigger: triggers) { if (trigger.getMessage() != null) { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java index 4f146c66c70..74c755af85e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java @@ -24,7 +24,7 @@ import com.evolveum.midpoint.common.Clock; import com.evolveum.midpoint.common.SynchronizationUtils; -import com.evolveum.midpoint.model.impl.lens.projector.policy.PolicyStateUpdater; +import com.evolveum.midpoint.model.impl.lens.projector.policy.PolicyStateRecorder; import com.evolveum.midpoint.prism.delta.*; import com.evolveum.midpoint.repo.api.ConflictWatcher; import com.evolveum.midpoint.repo.common.expression.Expression; @@ -116,7 +116,6 @@ public class ChangeExecutor { @Autowired private Clock clock; @Autowired private ModelObjectResolver objectResolver; @Autowired private OperationalDataManager metadataManager; - @Autowired private PolicyStateUpdater policyStateUpdater; @Autowired private CredentialsProcessor credentialsProcessor; private PrismObjectDefinition userDefinition = null; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java index 40308f52e06..5b0f14a1e0d 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedPolicyRuleImpl.java @@ -15,10 +15,6 @@ */ package com.evolveum.midpoint.model.impl.lens; -import java.util.*; -import java.util.Objects; -import java.util.stream.Collectors; - import com.evolveum.midpoint.model.api.context.*; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.util.PrismPrettyPrinter; @@ -31,7 +27,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType.FULL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import static com.evolveum.midpoint.xml.ns._public.common.common_3.TriggeredPolicyRulesStorageStrategyType.FULL; /** * @author semancik @@ -315,10 +317,10 @@ private void createMessageTreeNode(TreeNode root, EvaluatedP */ @Override - public EvaluatedPolicyRuleType toEvaluatedPolicyRuleType(PolicyRuleExternalizationOptions options) { + public void addToEvaluatedPolicyRuleTypes(Collection rules, PolicyRuleExternalizationOptions options) { EvaluatedPolicyRuleType rv = new EvaluatedPolicyRuleType(); rv.setRuleName(getName()); - boolean isFull = options.getTriggerStorageStrategy() == FULL; + boolean isFull = options.getTriggeredRulesStorageStrategy() == FULL; if (isFull && assignmentPath != null) { rv.setAssignmentPath(assignmentPath.toAssignmentPathType(options.isIncludeAssignmentsContent())); } @@ -326,8 +328,19 @@ public EvaluatedPolicyRuleType toEvaluatedPolicyRuleType(PolicyRuleExternalizati rv.setDirectOwnerRef(ObjectTypeUtil.createObjectRef(directOwner)); rv.setDirectOwnerDisplayName(ObjectTypeUtil.getDisplayName(directOwner)); } - triggers.forEach(t -> rv.getTrigger().add(t.toEvaluatedPolicyRuleTriggerType(options))); - return rv; + for (EvaluatedPolicyRuleTrigger trigger : triggers) { + if (trigger instanceof EvaluatedSituationTrigger && trigger.isHidden()) { + for (EvaluatedPolicyRule sourceRule : ((EvaluatedSituationTrigger) trigger).getSourceRules()) { + sourceRule.addToEvaluatedPolicyRuleTypes(rules, options); + } + } else { + rv.getTrigger().add(trigger.toEvaluatedPolicyRuleTriggerType(options)); + } + } + if (rv.getTrigger().isEmpty()) { + // skip empty situation rule + } else { + rules.add(rv); + } } - } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java index 5fb0be2dc03..040d7475c0f 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java @@ -69,7 +69,7 @@ public class PolicyRuleProcessor { @Autowired @Qualifier("cacheRepositoryService") private RepositoryService repositoryService; @Autowired private MappingFactory mappingFactory; @Autowired private MappingEvaluator mappingEvaluator; - @Autowired private PolicyStateUpdater policyStateUpdater; + @Autowired private PolicyStateRecorder policyStateRecorder; @Autowired private AssignmentConstraintEvaluator assignmentConstraintEvaluator; @Autowired private HasAssignmentConstraintEvaluator hasAssignmentConstraintEvaluator; @@ -149,7 +149,7 @@ public void evaluateAssignmentPolicyRules(LensContext c } } } - policyStateUpdater.applyAssignmentState(context, evaluatedAssignment, globalCtx.rulesToRecord); + policyStateRecorder.applyAssignmentState(context, evaluatedAssignment, globalCtx.rulesToRecord); } exclusionConstraintEvaluator.checkExclusionsLegacy(context, evaluatedAssignmentTriple.getPlusSet(), @@ -214,7 +214,7 @@ public void evaluateObjectPolicyRules(LensContext conte for (EvaluatedPolicyRule rule : situationRules) { evaluateFocusRule(rule, context, globalCtx, task, result); } - policyStateUpdater.applyObjectState(context, globalCtx.rulesToRecord); + policyStateRecorder.applyObjectState(context, globalCtx.rulesToRecord); } private Collection getAllGlobalRules(LensContext context) { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java similarity index 93% rename from model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java rename to model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java index 91490dc2f5b..cb6e7ced2f1 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateUpdater.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java @@ -43,9 +43,9 @@ * @author mederly */ @Component -public class PolicyStateUpdater { +public class PolicyStateRecorder { - private static final Trace LOGGER = TraceManager.getTrace(PolicyStateUpdater.class); + private static final Trace LOGGER = TraceManager.getTrace(PolicyStateRecorder.class); @Autowired private PrismContext prismContext; @@ -110,14 +110,16 @@ private ComputationResult compute(@NotNull List rulesToReco for (EvaluatedPolicyRule rule : rulesToRecord) { cr.newPolicySituations.add(rule.getPolicySituation()); RecordPolicyActionType recordAction = rule.getActions().getRecord(); - if (recordAction.getTriggerStorageStrategy() != PolicyTriggerStorageStrategyType.NONE) { - cr.newTriggeredRules.add(rule.toEvaluatedPolicyRuleType(new PolicyRuleExternalizationOptions(recordAction.getTriggerStorageStrategy(), false, true))); + if (recordAction.getPolicyRules() != TriggeredPolicyRulesStorageStrategyType.NONE) { + PolicyRuleExternalizationOptions externalizationOptions = new PolicyRuleExternalizationOptions( + recordAction.getPolicyRules(), false, true); + rule.addToEvaluatedPolicyRuleTypes(cr.newTriggeredRules, externalizationOptions); } } cr.oldPolicySituations.addAll(existingPolicySituation); cr.oldTriggeredRules.addAll(existingTriggeredPolicyRule); cr.situationsNeedUpdate = !Objects.equals(cr.oldPolicySituations, cr.newPolicySituations); - // we do not use this, because it uses hashCode, that is (for some reason) wrongly computed + // we do not use Objects.equal, because it uses hashCode, that is (for some reason) wrongly computed //cr.rulesNeedUpdate = !Objects.equals(cr.oldTriggeredRules, cr.newTriggeredRules); cr.rulesNeedUpdate = !MiscUtil.unorderedCollectionEquals(cr.oldTriggeredRules, cr.newTriggeredRules); return cr; diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java index 0a126381e4d..90bdfd958c5 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java @@ -36,6 +36,8 @@ import java.io.File; import java.util.Collections; +import static com.evolveum.midpoint.model.api.ModelExecuteOptions.createReconcile; +import static com.evolveum.midpoint.prism.delta.ObjectDelta.createEmptyModifyDelta; import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createAssignmentTo; import static org.testng.AssertJUnit.assertEquals; @@ -98,82 +100,79 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); } + @Test public void test100JackAssignRoleJudge() throws Exception { - final String TEST_NAME = "test100JackAssignRoleJudge"; - TestUtil.displayTestTitle(this, TEST_NAME); + TestCtx t = createContext(this, "test100JackAssignRoleJudge"); // GIVEN - Task task = taskManager.createTaskInstance(TestPolicyStateRecording.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); - assignRole(USER_JACK_OID, ROLE_JUDGE_OID, task, result); + t.displayWhen(); + assignRole(USER_JACK_OID, ROLE_JUDGE_OID, t.task, t.result); // THEN - TestUtil.displayThen(TEST_NAME); + t.displayThen(); UserType jack = getUser(USER_JACK_OID).asObjectable(); display("jack", jack); - result.computeStatus(); - TestUtil.assertSuccess(result); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); - assertAssignedRole(USER_JACK_OID, ROLE_JUDGE_OID, task, result); + assertAssignedRole(USER_JACK_OID, ROLE_JUDGE_OID, t.task, t.result); assertEquals("Wrong # of assignments", 1, jack.getAssignment().size()); assertEquals("Wrong policy situations", Collections.emptyList(), jack.getAssignment().get(0).getPolicySituation()); + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(1); } @Test public void test110JackAssignRolePirate() throws Exception { - final String TEST_NAME = "test110JackAssignRolePirate"; - TestUtil.displayTestTitle(this, TEST_NAME); - - // GIVEN - Task task = taskManager.createTaskInstance(TestPolicyStateRecording.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); + TestCtx t = createContext(this, "test110JackAssignRolePirate"); // WHEN - TestUtil.displayWhen(TEST_NAME); - assignRole(USER_JACK_OID, ROLE_PIRATE_OID, task, result); + t.displayWhen(); + assignRole(USER_JACK_OID, ROLE_PIRATE_OID, t.task, t.result); // THEN - TestUtil.displayThen(TEST_NAME); + t.displayThen(); UserType jack = getUser(USER_JACK_OID).asObjectable(); display("jack", jack); - result.computeStatus(); - TestUtil.assertSuccess(result); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); - assertAssignedRole(USER_JACK_OID, ROLE_PIRATE_OID, task, result); + assertAssignedRole(USER_JACK_OID, ROLE_PIRATE_OID, t.task, t.result); assertEquals("Wrong # of assignments", 2, jack.getAssignment().size()); for (AssignmentType assignment : jack.getAssignment()) { assertEquals("Wrong policy situations", Collections.singletonList(SchemaConstants.MODEL_POLICY_SITUATION_EXCLUSION_VIOLATION), assignment.getPolicySituation()); } + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(2); // rules without IDs, with IDs } // should keep the situation for both assignments @Test public void test120RecomputeJack() throws Exception { - final String TEST_NAME = "test120RecomputeJack"; - TestUtil.displayTestTitle(this, TEST_NAME); + TestCtx t = createContext(this, "test120RecomputeJack"); // GIVEN - Task task = taskManager.createTaskInstance(TestPolicyStateRecording.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); - recomputeUser(USER_JACK_OID, task, result); + t.displayWhen(); + executeChanges(createEmptyModifyDelta(UserType.class, USER_JACK_OID, prismContext), createReconcile(), t.task, t.result); + //recomputeUser(USER_JACK_OID, t.task, t.result); // THEN - TestUtil.displayThen(TEST_NAME); + t.displayThen(); UserType jack = getUser(USER_JACK_OID).asObjectable(); display("jack", jack); - result.computeStatus(); - TestUtil.assertSuccess(result); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); // TODO test that assignment IDs are filled in correctly (currently they are not) assertEquals("Wrong # of assignments", 2, jack.getAssignment().size()); @@ -182,35 +181,36 @@ public void test120RecomputeJack() throws Exception { Collections.singletonList(SchemaConstants.MODEL_POLICY_SITUATION_EXCLUSION_VIOLATION), assignment.getPolicySituation()); } + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(1); + dummyAuditService.assertExecutionDeltas(0); } @Test public void test200BobAssign2a3a() throws Exception { - final String TEST_NAME = "test200BobAssign2a3a"; - TestUtil.displayTestTitle(this, TEST_NAME); + TestCtx t = createContext(this, "test200BobAssign2a3a"); // GIVEN - Task task = taskManager.createTaskInstance(TestPolicyStateRecording.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + t.displayWhen(); ObjectDelta delta = DeltaBuilder.deltaFor(UserType.class, prismContext) .item(UserType.F_ASSIGNMENT) .add(createAssignmentTo(roleATest2aOid, ObjectTypes.ROLE, prismContext), createAssignmentTo(roleATest3aOid, ObjectTypes.ROLE, prismContext)) .asObjectDeltaCast(userBobOid); - executeChangesAssertSuccess(delta, null, task, result); + executeChangesAssertSuccess(delta, null, t.task, t.result); // THEN - TestUtil.displayThen(TEST_NAME); + t.displayThen(); UserType bob = getUser(userBobOid).asObjectable(); display("bob", bob); - result.computeStatus(); - TestUtil.assertSuccess(result); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); - assertAssignedRole(userBobOid, roleATest2aOid, task, result); - assertAssignedRole(userBobOid, roleATest3aOid, task, result); + assertAssignedRole(userBobOid, roleATest2aOid, t.task, t.result); + assertAssignedRole(userBobOid, roleATest3aOid, t.task, t.result); assertEquals("Wrong # of assignments", 2, bob.getAssignment().size()); assertEquals("Wrong policy situations for assignment 1", Collections.emptyList(), @@ -218,39 +218,41 @@ public void test200BobAssign2a3a() throws Exception { assertEquals("Wrong policy situations for assignment 2", Collections.emptyList(), bob.getAssignment().get(1).getPolicySituation()); + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(1); // no policy state update } @Test public void test200BobAssign2b3b() throws Exception { - final String TEST_NAME = "test200BobAssign2b3b"; - TestUtil.displayTestTitle(this, TEST_NAME); + TestCtx t = createContext(this, "test200BobAssign2b3b"); // GIVEN - Task task = taskManager.createTaskInstance(TestPolicyStateRecording.class.getName() + "." + TEST_NAME); - OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + t.displayWhen(); ObjectDelta delta = DeltaBuilder.deltaFor(UserType.class, prismContext) .item(UserType.F_ASSIGNMENT) .add(createAssignmentTo(roleATest2bOid, ObjectTypes.ROLE, prismContext), createAssignmentTo(roleATest3bOid, ObjectTypes.ROLE, prismContext)) .asObjectDeltaCast(userBobOid); - executeChangesAssertSuccess(delta, null, task, result); + executeChangesAssertSuccess(delta, null, t.task, t.result); // THEN - TestUtil.displayThen(TEST_NAME); + t.displayThen(); UserType bob = getUser(userBobOid).asObjectable(); display("bob", bob); - result.computeStatus(); - TestUtil.assertSuccess(result); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); - assertAssignedRole(userBobOid, roleATest2aOid, task, result); - assertAssignedRole(userBobOid, roleATest2bOid, task, result); - assertAssignedRole(userBobOid, roleATest3aOid, task, result); - assertAssignedRole(userBobOid, roleATest3bOid, task, result); + assertAssignedRole(userBobOid, roleATest2aOid, t.task, t.result); + assertAssignedRole(userBobOid, roleATest2bOid, t.task, t.result); + assertAssignedRole(userBobOid, roleATest3aOid, t.task, t.result); + assertAssignedRole(userBobOid, roleATest3bOid, t.task, t.result); assertEquals("Wrong # of assignments", 4, bob.getAssignment().size()); + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(2); // rules without IDs, with IDs // TODO policy state } diff --git a/model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml b/model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml index 1bf5c1f09b2..415c3aaa9c8 100644 --- a/model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml +++ b/model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml @@ -23,6 +23,9 @@ + + true + http://midpoint.evolveum.com/xml/ns/public/model/policy/situation#exclusionViolation diff --git a/model/model-impl/src/test/resources/lens/role-pirate-record-only.xml b/model/model-impl/src/test/resources/lens/role-pirate-record-only.xml index b936eeab0e2..46dd5419bf4 100644 --- a/model/model-impl/src/test/resources/lens/role-pirate-record-only.xml +++ b/model/model-impl/src/test/resources/lens/role-pirate-record-only.xml @@ -32,7 +32,7 @@ - messageOnly + messageOnly diff --git a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java index b1d88eeb8ee..772e3fdbc65 100644 --- a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java +++ b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java @@ -4551,4 +4551,33 @@ protected TaskType getRootTask(List> tasks) { return rv.get(0); } } + + // highly experimental + public class TestCtx { + public final String name; + + public final Task task; + public final OperationResult result; + + TestCtx(Object testCase, String name) { + this.name = name; + TestUtil.displayTestTitle(testCase, name); + task = taskManager.createTaskInstance(testCase.getClass().getName() + "." + name); + result = task.getResult(); + dummyAuditService.clear(); + } + + public void displayWhen() { + TestUtil.displayWhen(name); + } + + public void displayThen() { + TestUtil.displayThen(name); + } + } + + protected TestCtx createContext(Object testCase, String testName) { + return new TestCtx(testCase, testName); + } + } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java index 14a86b8f7a6..828fa662bf5 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java @@ -34,7 +34,7 @@ import javax.xml.namespace.QName; import java.util.*; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyTriggerStorageStrategyType.FULL; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.TriggeredPolicyRulesStorageStrategyType.FULL; import static java.util.Comparator.naturalOrder; /** @@ -207,11 +207,16 @@ private void processFragmentGroup(List fragments, ApprovalSchemaType r resultingSchemaType.getStage().add(stageDef); } if (firstFragment.policyRule != null) { - SchemaAttachedPolicyRuleType attachedRule = new SchemaAttachedPolicyRuleType(); - attachedRule.setStageMin(from); - attachedRule.setStageMax(i - 1); - attachedRule.setRule(firstFragment.policyRule.toEvaluatedPolicyRuleType(new PolicyRuleExternalizationOptions(FULL, false, true))); - attachedRules.getEntry().add(attachedRule); + List rules = new ArrayList<>(); + firstFragment.policyRule.addToEvaluatedPolicyRuleTypes(rules, new PolicyRuleExternalizationOptions(FULL, + false, true)); + for (EvaluatedPolicyRuleType rule : rules) { + SchemaAttachedPolicyRuleType attachedRule = new SchemaAttachedPolicyRuleType(); + attachedRule.setStageMin(from); + attachedRule.setStageMax(i - 1); + attachedRule.setRule(rule); + attachedRules.getEntry().add(attachedRule); + } } } diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyAuditService.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyAuditService.java index 9c6cb6326f3..9b4554eedf1 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyAuditService.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyAuditService.java @@ -148,6 +148,11 @@ public void assertRecords(int expectedNumber) { " but was "+records.size(); } + public void assertExecutionRecords(int expectedNumber) { + List executionRecords = getExecutionRecords(); + assertEquals("Wrong # of execution records", expectedNumber, executionRecords.size()); + } + public List getRecordsOfType(AuditEventType type) { List retval = new ArrayList(); for (AuditEventRecord record : records) { From c23e474690dfadb934df2e562a89d5fa7fe0a8af Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 26 Sep 2017 16:28:11 +0200 Subject: [PATCH 16/19] A couple more tests for policy state. --- .../impl/lens/TestPolicyStateRecording.java | 278 ++++++++++++++++-- .../lens/policy/state/a-test-wrong.xml | 25 ++ .../policy/state/metarole-common-rules.xml | 23 ++ .../resources/lens/policy/state/user-eve.xml | 24 ++ 4 files changed, 332 insertions(+), 18 deletions(-) create mode 100644 model/model-impl/src/test/resources/lens/policy/state/a-test-wrong.xml create mode 100644 model/model-impl/src/test/resources/lens/policy/state/user-eve.xml diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java index 90bdfd958c5..d26a66ee4cb 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java @@ -25,9 +25,7 @@ import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.DebugUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentPolicyEnforcementType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +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; @@ -35,6 +33,7 @@ import java.io.File; import java.util.Collections; +import java.util.List; import static com.evolveum.midpoint.model.api.ModelExecuteOptions.createReconcile; import static com.evolveum.midpoint.prism.delta.ObjectDelta.createEmptyModifyDelta; @@ -56,7 +55,10 @@ public class TestPolicyStateRecording extends AbstractLensTest { protected static final File TEST_DIR = new File(AbstractLensTest.TEST_DIR, "policy/state"); private static final File USER_BOB_FILE = new File(TEST_DIR, "user-bob.xml"); + private static final String WRONG_URI = "http://test.org/wrong"; private static String userBobOid; + private static final File USER_EVE_FILE = new File(TEST_DIR, "user-eve.xml"); + private static String userEveOid; private static final File ROLE_A_TEST_2A_FILE = new File(TEST_DIR, "a-test-2a.xml"); private static String roleATest2aOid; private static final File ROLE_A_TEST_2B_FILE = new File(TEST_DIR, "a-test-2b.xml"); @@ -71,6 +73,8 @@ public class TestPolicyStateRecording extends AbstractLensTest { private static String roleATest3xOid; private static final File ROLE_A_TEST_3Y_FILE = new File(TEST_DIR, "a-test-3y.xml"); private static String roleATest3yOid; + private static final File ROLE_A_TEST_WRONG_FILE = new File(TEST_DIR, "a-test-wrong.xml"); + private static String roleATestWrongOid; private static final File METAROLE_COMMON_RULES_FILE = new File(TEST_DIR, "metarole-common-rules.xml"); private static String metaroleCommonRulesOid; @@ -92,15 +96,16 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti roleATest3yOid = addAndRecompute(ROLE_A_TEST_3Y_FILE, initTask, initResult); roleATest3aOid = addAndRecompute(ROLE_A_TEST_3A_FILE, initTask, initResult); roleATest3bOid = addAndRecompute(ROLE_A_TEST_3B_FILE, initTask, initResult); + roleATestWrongOid = addAndRecompute(ROLE_A_TEST_WRONG_FILE, initTask, initResult); userBobOid = addAndRecompute(USER_BOB_FILE, initTask, initResult); + userEveOid = addAndRecompute(USER_EVE_FILE, initTask, initResult); InternalMonitor.reset(); DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); } - @Test public void test100JackAssignRoleJudge() throws Exception { TestCtx t = createContext(this, "test100JackAssignRoleJudge"); @@ -118,7 +123,7 @@ public void test100JackAssignRoleJudge() throws Exception { t.result.computeStatus(); TestUtil.assertSuccess(t.result); - assertAssignedRole(USER_JACK_OID, ROLE_JUDGE_OID, t.task, t.result); + assertAssignedRole(jack.asPrismObject(), ROLE_JUDGE_OID); assertEquals("Wrong # of assignments", 1, jack.getAssignment().size()); assertEquals("Wrong policy situations", Collections.emptyList(), @@ -143,12 +148,10 @@ public void test110JackAssignRolePirate() throws Exception { t.result.computeStatus(); TestUtil.assertSuccess(t.result); - assertAssignedRole(USER_JACK_OID, ROLE_PIRATE_OID, t.task, t.result); + assertAssignedRole(jack.asPrismObject(), ROLE_PIRATE_OID); assertEquals("Wrong # of assignments", 2, jack.getAssignment().size()); for (AssignmentType assignment : jack.getAssignment()) { - assertEquals("Wrong policy situations", - Collections.singletonList(SchemaConstants.MODEL_POLICY_SITUATION_EXCLUSION_VIOLATION), - assignment.getPolicySituation()); + assertExclusionViolationState(assignment); } display("Audit", dummyAuditService); @@ -209,8 +212,8 @@ public void test200BobAssign2a3a() throws Exception { t.result.computeStatus(); TestUtil.assertSuccess(t.result); - assertAssignedRole(userBobOid, roleATest2aOid, t.task, t.result); - assertAssignedRole(userBobOid, roleATest3aOid, t.task, t.result); + assertAssignedRole(bob.asPrismObject(), roleATest2aOid); + assertAssignedRole(bob.asPrismObject(), roleATest3aOid); assertEquals("Wrong # of assignments", 2, bob.getAssignment().size()); assertEquals("Wrong policy situations for assignment 1", Collections.emptyList(), @@ -224,8 +227,8 @@ public void test200BobAssign2a3a() throws Exception { } @Test - public void test200BobAssign2b3b() throws Exception { - TestCtx t = createContext(this, "test200BobAssign2b3b"); + public void test210BobAssign2b3b() throws Exception { + TestCtx t = createContext(this, "test210BobAssign2b3b"); // GIVEN @@ -245,17 +248,256 @@ public void test200BobAssign2b3b() throws Exception { t.result.computeStatus(); TestUtil.assertSuccess(t.result); - assertAssignedRole(userBobOid, roleATest2aOid, t.task, t.result); - assertAssignedRole(userBobOid, roleATest2bOid, t.task, t.result); - assertAssignedRole(userBobOid, roleATest3aOid, t.task, t.result); - assertAssignedRole(userBobOid, roleATest3bOid, t.task, t.result); + assertAssignedRole(bob.asPrismObject(), roleATest2aOid); + assertAssignedRole(bob.asPrismObject(), roleATest2bOid); + assertAssignedRole(bob.asPrismObject(), roleATest3aOid); + assertAssignedRole(bob.asPrismObject(), roleATest3bOid); assertEquals("Wrong # of assignments", 4, bob.getAssignment().size()); display("Audit", dummyAuditService); dummyAuditService.assertExecutionRecords(2); // rules without IDs, with IDs - // TODO policy state + + for (AssignmentType assignment : bob.getAssignment()) { + assertExclusionViolationState(assignment); + } + } + + private void assertExclusionViolationState(AssignmentType assignment) { + assertEquals("Wrong policy situations", + Collections.singletonList(SchemaConstants.MODEL_POLICY_SITUATION_EXCLUSION_VIOLATION), + assignment.getPolicySituation()); + assertEquals("Wrong # of triggered policy rules in assignment " + assignment, 1, assignment.getTriggeredPolicyRule().size()); + List triggers = assignment.getTriggeredPolicyRule().get(0).getTrigger(); + assertEquals("Wrong # of triggers in triggered policy rule in assignment " + assignment, 1, triggers.size()); + assertEquals("Wrong type of trigger in " + assignment, PolicyConstraintKindType.EXCLUSION, triggers.get(0).getConstraintKind()); + } + + // new user, new assignments (no IDs) + @Test + public void test220AliceAssign2a2b() throws Exception { + TestCtx t = createContext(this, "test220AliceAssign2a2b"); + + // GIVEN + UserType alice = prismContext.createObjectable(UserType.class) + .name("alice") + .assignment(createAssignmentTo(roleATest2aOid, ObjectTypes.ROLE, prismContext)) + .assignment(createAssignmentTo(roleATest2bOid, ObjectTypes.ROLE, prismContext)); + + // WHEN + t.displayWhen(); + addObject(alice.asPrismObject(), t.task, t.result); + + // THEN + t.displayThen(); + alice = getUser(alice.getOid()).asObjectable(); + display("alice", alice); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); + + assertAssignedRole(alice.asPrismObject(), roleATest2aOid); + assertAssignedRole(alice.asPrismObject(), roleATest2bOid); + assertEquals("Wrong # of assignments", 2, alice.getAssignment().size()); + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(2); // rules without IDs, with IDs ? + + for (AssignmentType assignment : alice.getAssignment()) { + assertExclusionViolationState(assignment); + } + } + + // new user, new assignments (explicit IDs) + @Test + public void test230ChuckAssign2a2b() throws Exception { + TestCtx t = createContext(this, "test230ChuckAssign2a2b"); + + // GIVEN + AssignmentType assignment2a = createAssignmentTo(roleATest2aOid, ObjectTypes.ROLE, prismContext); + assignment2a.setId(100L); + AssignmentType assignment2b = createAssignmentTo(roleATest2bOid, ObjectTypes.ROLE, prismContext); + assignment2b.setId(101L); + UserType chuck = prismContext.createObjectable(UserType.class) + .name("chuck") + .assignment(assignment2a) + .assignment(assignment2b); + + // WHEN + t.displayWhen(); + addObject(chuck.asPrismObject(), t.task, t.result); + + // THEN + t.displayThen(); + chuck = getUser(chuck.getOid()).asObjectable(); + display("chuck", chuck); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); + + assertAssignedRole(chuck.asPrismObject(), roleATest2aOid); + assertAssignedRole(chuck.asPrismObject(), roleATest2bOid); + assertEquals("Wrong # of assignments", 2, chuck.getAssignment().size()); + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(2); // sourceRef.oid is null on the first iteration (object OID is unknown before actual creation in repo) + + for (AssignmentType assignment : chuck.getAssignment()) { + assertExclusionViolationState(assignment); + } } + // new user, new assignments (explicit IDs, explicit OID) + @Test + public void test240DanAssign2a2b() throws Exception { + TestCtx t = createContext(this, "test240DanAssign2a2b"); + + // GIVEN + AssignmentType assignment2a = createAssignmentTo(roleATest2aOid, ObjectTypes.ROLE, prismContext); + assignment2a.setId(100L); + AssignmentType assignment2b = createAssignmentTo(roleATest2bOid, ObjectTypes.ROLE, prismContext); + assignment2b.setId(101L); + UserType dan = prismContext.createObjectable(UserType.class) + .oid("207752fa-9559-496c-b04d-42b5e9af2779") + .name("dan") + .assignment(assignment2a) + .assignment(assignment2b); + // WHEN + t.displayWhen(); + addObject(dan.asPrismObject(), t.task, t.result); + + // THEN + t.displayThen(); + dan = getUser(dan.getOid()).asObjectable(); + display("dan", dan); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); + + assertAssignedRole(dan.asPrismObject(), roleATest2aOid); + assertAssignedRole(dan.asPrismObject(), roleATest2bOid); + assertEquals("Wrong # of assignments", 2, dan.getAssignment().size()); + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(1); + + for (AssignmentType assignment : dan.getAssignment()) { + assertExclusionViolationState(assignment); + } + } + + // modified user, new assignment (with ID) + @Test + public void test250EveAssign2b() throws Exception { + TestCtx t = createContext(this, "test220AliceAssign2a2b"); + + // WHEN + t.displayWhen(); + AssignmentType assignment2b = createAssignmentTo(roleATest2bOid, ObjectTypes.ROLE, prismContext); + assignment2b.setId(200L); + ObjectDelta delta = DeltaBuilder.deltaFor(UserType.class, prismContext) + .item(UserType.F_ASSIGNMENT) + .add(assignment2b) + .asObjectDeltaCast(userEveOid); + executeChangesAssertSuccess(delta, null, t.task, t.result); + + // THEN + t.displayThen(); + UserType eve = getUser(userEveOid).asObjectable(); + display("alice", eve); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); + + assertAssignedRole(eve.asPrismObject(), roleATest2aOid); + assertAssignedRole(eve.asPrismObject(), roleATest2bOid); + assertEquals("Wrong # of assignments", 2, eve.getAssignment().size()); + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(1); + + for (AssignmentType assignment : eve.getAssignment()) { + assertExclusionViolationState(assignment); + } + } + + @Test + public void test300MakeRoleWrong() throws Exception { + TestCtx t = createContext(this, "test300MakeRoleWrong"); + + // GIVEN + + // WHEN + t.displayWhen(); + ObjectDelta delta = DeltaBuilder.deltaFor(RoleType.class, prismContext) + .item(RoleType.F_DESCRIPTION).replace("wrong") + .asObjectDeltaCast(roleATestWrongOid); + executeChangesAssertSuccess(delta, null, t.task, t.result); + + // THEN + t.displayThen(); + RoleType wrong = getRole(roleATestWrongOid).asObjectable(); + display("role 'wrong'", wrong); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); + + assertEquals("Wrong policy situations for role", Collections.singletonList(WRONG_URI), wrong.getPolicySituation()); + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(1); // no extra policy state update + } + + @Test + public void test310CreateWrongRole() throws Exception { + TestCtx t = createContext(this, "test310CreateWrongRole"); + + // GIVEN + RoleType wrong2 = prismContext.createObjectable(RoleType.class) + .name("wrong-2") + .description("wrong") + .assignment(createAssignmentTo(metaroleCommonRulesOid, ObjectTypes.ROLE, prismContext)); + + // WHEN + t.displayWhen(); + addObject(wrong2.asPrismObject(), t.task, t.result); + + // THEN + t.displayThen(); + wrong2 = getRole(wrong2.getOid()).asObjectable(); + display("role 'wrong-2'", wrong2); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); + + assertEquals("Wrong policy situations for role", Collections.singletonList(WRONG_URI), wrong2.getPolicySituation()); + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(2); // extra policy state update because of OID + } + + @Test + public void test320CreateWrongRoleKnownOid() throws Exception { + TestCtx t = createContext(this, "test320CreateWrongRoleKnownOid"); + + // GIVEN + AssignmentType assignmentCommon = createAssignmentTo(metaroleCommonRulesOid, ObjectTypes.ROLE, prismContext); + assignmentCommon.setId(300L); + RoleType wrong3 = prismContext.createObjectable(RoleType.class) + .name("wrong-3") + .oid("df6c6bdc-f938-4afc-98f3-10d18ceda274") + .description("wrong") + .assignment(assignmentCommon); + + // WHEN + t.displayWhen(); + addObject(wrong3.asPrismObject(), t.task, t.result); + + // THEN + t.displayThen(); + wrong3 = getRole(wrong3.getOid()).asObjectable(); + display("role 'wrong-3'", wrong3); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); + + assertEquals("Wrong policy situations for role", Collections.singletonList(WRONG_URI), wrong3.getPolicySituation()); + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(1); // no extra policy state update + } } diff --git a/model/model-impl/src/test/resources/lens/policy/state/a-test-wrong.xml b/model/model-impl/src/test/resources/lens/policy/state/a-test-wrong.xml new file mode 100644 index 00000000000..dc3231f4df1 --- /dev/null +++ b/model/model-impl/src/test/resources/lens/policy/state/a-test-wrong.xml @@ -0,0 +1,25 @@ + + + + a-test-wrong + + + + \ No newline at end of file diff --git a/model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml b/model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml index 415c3aaa9c8..35f0486a21d 100644 --- a/model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml +++ b/model/model-impl/src/test/resources/lens/policy/state/metarole-common-rules.xml @@ -34,4 +34,27 @@ + + + + + + + The role is in wrong state. + + + + + description + wrong + + + + + http://test.org/wrong + + + + + \ No newline at end of file diff --git a/model/model-impl/src/test/resources/lens/policy/state/user-eve.xml b/model/model-impl/src/test/resources/lens/policy/state/user-eve.xml new file mode 100644 index 00000000000..6f1a8eabc67 --- /dev/null +++ b/model/model-impl/src/test/resources/lens/policy/state/user-eve.xml @@ -0,0 +1,24 @@ + + + + + eve + + + + From 12cd6be3bdb3266f12d9ae8ba91d87bbb1b326ca Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 26 Sep 2017 17:45:15 +0200 Subject: [PATCH 17/19] Added policy state checking to TestPolicyDrivenRoleLifecycle (with a couple of workarounds). --- .../impl/AccCertCaseOperationsHelper.java | 2 + .../TestPolicyDrivenRoleLifecycle.java | 100 ++++++++++-------- 2 files changed, 59 insertions(+), 43 deletions(-) diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertCaseOperationsHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertCaseOperationsHelper.java index edc1e051d5e..e5eec2cb4ea 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertCaseOperationsHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertCaseOperationsHelper.java @@ -171,6 +171,8 @@ List> getDeltasToCreateCases( throw new IllegalStateException("Object class not found for object type " + objectType + " in campaign " + campaignShortName); } + // TODO derive search filter from certification handler (e.g. select only objects having assignments with the proper policySituation) + // It is only an optimization but potentially a very strong one. Workaround: enter query filter manually into scope definition. final SearchFilterType searchFilter = objectBasedScope != null ? objectBasedScope.getSearchFilter() : null; if (searchFilter != null) { ObjectFilter filter = QueryConvertor.parseFilter(searchFilter, objectClass, prismContext); 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 0a73d2140aa..0e32ff9ebe4 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 @@ -48,7 +48,9 @@ import static com.evolveum.midpoint.model.api.ModelExecuteOptions.createPartialProcessing; import static com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP; +import static java.util.Collections.emptyList; import static java.util.Collections.singleton; +import static java.util.Collections.singletonList; import static org.testng.AssertJUnit.assertEquals; /** @@ -68,6 +70,9 @@ public class TestPolicyDrivenRoleLifecycle extends AbstractUninitializedCertific protected static final File ROLE_CORRECT_FILE = new File(TEST_DIR, "role-correct.xml"); protected static final File ROLE_CORRECT_HIGH_RISK_FILE = new File(TEST_DIR, "role-correct-high-risk.xml"); + protected static final String SITUATION_INCOMPLETE_ROLE = "http://sample.org/situations#incomplete-role-c1-to-c4"; + protected static final String SITUATION_ACTIVE_ROLE_WITH_NO_IDENTIFIER = "http://sample.org/situations#active-role-with-no-identifier"; + protected static String roleEmptyOid; protected static String roleHighRiskEmptyOid; protected static String roleCorrectOid; @@ -99,11 +104,11 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); - userJackOid = repoAddObjectFromFile(USER_JACK_FILE, initResult).getOid(); - roleEmptyOid = repoAddObjectFromFile(ROLE_EMPTY_FILE, initResult).getOid(); - roleHighRiskEmptyOid = repoAddObjectFromFile(ROLE_HIGH_RISK_EMPTY_FILE, initResult).getOid(); - roleCorrectOid = repoAddObjectFromFile(ROLE_CORRECT_FILE, initResult).getOid(); - roleCorrectHighRiskOid = repoAddObjectFromFile(ROLE_CORRECT_HIGH_RISK_FILE, initResult).getOid(); + userJackOid = addAndRecompute(USER_JACK_FILE, initTask, initResult); + roleEmptyOid = addAndRecompute(ROLE_EMPTY_FILE, initTask, initResult); + roleHighRiskEmptyOid = addAndRecompute(ROLE_HIGH_RISK_EMPTY_FILE, initTask, initResult); + roleCorrectOid = addAndRecompute(ROLE_CORRECT_FILE, initTask, initResult); + roleCorrectHighRiskOid = addAndRecompute(ROLE_CORRECT_HIGH_RISK_FILE, initTask, initResult); } @NotNull @@ -126,19 +131,25 @@ public void test010AttemptToActivateIncompleteRoleC1345() throws Exception { TestUtil.displayWhen(TEST_NAME); TestUtil.displayThen(TEST_NAME); Holder> contextHolder = new Holder<>(); + activateRoleAssertFailure(roleEmptyOid, contextHolder, result, task); + + PrismObject role = getRole(roleEmptyOid); + display("role after", role); + + dumpRules(contextHolder); + assertEquals("Wrong policy situation", singletonList(SITUATION_INCOMPLETE_ROLE), role.asObjectable().getPolicySituation()); + } + + private void activateRoleAssertFailure(String roleOid, Holder> contextHolder, OperationResult result, Task task) + throws SchemaException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException, + SecurityViolationException, ConfigurationException, ObjectNotFoundException { try { - activateRole(roleEmptyOid, contextHolder, task, result); + activateRole(roleOid, contextHolder, task, result); fail("unexpected success"); } catch (PolicyViolationException e) { System.out.println("Got expected exception:"); e.printStackTrace(System.out); } - - PrismObject role = getRole(roleEmptyOid); - display("role after", role); - // TODO check policy situation - - dumpRules(contextHolder); } @Test @@ -155,19 +166,13 @@ public void test020AttemptToActivateIncompleteRoleC234() throws Exception { TestUtil.displayWhen(TEST_NAME); TestUtil.displayThen(TEST_NAME); Holder> contextHolder = new Holder<>(); - try { - activateRole(roleHighRiskEmptyOid, contextHolder, task, result); - fail("unexpected success"); - } catch (PolicyViolationException e) { - System.out.println("Got expected exception:"); - e.printStackTrace(System.out); - } + activateRoleAssertFailure(roleHighRiskEmptyOid, contextHolder, result, task); PrismObject role = getRole(roleHighRiskEmptyOid); display("role after", role); - // TODO check policy situation dumpRules(contextHolder); + assertEquals("Wrong policy situation", singletonList(SITUATION_INCOMPLETE_ROLE), role.asObjectable().getPolicySituation()); } @Test @@ -184,19 +189,13 @@ public void test030AttemptToActivateCorrectRoleC34() throws Exception { TestUtil.displayWhen(TEST_NAME); TestUtil.displayThen(TEST_NAME); Holder> contextHolder = new Holder<>(); - try { - activateRole(roleCorrectOid, contextHolder, task, result); - fail("unexpected success"); - } catch (PolicyViolationException e) { - System.out.println("Got expected exception:"); - e.printStackTrace(System.out); - } + activateRoleAssertFailure(roleCorrectOid, contextHolder, result, task); PrismObject role = getRole(roleCorrectOid); display("role after", role); - // TODO check policy situation dumpRules(contextHolder); + assertEquals("Wrong policy situation", singletonList(SITUATION_INCOMPLETE_ROLE), role.asObjectable().getPolicySituation()); } private void dumpRules(Holder> contextHolder) { @@ -219,6 +218,9 @@ public void test040AssignOwnerAndApproverToCorrectRole() throws Exception { ModelExecuteOptions noApprovals = createPartialProcessing(new PartialProcessingOptionsType().approvals(SKIP)); assignRole(USER_ADMINISTRATOR_OID, roleCorrectOid, SchemaConstants.ORG_APPROVER, noApprovals, task, result); assignRole(USER_ADMINISTRATOR_OID, roleCorrectOid, SchemaConstants.ORG_OWNER, noApprovals, task, result); + + // recompute the role to set correct policy situation + recomputeFocus(RoleType.class, roleCorrectOid, task, result); } @Test @@ -242,9 +244,10 @@ public void test050ActivateCorrectRole() throws Exception { PrismObject roleAfter = getRole(roleCorrectOid); display("role after", roleAfter); assertEquals("Wrong (changed) lifecycle state", SchemaConstants.LIFECYCLE_DRAFT, roleAfter.asObjectable().getLifecycleState()); - // TODO check policy situation dumpRules(contextHolder); + assertEquals("Wrong policy situation", emptyList(), roleAfter.asObjectable().getPolicySituation()); + assertEquals("Wrong triggered policy rules", emptyList(), roleAfter.asObjectable().getTriggeredPolicyRule()); Collection> options = GetOperationOptions.retrieveItemsNamed(TaskType.F_WORKFLOW_CONTEXT, WfContextType.F_WORK_ITEM); @@ -272,6 +275,9 @@ public void test050ActivateCorrectRole() throws Exception { PrismObject roleAfterApproval = getRole(roleCorrectOid); display("role after approval", roleAfterApproval); assertEquals("Wrong (unchanged) lifecycle state", SchemaConstants.LIFECYCLE_ACTIVE, roleAfterApproval.asObjectable().getLifecycleState()); + + assertEquals("Wrong policy situation", emptyList(), roleAfter.asObjectable().getPolicySituation()); + assertEquals("Wrong triggered policy rules", emptyList(), roleAfter.asObjectable().getTriggeredPolicyRule()); } @Test @@ -291,6 +297,9 @@ public void test060AssignOwnerAndApproverToCorrectHighRiskRole() throws Exceptio assignRole(USER_ADMINISTRATOR_OID, roleCorrectHighRiskOid, SchemaConstants.ORG_APPROVER, noApprovals, task, result); assignRole(userJackOid, roleCorrectHighRiskOid, SchemaConstants.ORG_APPROVER, noApprovals, task, result); assignRole(USER_ADMINISTRATOR_OID, roleCorrectHighRiskOid, SchemaConstants.ORG_OWNER, noApprovals, task, result); + + // recompute the role to set correct policy situation + recomputeFocus(RoleType.class, roleCorrectHighRiskOid, task, result); } @Test @@ -314,10 +323,12 @@ public void test070ActivateCorrectHighRiskRole() throws Exception { PrismObject roleAfter = getRole(roleCorrectHighRiskOid); display("role after", roleAfter); assertEquals("Wrong (changed) lifecycle state", SchemaConstants.LIFECYCLE_DRAFT, roleAfter.asObjectable().getLifecycleState()); - // TODO check policy situation dumpRules(contextHolder); + assertEquals("Wrong policy situation", emptyList(), roleAfter.asObjectable().getPolicySituation()); + assertEquals("Wrong triggered policy rules", emptyList(), roleAfter.asObjectable().getTriggeredPolicyRule()); + Collection> options = GetOperationOptions.retrieveItemsNamed(TaskType.F_WORKFLOW_CONTEXT, WfContextType.F_WORK_ITEM); List> tasks = getTasksForObject(roleCorrectHighRiskOid, RoleType.COMPLEX_TYPE, options, task, result); @@ -325,7 +336,6 @@ public void test070ActivateCorrectHighRiskRole() throws Exception { assertEquals("Wrong # of approval tasks for role", 2, tasks.size()); TaskType approvalTask = getApprovalTask(tasks); - TaskType rootTask = getRootTask(tasks); WfContextType wfc = approvalTask.getWorkflowContext(); assertEquals("Modification of correct-high-risk", wfc.getProcessInstanceName()); assertEquals("wrong # of work items", 1, wfc.getWorkItem().size()); @@ -333,21 +343,25 @@ public void test070ActivateCorrectHighRiskRole() throws Exception { ItemApprovalProcessStateType info = WfContextUtil.getItemApprovalProcessInfo(wfc); assertEquals("wrong # of approval stages", 2, info.getApprovalSchema().getStage().size()); assertEquals("wrong # of attached policy rules", 2, info.getPolicyRules().getEntry().size()); -// EvaluatedPolicyRuleType rule = info.getPolicyRules().getEntry().get(0).getRule(); -// List triggers = rule.getTrigger(); -// -// // TODO check trigger -// -// workflowService.completeWorkItem(workItem.getExternalId(), true, null, null, result); -// waitForTaskFinish(rootTask.getOid(), false); -// -// PrismObject roleAfterApproval = getRole(roleCorrectHighRiskOid); -// display("role after approval", roleAfterApproval); -// assertEquals("Wrong (unchanged) lifecycle state", SchemaConstants.LIFECYCLE_ACTIVE, roleAfterApproval.asObjectable().getLifecycleState()); - } + workflowService.completeWorkItem(workItem.getExternalId(), true, null, null, result); + approvalTask = modelService.getObject(TaskType.class, approvalTask.getOid(), options, task, result).asObjectable(); + wfc = approvalTask.getWorkflowContext(); + assertEquals("wrong # of work items", 1, wfc.getWorkItem().size()); + workItem = wfc.getWorkItem().get(0); + workflowService.completeWorkItem(workItem.getExternalId(), true, null, null, result); + TaskType rootTask = getRootTask(tasks); + waitForTaskFinish(rootTask.getOid(), false); + + PrismObject roleAfterApproval = getRole(roleCorrectHighRiskOid); + display("role after approval", roleAfterApproval); + assertEquals("Wrong (unchanged) lifecycle state", SchemaConstants.LIFECYCLE_ACTIVE, roleAfterApproval.asObjectable().getLifecycleState()); + + assertEquals("Wrong policy situation", singletonList(SITUATION_ACTIVE_ROLE_WITH_NO_IDENTIFIER), roleAfterApproval.asObjectable().getPolicySituation()); + assertEquals("Wrong triggered policy rules", emptyList(), roleAfterApproval.asObjectable().getTriggeredPolicyRule()); // recording rules = none + } private void activateRole(String oid, Holder> contextHolder, Task task, OperationResult result) throws SchemaException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException, From 68c9a53f7a476085fba030b6a087a1f9ef338ce6 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 27 Sep 2017 06:20:42 +0200 Subject: [PATCH 18/19] Fixed setting assignment policy state on assignment deletion. --- .../midpoint/prism/delta/ContainerDelta.java | 27 ++++----------- .../test/TestSoDCertification.java | 1 - .../model/impl/lens/ChangeExecutor.java | 2 +- .../impl/lens/EvaluatedAssignmentImpl.java | 2 +- .../projector/policy/PolicyRuleProcessor.java | 5 ++- .../projector/policy/PolicyStateRecorder.java | 15 ++++++--- .../impl/lens/TestPolicyStateRecording.java | 33 +++++++++++++++++++ 7 files changed, 56 insertions(+), 29 deletions(-) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java index eb092c43e75..e9eb76d18f5 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ContainerDelta.java @@ -186,16 +186,14 @@ private Collection findItemValues(Long id, ItemPath path, Collection void expand(PrismObject object, Trace logger) throws SchemaException { - PrismContainer container = null; - ItemPath path = this.getPath(); - if (object != null) { - container = object.findContainer(path); - } if (valuesToDelete != null) { + ItemPath path = this.getPath(); + PrismContainer container = null; + if (object != null) { + container = object.findContainer(path); + } Iterator> iterator = valuesToDelete.iterator(); while (iterator.hasNext()) { PrismContainerValue deltaCVal = iterator.next(); @@ -210,24 +208,11 @@ public void expand(PrismObject object, Trace logger) t for (Item containerItem: containerCVal.getItems()) { deltaCVal.add(containerItem.clone()); } + continue; } } // id-only value with ID that is not in the object any more: delete the value from delta iterator.remove(); - } else if (deltaCVal.getId() == null) { - if (container != null) { - @SuppressWarnings("unchecked") - List> containerCVals = - (List>) - container.findValuesIgnoreMetadata(deltaCVal); - if (containerCVals.size() > 1) { - logger.warn("More values to be deleted are matched by a single value in delete delta: values={}, delta value={}", - containerCVals, deltaCVal); - } else if (containerCVals.size() == 1) { - deltaCVal.setId(containerCVals.get(0).getId()); - } - // for the time being let's keep non-existent values in the delta - } } } } diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java index b7eb388b72d..f0abb077fc1 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestSoDCertification.java @@ -99,7 +99,6 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); } - // TODO move a test like this into model-intest @Test public void test001Triggers() throws Exception { final String TEST_NAME = "test001Triggers"; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java index 74c755af85e..a2e651d32b8 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java @@ -380,7 +380,7 @@ private ObjectDelta applyPendingAssignmentPolicyStateM .getPendingAssignmentPolicyStateModifications().entrySet()) { PlusMinusZero mode = entry.getKey().mode; if (mode == PlusMinusZero.MINUS) { - continue; // this assignment is being thrown out anyway, so let's ignore it + continue; // this assignment is being thrown out anyway, so let's ignore it (at least for now) } AssignmentType assignmentToFind = entry.getKey().assignment; List> modifications = entry.getValue(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java index 3f6d751d075..c86cea8a7a2 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java @@ -536,7 +536,7 @@ public List getNonNegativeTargets() { */ @NotNull public PlusMinusZero getMode() { - if (assignmentIdi.getItemNew() == null) { + if (assignmentIdi.getItemNew() == null || assignmentIdi.getItemNew().isEmpty()) { return MINUS; } else if (presentInCurrentObject) { return ZERO; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java index 040d7475c0f..8947e15abd3 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleProcessor.java @@ -24,6 +24,7 @@ import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.delta.ContainerDelta; import com.evolveum.midpoint.prism.delta.DeltaSetTriple; +import com.evolveum.midpoint.prism.delta.PlusMinusZero; import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.repo.common.expression.ExpressionUtil; @@ -149,7 +150,9 @@ public void evaluateAssignmentPolicyRules(LensContext c } } } - policyStateRecorder.applyAssignmentState(context, evaluatedAssignment, globalCtx.rulesToRecord); + // a bit of hack, but hopefully it will work + PlusMinusZero mode = inMinus ? PlusMinusZero.MINUS : evaluatedAssignment.getMode(); + policyStateRecorder.applyAssignmentState(context, evaluatedAssignment, mode, globalCtx.rulesToRecord); } exclusionConstraintEvaluator.checkExclusionsLegacy(context, evaluatedAssignmentTriple.getPlusSet(), diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java index cb6e7ced2f1..b9f0fee8833 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java @@ -53,6 +53,9 @@ public void applyObjectState(LensContext context, List< // compute policySituation and triggeredPolicyRules and compare it with the expected state // note that we use the new state for the comparison, because if values match we do not need to do anything LensFocusContext focusContext = context.getFocusContext(); + if (focusContext.isDelete()) { + return; + } F objectNew = focusContext.getObjectNew().asObjectable(); ComputationResult cr = compute(rulesToRecord, objectNew.getPolicySituation(), objectNew.getTriggeredPolicyRule()); if (cr.situationsNeedUpdate) { @@ -72,8 +75,11 @@ public void applyObjectState(LensContext context, List< } public void applyAssignmentState(LensContext context, - EvaluatedAssignmentImpl evaluatedAssignment, List rulesToRecord) throws SchemaException { + EvaluatedAssignmentImpl evaluatedAssignment, PlusMinusZero mode, List rulesToRecord) throws SchemaException { LensFocusContext focusContext = context.getFocusContext(); + if (focusContext.isDelete()) { + return; + } AssignmentType assignmentNew = evaluatedAssignment.getAssignmentType(false); AssignmentType assignmentOld = evaluatedAssignment.getAssignmentType(true); if (assignmentOld == null && assignmentNew == null) { @@ -84,19 +90,20 @@ public void applyAssignmentState(LensContext context, @NotNull AssignmentType assignmentToMatch = assignmentOld != null ? assignmentOld : assignmentNew; // this value is used to compute policy situation/rules modifications @NotNull AssignmentType assignmentToCompute = assignmentNew != null ? assignmentNew : assignmentOld; - @NotNull PlusMinusZero mode = evaluatedAssignment.getMode(); Long id = assignmentToMatch.getId(); ComputationResult cr = compute(rulesToRecord, assignmentToCompute.getPolicySituation(), assignmentToCompute.getTriggeredPolicyRule()); if (cr.situationsNeedUpdate) { - focusContext.addToPendingAssignmentPolicyStateModifications(assignmentToMatch, mode, DeltaBuilder.deltaFor(FocusType.class, prismContext) + focusContext.addToPendingAssignmentPolicyStateModifications(assignmentToMatch, + mode, DeltaBuilder.deltaFor(FocusType.class, prismContext) .item(FocusType.F_ASSIGNMENT, new IdItemPathSegment(id), AssignmentType.F_POLICY_SITUATION) .oldRealValues(cr.oldPolicySituations) .replaceRealValues(cr.newPolicySituations) .asItemDelta()); } if (cr.rulesNeedUpdate) { - focusContext.addToPendingAssignmentPolicyStateModifications(assignmentToMatch, mode, DeltaBuilder.deltaFor(FocusType.class, prismContext) + focusContext.addToPendingAssignmentPolicyStateModifications(assignmentToMatch, + mode, DeltaBuilder.deltaFor(FocusType.class, prismContext) .item(FocusType.F_ASSIGNMENT, new IdItemPathSegment(id), AssignmentType.F_TRIGGERED_POLICY_RULE) .oldRealValues(cr.oldTriggeredRules) .replaceRealValues(cr.newTriggeredRules) diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java index d26a66ee4cb..0b929ac732a 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java @@ -190,6 +190,39 @@ public void test120RecomputeJack() throws Exception { dummyAuditService.assertExecutionDeltas(0); } + @Test + public void test130JackUnassignRolePirate() throws Exception { + TestCtx t = createContext(this, "test130JackUnassignRolePirate"); + + // GIVEN + UserType jack = getUser(USER_JACK_OID).asObjectable(); + AssignmentType pirateAssignment = findAssignmentByTarget(jack.asPrismObject(), ROLE_PIRATE_OID).get(); + + // WHEN + t.displayWhen(); + ObjectDelta delta = DeltaBuilder.deltaFor(UserType.class, prismContext) + .item(UserType.F_ASSIGNMENT) + .delete(pirateAssignment.clone()) + .asObjectDeltaCast(USER_JACK_OID); + executeChangesAssertSuccess(delta, null, t.task, t.result); + + // THEN + t.displayThen(); + jack = getUser(USER_JACK_OID).asObjectable(); + display("jack", jack); + t.result.computeStatus(); + TestUtil.assertSuccess(t.result); + + assertNotAssignedRole(jack.asPrismObject(), ROLE_PIRATE_OID); + assertEquals("Wrong # of assignments", 1, jack.getAssignment().size()); + assertEquals("Wrong policy situations", + Collections.emptyList(), + jack.getAssignment().get(0).getPolicySituation()); + + display("Audit", dummyAuditService); + dummyAuditService.assertExecutionRecords(1); // executed in one shot + } + @Test public void test200BobAssign2a3a() throws Exception { TestCtx t = createContext(this, "test200BobAssign2a3a"); From b17e252932f54d23d86b5bef66403092e5981f78 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 27 Sep 2017 06:33:02 +0200 Subject: [PATCH 19/19] Minor change. --- .../midpoint/model/impl/lens/TestPolicyStateRecording.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java index 0b929ac732a..07ae1dd23e4 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyStateRecording.java @@ -196,7 +196,7 @@ public void test130JackUnassignRolePirate() throws Exception { // GIVEN UserType jack = getUser(USER_JACK_OID).asObjectable(); - AssignmentType pirateAssignment = findAssignmentByTarget(jack.asPrismObject(), ROLE_PIRATE_OID).get(); + AssignmentType pirateAssignment = findAssignmentByTargetRequired(jack.asPrismObject(), ROLE_PIRATE_OID); // WHEN t.displayWhen();