use of com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule in project midpoint by Evolveum.
the class ObjectPolicyAspectPart method extractObjectBasedInstructions.
<T extends ObjectType> void extractObjectBasedInstructions(@NotNull ObjectTreeDeltas<T> objectTreeDeltas, @Nullable PrismObject<? extends FocusType> requester, @NotNull List<PcpStartInstruction> instructions, @NotNull ModelInvocationContext<T> ctx, @NotNull OperationResult parentResult) throws SchemaException, ObjectNotFoundException {
OperationResult result = parentResult.subresult(OP_EXTRACT_OBJECT_BASED_INSTRUCTIONS).setMinor().build();
ApprovalProcessStartInstructionCreationTraceType trace;
if (result.isTracingNormal(ApprovalProcessStartInstructionCreationTraceType.class)) {
trace = new ApprovalProcessStartInstructionCreationTraceType(prismContext);
result.addTrace(trace);
} else {
trace = null;
}
try {
ObjectDelta<T> focusDelta = objectTreeDeltas.getFocusChange();
LensFocusContext<T> focusContext = (LensFocusContext<T>) ctx.modelContext.getFocusContext();
PrismObject<T> object = focusContext.getObjectOld() != null ? focusContext.getObjectOld() : focusContext.getObjectNew();
List<? extends EvaluatedPolicyRule> triggeredApprovalActionRules = main.selectTriggeredApprovalActionRules(focusContext.getObjectPolicyRules());
LOGGER.trace("extractObjectBasedInstructions: triggeredApprovalActionRules:\n{}", debugDumpLazily(triggeredApprovalActionRules));
List<PcpStartInstruction> newInstructions = new ArrayList<>();
if (!triggeredApprovalActionRules.isEmpty()) {
generateObjectOidIfNeeded(focusDelta, ctx.modelContext);
ProcessSpecifications processSpecifications = ProcessSpecifications.createFromRules(triggeredApprovalActionRules, prismContext);
LOGGER.trace("Process specifications:\n{}", debugDumpLazily(processSpecifications));
for (ProcessSpecification processSpecificationEntry : processSpecifications.getSpecifications()) {
if (focusDelta.isEmpty()) {
// we're done
break;
}
WfProcessSpecificationType processSpecification = processSpecificationEntry.basicSpec;
List<ObjectDelta<T>> deltasToApprove = extractDeltasToApprove(focusDelta, processSpecification);
LOGGER.trace("Deltas to approve:\n{}", debugDumpLazily(deltasToApprove));
if (deltasToApprove.isEmpty()) {
continue;
}
LOGGER.trace("Remaining delta:\n{}", debugDumpLazily(focusDelta));
ApprovalSchemaBuilder builder = new ApprovalSchemaBuilder(main, approvalSchemaHelper);
builder.setProcessSpecification(processSpecificationEntry);
for (Pair<ApprovalPolicyActionType, EvaluatedPolicyRule> actionWithRule : processSpecificationEntry.actionsWithRules) {
ApprovalPolicyActionType approvalAction = actionWithRule.getLeft();
builder.add(main.getSchemaFromAction(approvalAction), approvalAction, object, actionWithRule.getRight());
}
buildSchemaForObject(requester, newInstructions, ctx, result, deltasToApprove, builder);
}
} else if (configurationHelper.getUseDefaultApprovalPolicyRules(ctx.wfConfiguration) != DefaultApprovalPolicyRulesUsageType.NEVER) {
// default rule
ApprovalSchemaBuilder builder = new ApprovalSchemaBuilder(main, approvalSchemaHelper);
if (builder.addPredefined(object, RelationKindType.OWNER, result)) {
LOGGER.trace("Added default approval action, as no explicit one was found");
generateObjectOidIfNeeded(focusDelta, ctx.modelContext);
List<ObjectDelta<T>> deltasToApprove = singletonList(focusDelta.clone());
focusDelta.clear();
buildSchemaForObject(requester, newInstructions, ctx, result, deltasToApprove, builder);
}
}
if (trace != null) {
for (PcpStartInstruction newInstruction : newInstructions) {
trace.getCaseRef().add(ObjectTypeUtil.createObjectRefWithFullObject(newInstruction.getCase(), prismContext));
}
}
instructions.addAll(newInstructions);
result.addReturn("instructionsCreated", newInstructions.size());
} catch (Throwable t) {
result.recordFatalError(t);
throw t;
} finally {
result.computeStatusIfUnknown();
}
}
use of com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule in project midpoint by Evolveum.
the class ProcessSpecifications method createFromRules.
static ProcessSpecifications createFromRules(List<? extends EvaluatedPolicyRule> rules, PrismContext prismContext) throws ObjectNotFoundException {
// Step 1: plain list of approval actions -> map: process-spec -> list of related actions/rules ("collected")
LinkedHashMap<WfProcessSpecificationType, List<Pair<ApprovalPolicyActionType, EvaluatedPolicyRule>>> collectedSpecifications = new LinkedHashMap<>();
for (EvaluatedPolicyRule rule : rules) {
for (ApprovalPolicyActionType approvalAction : rule.getEnabledActions(ApprovalPolicyActionType.class)) {
WfProcessSpecificationType spec = approvalAction.getProcessSpecification();
collectedSpecifications.computeIfAbsent(spec, s -> new ArrayList<>()).add(new ImmutablePair<>(approvalAction, rule));
}
}
// Step 2: resolve references
for (WfProcessSpecificationType spec : new HashSet<>(collectedSpecifications.keySet())) {
// cloned to avoid concurrent modification exception
if (spec != null && spec.getRef() != null) {
List<Map.Entry<WfProcessSpecificationType, List<Pair<ApprovalPolicyActionType, EvaluatedPolicyRule>>>> matching = collectedSpecifications.entrySet().stream().filter(e -> e.getKey() != null && spec.getRef().equals(e.getKey().getName())).collect(Collectors.toList());
if (matching.isEmpty()) {
throw new IllegalStateException("Process specification named '" + spec.getRef() + "' referenced from an approval action couldn't be found");
} else if (matching.size() > 1) {
throw new IllegalStateException("More than one process specification named '" + spec.getRef() + "' referenced from an approval action: " + matching);
} else {
// move all actions/rules to the referenced process specification
List<Pair<ApprovalPolicyActionType, EvaluatedPolicyRule>> referencedSpecActions = matching.get(0).getValue();
referencedSpecActions.addAll(collectedSpecifications.get(spec));
collectedSpecifications.remove(spec);
}
}
}
Map<String, Pair<ApprovalPolicyActionType, EvaluatedPolicyRule>> actionsMap = null;
// Step 3: include other actions
for (Map.Entry<WfProcessSpecificationType, List<Pair<ApprovalPolicyActionType, EvaluatedPolicyRule>>> processSpecificationEntry : collectedSpecifications.entrySet()) {
WfProcessSpecificationType spec = processSpecificationEntry.getKey();
if (spec == null || spec.getIncludeAction().isEmpty() && spec.getIncludeActionIfPresent().isEmpty()) {
continue;
}
if (actionsMap == null) {
actionsMap = createActionsMap(collectedSpecifications.values());
}
for (String actionToInclude : spec.getIncludeAction()) {
processActionToInclude(actionToInclude, actionsMap, processSpecificationEntry, true);
}
for (String actionToInclude : spec.getIncludeActionIfPresent()) {
processActionToInclude(actionToInclude, actionsMap, processSpecificationEntry, false);
}
}
// Step 4: sorts process specifications and wraps into ProcessSpecification objects
ProcessSpecifications rv = new ProcessSpecifications(prismContext);
collectedSpecifications.entrySet().stream().sorted((ps1, ps2) -> {
WfProcessSpecificationType key1 = ps1.getKey();
WfProcessSpecificationType key2 = ps2.getKey();
if (key1 == null) {
// non-empty (key2) records first
return key2 == null ? 0 : 1;
} else if (key2 == null) {
// non-empty (key1) record first
return -1;
}
int order1 = defaultIfNull(key1.getOrder(), Integer.MAX_VALUE);
int order2 = defaultIfNull(key2.getOrder(), Integer.MAX_VALUE);
return Integer.compare(order1, order2);
}).forEach(e -> rv.specifications.add(rv.new ProcessSpecification(e)));
return rv;
}
use of com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule in project midpoint by Evolveum.
the class TestObjectLifecycleAdvanced method test020ActivateIncompleteRole.
@Test
public void test020ActivateIncompleteRole() throws Exception {
login(userAdministrator);
Task task = getTestTask();
OperationResult result = getTestOperationResult();
@SuppressWarnings({ "raw" }) ObjectDelta<RoleType> activateRoleDelta = prismContext.deltaFor(RoleType.class).item(RoleType.F_LIFECYCLE_STATE).replace(SchemaConstants.LIFECYCLE_ACTIVE).asObjectDelta(roleEmployeeOid);
RecordingProgressListener recordingListener = new RecordingProgressListener();
try {
modelService.executeChanges(Collections.singleton(activateRoleDelta), null, task, Collections.singleton(recordingListener), result);
fail("unexpected success");
} catch (PolicyViolationException e) {
System.out.println("Got expected exception: " + e.getMessage());
}
// noinspection unchecked
LensContext<RoleType> context = (LensContext<RoleType>) recordingListener.getModelContext();
System.out.println(context.dumpFocusPolicyRules(0));
EvaluatedPolicyRule incompleteActivationRule = context.getFocusContext().getObjectPolicyRules().stream().filter(rule -> "disallow-incomplete-role-activation".equals(rule.getName())).findFirst().orElseThrow(() -> new AssertionError("rule not found"));
// objectState + or
assertEquals("Wrong # of triggers in incompleteActivationRule", 2, incompleteActivationRule.getTriggers().size());
}
use of com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule in project midpoint by Evolveum.
the class AssignmentPolicyAspectPart method logApprovalActions.
private void logApprovalActions(EvaluatedAssignment<?> assignment, List<EvaluatedPolicyRule> triggeredApprovalActionRules) {
if (LOGGER.isDebugEnabled() && !triggeredApprovalActionRules.isEmpty()) {
LOGGER.trace("-------------------------------------------------------------");
String verb = assignment.isBeingAdded() ? "added" : assignment.isBeingDeleted() ? "deleted" : "modified";
LOGGER.debug("Assignment to be {}: {}: {} this target policy rules, {} triggered approval actions:", verb, assignment, assignment.getThisTargetPolicyRules().size(), triggeredApprovalActionRules.size());
for (EvaluatedPolicyRule t : triggeredApprovalActionRules) {
LOGGER.debug(" - Approval actions: {}", t.getEnabledActions(ApprovalPolicyActionType.class));
for (EvaluatedPolicyRuleTrigger<?> trigger : t.getTriggers()) {
LOGGER.debug(" - {}", trigger);
}
}
}
}
use of com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule in project midpoint by Evolveum.
the class TestPolicyRules2 method test220AddChained.
@Test
public void test220AddChained() throws Exception {
// GIVEN
Task task = getTestTask();
OperationResult result = task.getResult();
LensContext<RoleType> context = createLensContext(RoleType.class);
fillContextWithAddDelta(context, prismContext.parseObject(ROLE_CHAINED_REFERENCES_FILE));
displayDumpable("Input context", context);
assertFocusModificationSanity(context);
// WHEN
when();
clockwork.run(context, task, result);
then();
displayDumpable("Output context", context);
Map<String, EvaluatedPolicyRule> rules = new HashMap<>();
forEvaluatedFocusPolicyRule(context, (r) -> {
displayDumpable("rule", r);
rules.put(r.getName(), r);
});
assertEquals("Wrong # of policy rules", 5, rules.size());
EvaluatedPolicyRule rule1 = rules.get("rule1");
assertNotNull("no rule1", rule1);
PolicyConstraintsType pc1 = rule1.getPolicyConstraints();
assertEquals(1, pc1.getAnd().size());
PolicyConstraintsType pc1inner = pc1.getAnd().get(0);
assertEquals("mod-description-and-riskLevel-and-inducement", pc1inner.getName());
assertEquals("mod-riskLevel-and-inducement", pc1inner.getAnd().get(0).getName());
assertEquals(2, pc1inner.getAnd().get(0).getModification().size());
EvaluatedPolicyRule rule2 = rules.get("rule2");
assertNotNull("no rule2", rule2);
PolicyConstraintsType pc2 = rule2.getPolicyConstraints();
assertEquals("mod-description-and-riskLevel-and-inducement", pc2.getName());
assertEquals("mod-riskLevel-and-inducement", pc2.getAnd().get(0).getName());
assertEquals(2, pc2.getAnd().get(0).getModification().size());
assertEquals("Constraints in rule1, rule2 are different", pc1inner, pc2);
EvaluatedPolicyRule rule3 = rules.get("rule3");
assertNotNull("no rule3", rule3);
PolicyConstraintsType pc3 = rule3.getPolicyConstraints();
assertEquals("mod-riskLevel-and-inducement", pc3.getName());
assertEquals(2, pc3.getModification().size());
assertEquals("Constraints in rule2 and rule3 are different", pc2.getAnd().get(0), pc3);
EvaluatedPolicyRule rule4 = rules.get("rule4");
assertNotNull("no rule4", rule4);
PolicyConstraintsType pc4 = rule4.getPolicyConstraints();
assertEquals(1, pc4.getModification().size());
assertEquals("mod-inducement", pc4.getModification().get(0).getName());
assertSerializable(context);
}
Aggregations