Skip to content

Commit

Permalink
Fix the direct/indirect assignment target rules
Browse files Browse the repository at this point in the history
The distinction between rules assigned directly to current assignment
target and those assigned indirectly to it is now better clarified.
  • Loading branch information
mederly committed Feb 14, 2023
1 parent 05d47a5 commit 8552450
Show file tree
Hide file tree
Showing 19 changed files with 209 additions and 177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ public class OperationResult
public static final String PARAM_PROJECTION = "projection";
public static final String PARAM_LANGUAGE = "language";
public static final String PARAM_POLICY_RULE = "policyRule";
public static final String PARAM_POLICY_RULE_ID = "policyRuleId";

public static final String RETURN_COUNT = "count";
public static final String RETURN_COMMENT = "comment";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,4 @@ default AssignmentPathSegment getAt(int index) {
* Preliminary (limited) implementation. To be used to compare paths pointing to the same target object. Use with care.
*/
boolean equivalent(AssignmentPath other);

/** TODO */
boolean appliesDirectly();
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.io.Serializable;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
import javax.xml.namespace.QName;

import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -82,15 +83,23 @@ default AssignmentType getAssignmentType(boolean old) {
* are compiled from all the applicable sources (target, meta-roles, etc.)
*/
@NotNull
Collection<? extends EvaluatedPolicyRule> getThisTargetPolicyRules();
default Collection<? extends EvaluatedPolicyRule> getThisTargetPolicyRules() {
return getAllTargetsPolicyRules().stream()
.filter(r -> r.getTargetType() == EvaluatedPolicyRule.TargetType.DIRECT_ASSIGNMENT_TARGET)
.collect(Collectors.toList());
}

/**
* Returns all policy rules that apply to some other target object of this assignment
* (and are derived from this assignment) - even those that were not triggered. The policy rules
* are compiled from all the applicable sources (target, meta-roles, etc.)
*/
@NotNull
Collection<? extends EvaluatedPolicyRule> getOtherTargetsPolicyRules();
default Collection<? extends EvaluatedPolicyRule> getOtherTargetsPolicyRules() {
return getAllTargetsPolicyRules().stream()
.filter(r -> r.getTargetType() == EvaluatedPolicyRule.TargetType.INDIRECT_ASSIGNMENT_TARGET)
.collect(Collectors.toList());
}

/**
* Returns all policy rules that apply to any of the target objects provided by this assignment
Expand All @@ -99,16 +108,16 @@ default AssignmentType getAssignmentType(boolean old) {
*
* The difference to getThisTargetPolicyRules is that if e.g.
* jack is a Pirate, and Pirate induces Sailor, then
* - getThisTargetPolicyRules will show rules that are attached to Pirate
* - getAllTargetsPolicyRules will show rules that are attached to Pirate and Sailor
* - getOtherTargetsPolicyRules will show rules that are attached to Sailor
*
* - `getThisTargetPolicyRules` will show rules that are attached to Pirate
* - `getAllTargetsPolicyRules` will show rules that are attached to Pirate and Sailor
* - `getOtherTargetsPolicyRules` will show rules that are attached to Sailor
*/
@NotNull
Collection<? extends EvaluatedPolicyRule> getAllTargetsPolicyRules();

/**
* How many target policy rules are there. This is more efficient than getAllTargetsPolicyRules().size(), as the
* collection of all targets policy rules is computed on demand.
* How many target policy rules are there.
*/
int getAllTargetsPolicyRulesCount();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,6 @@ default boolean isTriggered() {

AssignmentPath getAssignmentPath();

/**
* Object that "directly owns" the rule. TODO. [consider if really needed]
*/
@Nullable
ObjectType getDirectOwner();

// TODO consider removing
String getPolicySituation();

Expand Down Expand Up @@ -125,4 +119,31 @@ default boolean isApplicableToProjection() {
default boolean isApplicableToAssignment() {
return PolicyRuleTypeUtil.isApplicableToAssignment(getPolicyRule());
}

/** To which object is the policy rule targeted and how. */
@NotNull TargetType getTargetType();

/**
* To which object is the policy rule targeted, from the point of assignment mechanisms - and how?
* For example, if it's assigned to the focus, then it's {@link #OBJECT}. If it's assigned directly to the assignment
* target, it's {@link #DIRECT_ASSIGNMENT_TARGET}.
*/
enum TargetType {

/** Focus or projection */
OBJECT,

/** The rule applies directly to the target of the current evaluated assignment (attached to this rule!). */
DIRECT_ASSIGNMENT_TARGET,

/**
* The rule applies to a different target (induced to focus), stemming from the current evaluated assignment
* (attached to this rule).
*
* An example: Let `Engineer` induce `Employee` which conflicts with `Contractor`. An SoD rule is attached
* to `Employee`. But let the user have assignments for `Engineer` and `Contractor` only. So the target type
* for such rule is this one.
*/
INDIRECT_ASSIGNMENT_TARGET
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.util.List;
import javax.xml.namespace.QName;

import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule.TargetType;
import com.evolveum.midpoint.schema.util.*;
import com.evolveum.prism.xml.ns._public.query_3.PagingType;

Expand Down Expand Up @@ -125,7 +126,7 @@ private EvaluatedPolicyRule evaluatePolicyRule(
String ruleId = PolicyRuleTypeUtil.createId(collection.getOid(), assignmentType.getId());

EvaluatedPolicyRuleImpl evaluatedPolicyRule =
new EvaluatedPolicyRuleImpl(policyRuleType.clone(), ruleId, assignmentPath, null);
new EvaluatedPolicyRuleImpl(policyRuleType.clone(), ruleId, assignmentPath, TargetType.OBJECT);

PolicyConstraintsType policyConstraints = policyRuleType.getPolicyConstraints();
if (policyConstraints == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,21 @@ public class EvaluatedPolicyRuleImpl implements EvaluatedPolicyRule {
*
* For global policy rules, assignmentPath is the path to the target object that matched global policy rule.
*
* See also {@link #targetType}.
*
* It can null for artificially-created policy rules e.g. in task validity cases. To be reviewed.
*/
@Nullable private final AssignmentPath assignmentPath;
@Nullable private final ObjectType directOwner;

/**
* Evaluated assignment that brought this policy rule to the focus or target.
* May be missing for artificially-crafted policy rules (to be reviewed!)
*/
private final EvaluatedAssignmentImpl<?> evaluatedAssignment;

/** See {@link EvaluatedPolicyRule#getTargetType()}. */
@NotNull private final TargetType targetType;

/** Tries to uniquely identify the policy rule. Used e.g. for threshold counters. */
@NotNull private final String ruleId;

Expand All @@ -95,12 +99,21 @@ public EvaluatedPolicyRuleImpl(
@NotNull PolicyRuleType policyRuleBean,
@NotNull String ruleId,
@Nullable AssignmentPath assignmentPath,
@Nullable EvaluatedAssignmentImpl<?> evaluatedAssignment) {
@NotNull TargetType targetType) {
this(policyRuleBean, ruleId, assignmentPath, null, targetType);
}

public EvaluatedPolicyRuleImpl(
@NotNull PolicyRuleType policyRuleBean,
@NotNull String ruleId,
@Nullable AssignmentPath assignmentPath,
@Nullable EvaluatedAssignmentImpl<?> evaluatedAssignment,
@NotNull TargetType targetType) {
this.policyRuleBean = policyRuleBean;
this.ruleId = ruleId;
this.assignmentPath = assignmentPath;
this.evaluatedAssignment = evaluatedAssignment;
this.directOwner = computeDirectOwner();
this.targetType = targetType;
}

@SuppressWarnings("MethodDoesntCallSuperMethod")
Expand All @@ -109,15 +122,8 @@ public EvaluatedPolicyRuleImpl clone() {
CloneUtil.clone(policyRuleBean),
ruleId,
CloneUtil.clone(assignmentPath),
evaluatedAssignment);
}

private ObjectType computeDirectOwner() {
if (assignmentPath == null) {
return null;
}
List<ObjectType> roots = assignmentPath.getFirstOrderChain();
return roots.isEmpty() ? null : roots.get(roots.size()-1);
evaluatedAssignment,
targetType);
}

@Override
Expand All @@ -140,12 +146,6 @@ public EvaluatedAssignmentImpl<?> getEvaluatedAssignment() {
return evaluatedAssignment;
}

@Nullable
@Override
public ObjectType getDirectOwner() {
return directOwner;
}

@Override
public PolicyConstraintsType getPolicyConstraints() {
return policyRuleBean.getPolicyConstraints();
Expand Down Expand Up @@ -312,7 +312,6 @@ public String debugDump(int indent) {
sb.append('\n');
debugDumpWithLabelLn(sb, "assignmentPath", assignmentPath, indent + 1);
debugDumpWithLabelLn(sb, "triggers", triggers, indent + 1);
debugDumpWithLabelLn(sb, "directOwner", ObjectTypeUtil.toShortString(directOwner), indent + 1);
debugDumpWithLabel(sb, "rootObjects", assignmentPath != null ? String.valueOf(assignmentPath.getFirstOrderChain()) : null, indent + 1);
return sb.toString();
}
Expand All @@ -327,13 +326,12 @@ public boolean equals(Object o) {
return java.util.Objects.equals(policyRuleBean, that.policyRuleBean) &&
Objects.equals(assignmentPath, that.assignmentPath) &&
Objects.equals(triggers, that.triggers) &&
Objects.equals(policyExceptions, that.policyExceptions) &&
Objects.equals(directOwner, that.directOwner);
Objects.equals(policyExceptions, that.policyExceptions);
}

@Override
public int hashCode() {
return Objects.hash(policyRuleBean, assignmentPath, triggers, policyExceptions, directOwner);
return Objects.hash(policyRuleBean, assignmentPath, triggers, policyExceptions);
}

@Override
Expand Down Expand Up @@ -396,9 +394,12 @@ public void addToEvaluatedPolicyRuleBeans(Collection<EvaluatedPolicyRuleType> ru
if (isFull && assignmentPath != null) {
bean.setAssignmentPath(assignmentPath.toAssignmentPathType(options.isIncludeAssignmentsContent()));
}
if (isFull && directOwner != null) {
bean.setDirectOwnerRef(ObjectTypeUtil.createObjectRef(directOwner));
bean.setDirectOwnerDisplayName(ObjectTypeUtil.getDisplayName(directOwner));
if (isFull) {
ObjectType directOwner = computeDirectOwner();
if (directOwner != null) {
bean.setDirectOwnerRef(ObjectTypeUtil.createObjectRef(directOwner));
bean.setDirectOwnerDisplayName(ObjectTypeUtil.getDisplayName(directOwner));
}
}
for (EvaluatedPolicyRuleTrigger<?> trigger : triggers) {
if (triggerSelector != null && !triggerSelector.test(trigger)) {
Expand All @@ -419,6 +420,14 @@ public void addToEvaluatedPolicyRuleBeans(Collection<EvaluatedPolicyRuleType> ru
}
}

private ObjectType computeDirectOwner() {
if (assignmentPath == null) {
return null;
}
List<ObjectType> roots = assignmentPath.getFirstOrderChain();
return roots.isEmpty() ? null : roots.get(roots.size()-1);
}

@NotNull
public List<PolicyActionType> getEnabledActions() {
return enabledActions;
Expand Down Expand Up @@ -572,6 +581,11 @@ private boolean hasSituationConstraint(PolicyConstraintsType constraints) {
hasSituationConstraint(constraints.getNot()));
}

@Override
public @NotNull EvaluatedPolicyRule.TargetType getTargetType() {
return targetType;
}

@NotNull Collection<String> getTriggeredEventMarks() {
if (isTriggered()) {
return getAllEventMarks();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1227,14 +1227,10 @@ public String dumpAssignmentPolicyRules(int indent, boolean alsoMessages) {
evaluatedAssignmentTriple.debugDumpSets(sb, assignment -> {
DebugUtil.indentDebugDump(sb, indent);
sb.append(assignment.toHumanReadableString());
Collection<EvaluatedPolicyRuleImpl> thisTargetPolicyRules = assignment.getThisTargetPolicyRules();
dumpPolicyRulesCollection("thisTargetPolicyRules", indent + 1, sb, thisTargetPolicyRules, alsoMessages);
@SuppressWarnings({ "raw" })
Collection<EvaluatedPolicyRuleImpl> otherTargetsPolicyRules = assignment.getOtherTargetsPolicyRules();
dumpPolicyRulesCollection("otherTargetsPolicyRules", indent + 1, sb, otherTargetsPolicyRules, alsoMessages);
@SuppressWarnings({ "raw" })
Collection<EvaluatedPolicyRuleImpl> focusPolicyRules = assignment.getFocusPolicyRules();
dumpPolicyRulesCollection("focusPolicyRules", indent + 1, sb, focusPolicyRules, alsoMessages);
dumpPolicyRulesCollection(
"targetPolicyRules", indent + 1, sb, assignment.getAllTargetsPolicyRules(), alsoMessages);
dumpPolicyRulesCollection(
"focusPolicyRules", indent + 1, sb, assignment.getFocusPolicyRules(), alsoMessages);
}, 1);
return sb.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,13 +302,4 @@ public ObjectType getConstructionThisObject() {
return constructionSource.getSource(); // first role (for order=2) a.k.a. index -2 (generally)
}
}

public boolean appliesDirectly() {
assert !isEmpty();
// TODO what about deputy relation which does not increase summaryOrder?
long zeroOrderCount = segments.stream()
.filter(seg -> seg.getEvaluationOrderForTarget().getSummaryOrder() == 0)
.count();
return zeroOrderCount == 1;
}
}

0 comments on commit 8552450

Please sign in to comment.