Skip to content

Commit

Permalink
Make role expansion configurable in case preview
Browse files Browse the repository at this point in the history
This resolves MID-4105.
  • Loading branch information
mederly committed Mar 24, 2021
1 parent 079d043 commit 868eca6
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 7 deletions.
Expand Up @@ -19970,6 +19970,19 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="approvals" type="tns:AdminGuiApprovalsConfigurationType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
<p>
Configuration related to approvals GUI.
</p>
</xsd:documentation>
<xsd:appinfo>
<a:since>4.3</a:since>
<a:displayName>AdminGuiConfigurationType.approvals</a:displayName>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="displayFormats" type="tns:AdminGuiConfigurationDisplayFormatsType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Expand Down Expand Up @@ -20015,6 +20028,36 @@
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="AdminGuiApprovalsConfigurationType">
<xsd:annotation>
<xsd:documentation>
Configuration related to approvals GUI.
</xsd:documentation>
<xsd:appinfo>
<a:container/>
<a:since>4.3</a:since>
<a:experimental>true</a:experimental>
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="expandRolesOnPreview" type="xsd:boolean" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
<p>
Whether to expand (resolve) abstract role members on approval case preview.
Default is false.
</p>
</xsd:documentation>
<xsd:appinfo>
<a:since>4.3</a:since>
<a:displayName>AdminGuiApprovalsConfigurationType.expandRolesOnPreview</a:displayName>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="adminGuiApprovalsConfiguration" type="tns:AdminGuiApprovalsConfigurationType" />

<xsd:complexType name="AdminGuiConfigurationDisplayFormatsType">
<xsd:annotation>
<xsd:documentation>
Expand Down
Expand Up @@ -55,6 +55,7 @@ public class CompiledGuiProfile implements DebugDumpable, Serializable {
private GuiObjectDetailsSetType objectDetails;
private FeedbackMessagesHookType feedbackMessagesHook;
private AdminGuiConfigurationRoleManagementType roleManagement;
private AdminGuiApprovalsConfigurationType approvals;
private List<UserInterfaceFeatureType> features = new ArrayList<>();
private AdminGuiConfigurationDisplayFormatsType displayFormats;
private byte[] jpegPhoto;
Expand Down Expand Up @@ -284,6 +285,18 @@ public void setRoleManagement(AdminGuiConfigurationRoleManagementType roleManage
this.roleManagement = roleManagement;
}

public AdminGuiApprovalsConfigurationType getApprovals() {
return approvals;
}

public void setApprovals(AdminGuiApprovalsConfigurationType approvals) {
this.approvals = approvals;
}

public boolean isExpandRolesOnApprovalPreview() {
return approvals != null && Boolean.TRUE.equals(approvals.isExpandRolesOnPreview());
}

public List<UserInterfaceFeatureType> getFeatures() {
return features;
}
Expand Down Expand Up @@ -381,6 +394,7 @@ public String debugDump(int indent) {
DebugUtil.debugDumpWithLabelToStringLn(sb, "objectDetails", objectDetails, indent + 1);
DebugUtil.debugDumpWithLabelToStringLn(sb, "feedbackMessagesHook", feedbackMessagesHook, indent + 1);
DebugUtil.debugDumpWithLabelToStringLn(sb, "roleManagement", roleManagement, indent + 1);
DebugUtil.debugDumpWithLabelToStringLn(sb, "approvals", approvals, indent + 1);
DebugUtil.debugDumpWithLabel(sb, "features", features, indent + 1);
return sb.toString();
}
Expand Down
Expand Up @@ -253,12 +253,28 @@ private void applyAdminGuiConfiguration(CompiledGuiProfile composite, AdminGuiCo
composite.getRoleManagement().setAssignmentApprovalRequestLimit(newValue);
} else {
if (composite.getRoleManagement() == null) {
composite.setRoleManagement(new AdminGuiConfigurationRoleManagementType());
composite.setRoleManagement(new AdminGuiConfigurationRoleManagementType(prismContext));
}
composite.getRoleManagement().setAssignmentApprovalRequestLimit(
adminGuiConfiguration.getRoleManagement().getAssignmentApprovalRequestLimit());
}
}

if (adminGuiConfiguration.getApprovals() != null &&
adminGuiConfiguration.getApprovals().isExpandRolesOnPreview() != null) {
if (composite.getApprovals() != null && composite.getApprovals().isExpandRolesOnPreview() != null) {
// the most permissive value wins (so it is possible to give an exception to selected users)
boolean newValue = adminGuiConfiguration.getApprovals().isExpandRolesOnPreview() ||
composite.getApprovals().isExpandRolesOnPreview();
composite.getApprovals().setExpandRolesOnPreview(newValue);
} else {
if (composite.getApprovals() == null) {
composite.setApprovals(new AdminGuiApprovalsConfigurationType(prismContext));
}
composite.getApprovals().setExpandRolesOnPreview(
adminGuiConfiguration.getApprovals().isExpandRolesOnPreview());
}
}
}

