Skip to content

Commit

Permalink
Improvements for policy constraints and actions presentation.
Browse files Browse the repository at this point in the history
Option to explicitly set approval names (processes, work items, tasks).
Option to set approval names to default value using #default# key.
Added objectDisplayInformation, targetDisplayInformation variables for constraint/action presentation.
Minor GUI code fixes.
New midpoint.translate scripting function.
Resolving LocalizableMessageTemplateType to LocalizableMessageType in ModelInteractionService.
  • Loading branch information
mederly committed Oct 31, 2017
1 parent 51e453c commit a5dd72f
Show file tree
Hide file tree
Showing 35 changed files with 357 additions and 173 deletions.
Expand Up @@ -2006,7 +2006,7 @@ protected void setTimeZone(PageBase page) {
MidPointPrincipal principal = SecurityUtils.getPrincipalUser();
if (user != null && user.asObjectable().getTimezone() != null) {
timeZone = user.asObjectable().getTimezone();
} else {
} else if (principal != null && principal.getAdminGuiConfiguration() != null) {
timeZone = principal.getAdminGuiConfiguration().getDefaultTimezone();
}
if (timeZone != null) {
Expand Down
Expand Up @@ -183,18 +183,27 @@ private void initLayout() {
mainForm.add(new ScenePanel(ID_SECONDARY_DELTAS_SCENE, secondaryDeltasModel));

WebMarkupContainer policyViolationsContainer = new WebMarkupContainer(ID_POLICY_VIOLATIONS_CONTAINER);
policyViolationsContainer.add(new VisibleBehaviour(() -> !policyViolationsModel.getObject().isEmpty()));
policyViolationsContainer.add(new VisibleBehaviour(() -> !violationsEmpty()));
policyViolationsContainer.add(new EvaluatedTriggerGroupListPanel(ID_POLICY_VIOLATIONS, policyViolationsModel));
mainForm.add(policyViolationsContainer);

WebMarkupContainer approvalsContainer = new WebMarkupContainer(ID_APPROVALS_CONTAINER);
approvalsContainer.add(new VisibleBehaviour(() -> policyViolationsModel.getObject().isEmpty() && !approvalsModel.getObject().isEmpty()));
approvalsContainer.add(new VisibleBehaviour(() -> violationsEmpty() && !approvalsEmpty()));
approvalsContainer.add(new ApprovalProcessesPreviewPanel(ID_APPROVALS, approvalsModel));
mainForm.add(approvalsContainer);

initButtons(mainForm);
}

private boolean approvalsEmpty() {
return approvalsModel.getObject().isEmpty();
}

private boolean violationsEmpty() {
return policyViolationsModel.getObject().stream()
.allMatch(g -> g.getTriggers().isEmpty());
}

private void initButtons(Form mainForm) {
AjaxButton cancel = new AjaxButton(ID_CONTINUE_EDITING, createStringResource("PagePreviewChanges.button.continueEditing")) {
@Override
Expand Down
Expand Up @@ -95,13 +95,13 @@ private void init(SystemConfigurationType config) {
aepLevel = AEPlevel.fromAEPLevelType(globalAEP);
}

CleanupPolicyType auditCleanup = config.getCleanupPolicy().getAuditRecords();
CleanupPolicyType taskCleanup = config.getCleanupPolicy().getClosedTasks();
CleanupPolicyType auditCleanup = config.getCleanupPolicy() != null ? config.getCleanupPolicy().getAuditRecords() : null;
CleanupPolicyType taskCleanup = config.getCleanupPolicy() != null ? config.getCleanupPolicy().getClosedTasks() : null;

deploymentInformation = config.getDeploymentInformation();

auditCleanupValue = auditCleanup.getMaxAge().toString();
taskCleanupValue = taskCleanup.getMaxAge().toString();
auditCleanupValue = auditCleanup != null && auditCleanup.getMaxAge() != null ? auditCleanup.getMaxAge().toString() : null;
taskCleanupValue = taskCleanup != null && taskCleanup.getMaxAge() != null ? taskCleanup.getMaxAge().toString() : null;

passPolicyDto = loadPasswordPolicy(config);
securityPolicyDto = loadSecurityPolicy(config);
Expand Down Expand Up @@ -187,8 +187,8 @@ public SystemConfigurationType getNewObject() throws DatatypeConfigurationExcept
projectionPolicy.setAssignmentPolicyEnforcement(globalAEP);
newObject.setGlobalAccountSynchronizationSettings(projectionPolicy);
}
Duration auditCleanupDuration = DatatypeFactory.newInstance().newDuration(getAuditCleanupValue());
Duration cleanupTaskDuration = DatatypeFactory.newInstance().newDuration(getTaskCleanupValue());
Duration auditCleanupDuration = getAuditCleanupValue() != null ? DatatypeFactory.newInstance().newDuration(getAuditCleanupValue()) : null;
Duration cleanupTaskDuration = getTaskCleanupValue() != null ? DatatypeFactory.newInstance().newDuration(getTaskCleanupValue()) : null;
CleanupPolicyType auditCleanup = new CleanupPolicyType();
CleanupPolicyType taskCleanup = new CleanupPolicyType();
auditCleanup.setMaxAge(auditCleanupDuration);
Expand Down
Expand Up @@ -15,9 +15,7 @@
*/
package com.evolveum.midpoint.web.page.self;

import com.evolveum.midpoint.gui.api.component.ObjectBrowserPanel;
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.model.api.ModelInteractionService;
import com.evolveum.midpoint.model.api.RoleSelectionSpecification;
import com.evolveum.midpoint.prism.PrismObject;
Expand All @@ -40,7 +38,6 @@
import com.evolveum.midpoint.web.component.search.Search;
import com.evolveum.midpoint.web.component.search.SearchFactory;
import com.evolveum.midpoint.web.component.search.SearchPanel;
import com.evolveum.midpoint.web.component.util.ListDataProvider;
import com.evolveum.midpoint.web.component.util.SelectableBean;
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import com.evolveum.midpoint.web.page.admin.orgs.OrgTreePanel;
Expand All @@ -67,9 +64,7 @@
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;

import javax.xml.namespace.QName;
import java.util.*;

/**
Expand Down
Expand Up @@ -446,43 +446,41 @@ private List<ConflictDto> getAssignmentConflicts(){
.previewChanges(WebComponentUtil.createDeltaCollection(delta), recomputeOptions, task, result);
DeltaSetTriple<? extends EvaluatedAssignment> evaluatedAssignmentTriple = modelContext
.getEvaluatedAssignmentTriple();
Collection<? extends EvaluatedAssignment> addedAssignments = evaluatedAssignmentTriple
.getPlusSet();
if (addedAssignments != null) {
for (EvaluatedAssignment<UserType> evaluatedAssignment : addedAssignments) {
for (EvaluatedPolicyRule policyRule : evaluatedAssignment.getAllTargetsPolicyRules()) {
for (EvaluatedPolicyRuleTrigger<?> trigger : policyRule.getAllTriggers()) {
if (trigger instanceof EvaluatedExclusionTrigger) {
EvaluatedExclusionTrigger exclusionTrigger = (EvaluatedExclusionTrigger) trigger;
EvaluatedAssignment<F> conflictingAssignment = exclusionTrigger.getConflictingAssignment();
PrismObject<F> addedAssignmentTargetObj = (PrismObject<F>)evaluatedAssignment.getTarget();
PrismObject<F> exclusionTargetObj = (PrismObject<F>)conflictingAssignment.getTarget();

AssignmentConflictDto<F> dto1 = new AssignmentConflictDto<>(exclusionTargetObj,
conflictingAssignment.getAssignmentType(true) != null);
AssignmentConflictDto<F> dto2 = new AssignmentConflictDto<>(addedAssignmentTargetObj,
evaluatedAssignment.getAssignmentType(true) != null);
// everything other than 'enforce' is a warning
boolean isWarning = policyRule.containsEnabledAction()
&& !policyRule.containsEnabledAction(EnforcementPolicyActionType.class);
ConflictDto conflict = new ConflictDto(dto1, dto2, isWarning);
String oid1 = exclusionTargetObj.getOid();
String oid2 = addedAssignmentTargetObj.getOid();
if (!conflictsMap.containsKey(oid1 + oid2) && !conflictsMap.containsKey(oid2 + oid1)) {
conflictsMap.put(oid1 + oid2, conflict);
} else if (!isWarning) {
// error is stronger than warning, so we replace (potential) warnings with this error
// TODO Kate please review this
if (conflictsMap.containsKey(oid1 + oid2)) {
conflictsMap.replace(oid1 + oid2, conflict);
}
if (conflictsMap.containsKey(oid2 + oid1)) {
conflictsMap.replace(oid2 + oid1, conflict);
}
Collection<? extends EvaluatedAssignment> addedAssignments = evaluatedAssignmentTriple.getPlusSet();
for (EvaluatedAssignment<UserType> evaluatedAssignment : addedAssignments) {
for (EvaluatedPolicyRule policyRule : evaluatedAssignment.getAllTargetsPolicyRules()) {
if (!policyRule.containsEnabledAction()) {
continue;
}
// everything other than 'enforce' is a warning
boolean isWarning = !policyRule.containsEnabledAction(EnforcementPolicyActionType.class);
for (EvaluatedPolicyRuleTrigger<?> trigger : policyRule.getAllTriggers()) {
if (trigger instanceof EvaluatedExclusionTrigger) {
EvaluatedExclusionTrigger exclusionTrigger = (EvaluatedExclusionTrigger) trigger;
EvaluatedAssignment<F> conflictingAssignment = exclusionTrigger.getConflictingAssignment();
PrismObject<F> addedAssignmentTargetObj = (PrismObject<F>)evaluatedAssignment.getTarget();
PrismObject<F> exclusionTargetObj = (PrismObject<F>)conflictingAssignment.getTarget();

AssignmentConflictDto<F> dto1 = new AssignmentConflictDto<>(exclusionTargetObj,
conflictingAssignment.getAssignmentType(true) != null);
AssignmentConflictDto<F> dto2 = new AssignmentConflictDto<>(addedAssignmentTargetObj,
evaluatedAssignment.getAssignmentType(true) != null);
ConflictDto conflict = new ConflictDto(dto1, dto2, isWarning);
String oid1 = exclusionTargetObj.getOid();
String oid2 = addedAssignmentTargetObj.getOid();
if (!conflictsMap.containsKey(oid1 + oid2) && !conflictsMap.containsKey(oid2 + oid1)) {
conflictsMap.put(oid1 + oid2, conflict);
} else if (!isWarning) {
// error is stronger than warning, so we replace (potential) warnings with this error
// TODO Kate please review this
if (conflictsMap.containsKey(oid1 + oid2)) {
conflictsMap.replace(oid1 + oid2, conflict);
}
if (conflictsMap.containsKey(oid2 + oid1)) {
conflictsMap.replace(oid2 + oid1, conflict);
}
}
}

}
}
}
Expand Down
Expand Up @@ -107,4 +107,7 @@ public class ExpressionConstants {
public static final QName VAR_TASK = new QName(SchemaConstants.NS_C, "task");
public static final QName VAR_RULE_EVALUATION_CONTEXT = new QName(SchemaConstants.NS_C, "ruleEvaluationContext");
public static final QName VAR_STAGE_DEFINITION = new QName(SchemaConstants.NS_C, "stageDefinition");

public static final QName VAR_OBJECT_DISPLAY_INFORMATION = new QName(SchemaConstants.NS_C, "objectDisplayInformation");
public static final QName VAR_TARGET_DISPLAY_INFORMATION = new QName(SchemaConstants.NS_C, "targetDisplayInformation");
}
Expand Up @@ -118,4 +118,8 @@ private static List<Object> convertLocalizableMessageArguments(List<LocalizableM
}
return rv;
}

public static boolean isEmpty(LocalizableMessage message) {
return message == null || message.getKey() == null && message.getFallbackLocalizableMessage() == null && message.getFallbackMessage() == null;
}
}
Expand Up @@ -748,11 +748,11 @@ public static void mergeExtension(PrismContainerValue<?> dstExtensionContainerVa
}
}

public static LocalizableMessage createTechnicalObjectSpecification(PrismObject<?> object, boolean startsWithUppercase) {
public static LocalizableMessage createTechnicalDisplayInformation(PrismObject<?> object, boolean startsWithUppercase) {
if (object != null) {
return new LocalizableMessageBuilder()
.key(SchemaConstants.TECHNICAL_OBJECT_SPECIFICATION_KEY)
.arg(createObjectTypeSpecification(object.asObjectable().getClass().getSimpleName(), startsWithUppercase))
.arg(createTypeDisplayInformation(object.asObjectable().getClass().getSimpleName(), startsWithUppercase))
.arg(object.asObjectable().getName())
.arg(object.getOid())
.build();
Expand All @@ -761,23 +761,23 @@ public static LocalizableMessage createTechnicalObjectSpecification(PrismObject<
}
}

public static LocalizableMessage createObjectSpecification(PrismObject<?> object, boolean startsWithUppercase) {
public static LocalizableMessage createDisplayInformation(PrismObject<?> object, boolean startsWithUppercase) {
if (object != null) {
return new LocalizableMessageBuilder()
.key(SchemaConstants.OBJECT_SPECIFICATION_KEY)
.arg(createObjectTypeSpecification(object.asObjectable().getClass().getSimpleName(), startsWithUppercase))
.arg(createTypeDisplayInformation(object.asObjectable().getClass().getSimpleName(), startsWithUppercase))
.arg(object.asObjectable().getName())
.build();
} else {
return LocalizableMessageBuilder.buildFallbackMessage("?"); // should not really occur!
}
}

public static LocalizableMessage createObjectSpecificationWithPath(PrismObject<?> object, boolean startsWithUppercase, String path) {
public static LocalizableMessage createDisplayInformationWithPath(PrismObject<?> object, boolean startsWithUppercase, String path) {
if (object != null) {
return new LocalizableMessageBuilder()
.key(SchemaConstants.OBJECT_SPECIFICATION_WITH_PATH_KEY)
.arg(createObjectTypeSpecification(object.asObjectable().getClass().getSimpleName(), startsWithUppercase))
.arg(createTypeDisplayInformation(object.asObjectable().getClass().getSimpleName(), startsWithUppercase))
.arg(object.asObjectable().getName())
.arg(path)
.build();
Expand All @@ -786,11 +786,11 @@ public static LocalizableMessage createObjectSpecificationWithPath(PrismObject<?
}
}

public static LocalizableMessage createObjectTypeSpecification(QName type, boolean startsWithUppercase) {
return createObjectTypeSpecification(type != null ? type.getLocalPart() : null, startsWithUppercase);
public static LocalizableMessage createTypeDisplayInformation(QName type, boolean startsWithUppercase) {
return createTypeDisplayInformation(type != null ? type.getLocalPart() : null, startsWithUppercase);
}

public static LocalizableMessage createObjectTypeSpecification(String objectClassName, boolean startsWithUppercase) {
public static LocalizableMessage createTypeDisplayInformation(String objectClassName, boolean startsWithUppercase) {
String prefix = startsWithUppercase ? SchemaConstants.OBJECT_TYPE_KEY_PREFIX : SchemaConstants.OBJECT_TYPE_LOWERCASE_KEY_PREFIX;
return new LocalizableMessageBuilder()
.key(prefix + objectClassName)
Expand Down
Expand Up @@ -1183,6 +1183,13 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="approvalDisplayName" type="tns:LocalizableMessageTemplateType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
If not specified, the name is derived from triggered constraints (short messages).
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:choice>
<xsd:sequence>
<xsd:element name="approverRelation" type="xsd:QName" minOccurs="0" maxOccurs="unbounded">
Expand Down Expand Up @@ -1421,6 +1428,14 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="approvalDisplayName" type="tns:LocalizableMessageTemplateType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Name for approval process. If not specified, name from approval action(s) is taken.
If not specified even there, the name is derived from triggered constraints (short messages).
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:choice>
</xsd:sequence>
Expand Down
Expand Up @@ -19,6 +19,7 @@
import com.evolveum.midpoint.model.api.context.ModelContext;
import com.evolveum.midpoint.model.api.util.MergeDeltas;
import com.evolveum.midpoint.model.api.visualizer.Scene;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
Expand All @@ -40,6 +41,7 @@
import javax.xml.namespace.QName;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
* A service provided by the IDM Model that allows to improve the (user) interaction with the model.
Expand Down Expand Up @@ -317,4 +319,11 @@ MidPointPrincipal assumePowerOfAttorney(PrismObject<UserType> donor, Task task,

MidPointPrincipal dropPowerOfAttorney(Task task, OperationResult result)
throws SchemaException, SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException;

// Maybe a bit of hack: used to deduplicate processing of localizable message templates
@NotNull
LocalizableMessageType createLocalizableMessageType(LocalizableMessageTemplateType template,
Map<QName, Object> variables, Task task, OperationResult result)
throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException,
ConfigurationException, SecurityViolationException;
}
Expand Up @@ -23,6 +23,7 @@
import javax.xml.namespace.QName;

import com.evolveum.midpoint.prism.Item;
import com.evolveum.midpoint.util.LocalizableMessage;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -1086,4 +1087,8 @@ TaskType submitTaskFromTemplate(String templateTaskOid, List<Item<?, ?>> extensi
TaskType submitTaskFromTemplate(String templateTaskOid, Map<QName, Object> extensionValues)
throws CommunicationException, ObjectNotFoundException, SchemaException, SecurityViolationException,
ConfigurationException, ExpressionEvaluationException, ObjectAlreadyExistsException, PolicyViolationException;

String translate(LocalizableMessage message);

String translate(LocalizableMessageType message);
}

0 comments on commit a5dd72f

Please sign in to comment.