private void applyConfigurableDashboard(CompiledGuiProfile composit, ConfigurableUserDashboardType configurableUserDashboard, Task task, OperationResult result) {
Expand Down
Expand Up @@ -129,14 +129,14 @@ private ApprovalStageExecutionPreviewType createStageExecutionPreview(CaseType a
StageComputeHelper.ComputationResult computationResult = computeHelper
.computeStageApprovers(stageDef, aCase,
() -> computeHelper.getDefaultVariables(aCase, aCase.getApprovalContext(), requestChannel, result),
opTask, result);
StageComputeHelper.ComputationMode.PREVIEW, opTask, result);
rv.getExpectedApproverRef().addAll(computationResult.getApproverRefs());
rv.setExpectedAutomatedOutcome(computationResult.getPredeterminedOutcome());
rv.setExpectedAutomatedCompletionReason(computationResult.getAutomatedCompletionReason());
} catch (Throwable t) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't compute stage execution preview", t);
rv.setErrorMessage(MiscUtil.formatExceptionMessageWithCause(t));
rv.getExpectedApproverRef().addAll(CloneUtil.cloneCollectionMembers(stageDef.getApproverRef())); // at least something here
rv.getExpectedApproverRef().addAll(CloneUtil.cloneCollectionMembers(stageDef.getApproverRef())); // at least something here
}
return rv;
}
Expand Down
Expand Up @@ -75,7 +75,7 @@ public Action execute(OperationResult parentResult) {
() -> engine.stageComputeHelper
.getDefaultVariables(ctx.getCurrentCase(), ctx.getWfContext(), ctx.getTask().getChannel(),
result),
ctx.getTask(), result);
StageComputeHelper.ComputationMode.EXECUTION, ctx.getTask(), result);

ApprovalLevelOutcomeType predeterminedOutcome = preStageComputationResult.getPredeterminedOutcome();
Set<ObjectReferenceType> approverRefs = preStageComputationResult.getApproverRefs();
Expand Down
Expand Up @@ -21,6 +21,13 @@
import java.util.stream.Collectors;
import javax.xml.namespace.QName;

import com.evolveum.midpoint.model.api.authentication.GuiProfiledPrincipal;
import com.evolveum.midpoint.security.api.MidPointPrincipal;
import com.evolveum.midpoint.security.api.SecurityUtil;

import com.evolveum.midpoint.util.logging.LoggingUtils;

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -127,7 +134,8 @@ public interface VariablesProvider {

// TODO method name
public ComputationResult computeStageApprovers(ApprovalStageDefinitionType stageDef, CaseType theCase,
VariablesProvider variablesProvider, Task opTask, OperationResult opResult) {
VariablesProvider variablesProvider, @NotNull ComputationMode computationMode,
Task opTask, OperationResult opResult) {
ComputationResult rv = new ComputationResult();
VariablesMap variablesMap = null;
VariablesProvider enhancedVariablesProvider = () -> {
Expand Down Expand Up @@ -170,8 +178,12 @@ public ComputationResult computeStageApprovers(ApprovalStageDefinitionType stage

LOGGER.trace("Approvers at the stage {} (before potential group expansion) are: {}", stageDef, rv.approverRefs);
if (stageDef.getGroupExpansion() == GroupExpansionType.ON_WORK_ITEM_CREATION) {
rv.approverRefs = expandGroups(rv.approverRefs); // see MID-4105
LOGGER.trace("Approvers at the stage {} (after group expansion) are: {}", stageDef, rv.approverRefs);
if (shouldExpandGroup(computationMode)) {
rv.approverRefs = expandGroups(rv.approverRefs); // see MID-4105
LOGGER.trace("Approvers at the stage {} (after group expansion) are: {}", stageDef, rv.approverRefs);
} else {
LOGGER.trace("Groups will not be expanded; computation mode = {}", computationMode);
}
}

if (rv.approverRefs.isEmpty()) {
Expand All @@ -183,6 +195,23 @@ public ComputationResult computeStageApprovers(ApprovalStageDefinitionType stage
return rv;
}

private boolean shouldExpandGroup(ComputationMode computationMode) {
if (computationMode != ComputationMode.PREVIEW) {
return true;
}
MidPointPrincipal principal;
try {
principal = SecurityUtil.getPrincipal();
} catch (SecurityViolationException e) {
LoggingUtils.logException(LOGGER, "Couldn't get midPoint principal", e);
principal = null;
}
if (!(principal instanceof GuiProfiledPrincipal)) {
return false;
}
return ((GuiProfiledPrincipal) principal).getCompiledGuiProfile().isExpandRolesOnApprovalPreview();
}

public String evaluateAutoCompleteExpression(ApprovalStageDefinitionType stageDef, VariablesMap variables,
Task opTask, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException {
List<String> outcomes = evaluationHelper.evaluateExpression(stageDef.getAutomaticallyCompleted(), variables,
Expand Down Expand Up @@ -250,5 +279,11 @@ private Collection<ObjectReferenceType> expandAbstractRole(ObjectReferenceType a
}
}

/**
* Do we do our computation during preview or during actual execution?
*/
public enum ComputationMode {
PREVIEW, EXECUTION
}
}

0 comments on commit 868eca6

Please sign in to comment.