Skip to content

Commit

Permalink
Fix visibility of approval buttons for attorney
Browse files Browse the repository at this point in the history
This is a very limited cherry-pick of c406971.
It fixes the visibility of Approve/Reject/Forward buttons visibility.

This resolves MID-6225.
  • Loading branch information
mederly committed Apr 27, 2020
1 parent 0765fa1 commit 251129f
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 45 deletions.
Expand Up @@ -3956,6 +3956,14 @@ public static void dropPowerOfAttorneyIfRequested(OperationResult result, PrismO
}
}

public static <T> T runUnderPowerOfAttorneyIfNeeded(CheckedProducer<T> producer, PrismObject<UserType> powerDonor,
PageBase pageBase, Task task, OperationResult result) throws CommonException {
if (powerDonor != null) {
return pageBase.getModelInteractionService().runUnderPowerOfAttorneyChecked(producer, powerDonor, task, result);
} else {
return producer.get();
}
}

@NotNull
public static List<SceneDto> computeChangesCategorizationList(ChangesByState changesByState, ObjectReferenceType objectRef,
Expand Down
Expand Up @@ -81,7 +81,7 @@ public void onClick(AjaxRequestTarget ajaxRequestTarget) {

}
};
workItemApproveButton.add(new VisibleBehaviour(() -> isApproveRejectButtonVisible()));
workItemApproveButton.add(new VisibleBehaviour(this::isApproveRejectButtonVisible));
workItemApproveButton.setOutputMarkupId(true);
actionButtonsContainer.add(workItemApproveButton);

Expand All @@ -97,7 +97,7 @@ public void onClick(AjaxRequestTarget ajaxRequestTarget) {
}
};
workItemRejectButton.setOutputMarkupId(true);
workItemRejectButton.add(new VisibleBehaviour(() -> isApproveRejectButtonVisible()));
workItemRejectButton.add(new VisibleBehaviour(this::isApproveRejectButtonVisible));
actionButtonsContainer.add(workItemRejectButton);

AjaxButton workItemForwardButton = new AjaxButton(ID_WORK_ITEM_FORWARD_BUTTON,
Expand All @@ -110,7 +110,7 @@ public void onClick(AjaxRequestTarget ajaxRequestTarget) {
}
};
workItemForwardButton.setOutputMarkupId(true);
workItemForwardButton.add(new VisibleBehaviour(() -> isForwardButtonVisible()));
workItemForwardButton.add(new VisibleBehaviour(this::isForwardButtonVisible));
actionButtonsContainer.add(workItemForwardButton);

AjaxButton workItemClaimButton = new AjaxButton(ID_WORK_ITEM_CLAIM_BUTTON,
Expand Down Expand Up @@ -222,30 +222,37 @@ public String getObject() {
}

private boolean isApproveRejectButtonVisible() {
boolean isAuthorized = false;
if (CaseWorkItemUtil.isCaseWorkItemClosed(getModelObject()) ||
CaseWorkItemUtil.isWorkItemClaimable(getModelObject())) {
return false; // checking separately to avoid needless authorization checking
}
try {
OperationResult result = new OperationResult(OPERATION_CHECK_SUBMIT_ACTION_AUTHORIZATION);
Task task = getPageBase().createSimpleTask(OPERATION_CHECK_SUBMIT_ACTION_AUTHORIZATION);
isAuthorized = getPageBase().getWorkflowManager().isCurrentUserAuthorizedToSubmit(getModelObject(), task, result);
return WebComponentUtil.runUnderPowerOfAttorneyIfNeeded(() ->
getPageBase().getWorkflowManager().isCurrentUserAuthorizedToSubmit(getModelObject(), task, result),
getPowerDonor(), getPageBase(), task, result);
} catch (Exception ex) {
LOGGER.error("Cannot check current user authorization to submit work item: {}", ex.getLocalizedMessage(), ex);
return false;
}
return CaseWorkItemUtil.isCaseWorkItemNotClosed(getModelObject()) &&
!CaseWorkItemUtil.isWorkItemClaimable(getModelObject()) && isAuthorized;

}

private boolean isForwardButtonVisible() {
boolean isAuthorized = false;
if (CaseWorkItemUtil.isCaseWorkItemClosed(getModelObject()) ||
CaseWorkItemUtil.isWorkItemClaimable(getModelObject())) {
return false; // checking separately to avoid needless authorization checking
}
try {
OperationResult result = new OperationResult(OPERATION_CHECK_DELEGATE_AUTHORIZATION);
Task task = getPageBase().createSimpleTask(OPERATION_CHECK_DELEGATE_AUTHORIZATION);
isAuthorized = getPageBase().getWorkflowManager().isCurrentUserAuthorizedToDelegate(getModelObject(), task, result);
return WebComponentUtil.runUnderPowerOfAttorneyIfNeeded(() ->
getPageBase().getWorkflowManager().isCurrentUserAuthorizedToDelegate(getModelObject(), task, result),
getPowerDonor(), getPageBase(), task, result);
} catch (Exception ex) {
LOGGER.error("Cannot check current user authorization to submit work item: {}", ex.getLocalizedMessage(), ex);
return false;
}
return CaseWorkItemUtil.isCaseWorkItemNotClosed(getModelObject()) &&
!CaseWorkItemUtil.isWorkItemClaimable(getModelObject()) && isAuthorized;
}

private boolean isClaimButtonVisible() {
Expand Down
Expand Up @@ -9,7 +9,6 @@
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.schema.GetOperationOptionsBuilder;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.WorkItemId;
import com.evolveum.midpoint.security.api.AuthorizationConstants;
Expand Down Expand Up @@ -37,8 +36,6 @@
import java.util.ArrayList;
import java.util.List;

import static com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType.F_OBJECT_REF;

/**
* @author mederly
*/
Expand Down Expand Up @@ -205,7 +202,12 @@ private void initLayout(){
summaryPanel.setOutputMarkupId(true);
add(summaryPanel);

WorkItemDetailsPanel workItemDetailsPanel = new WorkItemDetailsPanel(ID_WORK_ITEM_DETAILS, caseWorkItemModel);
WorkItemDetailsPanel workItemDetailsPanel = new WorkItemDetailsPanel(ID_WORK_ITEM_DETAILS, caseWorkItemModel) {
@Override
protected PrismObject<UserType> getPowerDonor() {
return PageCaseWorkItem.this.getPowerDonor();
}
};
workItemDetailsPanel.setOutputMarkupId(true);
add(workItemDetailsPanel);

Expand Down
Expand Up @@ -19,6 +19,7 @@
import com.evolveum.midpoint.schema.DeltaConvertor;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ApprovalContextUtil;
import com.evolveum.midpoint.schema.util.CaseTypeUtil;
import com.evolveum.midpoint.schema.util.WorkItemTypeUtil;
Expand Down Expand Up @@ -54,17 +55,15 @@
/**
* Created by honchar
*/
public class WorkItemDetailsPanel extends BasePanel<CaseWorkItemType>{
public class WorkItemDetailsPanel extends BasePanel<CaseWorkItemType> {
private static final long serialVersionUID = 1L;

private static final String DOT_CLASS = WorkItemDetailsPanel.class.getName() + ".";
private static final Trace LOGGER = TraceManager.getTrace(WorkItemDetailsPanel.class);
private static final String OPERATION_PREPARE_DELTA_VISUALIZATION = DOT_CLASS + "prepareDeltaVisualization";
private static final String OPERATION_LOAD_CUSTOM_FORM = DOT_CLASS + "loadCustomForm";
private static final String OPERATION_LOAD_CASE_FOCUS_OBJECT = DOT_CLASS + "loadCaseFocusObject";
private static final String OPERATION_CHECK_SUBMIT_AUTHORIZATION = DOT_CLASS + "checkApproveRejectAuthorization";
private static final String OPERATION_CHECK_DELEGATE_AUTHORIZATION = DOT_CLASS + "checkDelegateAuthorization";
private static final String OPERATION_CHECK_CLAIM_AUTHORIZATION = DOT_CLASS + "checkClaimAuthorization";
private static final String OPERATION_CHECK_ACTIONS_AUTHORIZATION = DOT_CLASS + "checkActionsAuthorization";

private static final String ID_DISPLAY_NAME_PANEL = "displayNamePanel";
private static final String ID_REQUESTED_BY = "requestedBy";
Expand Down Expand Up @@ -284,22 +283,25 @@ public String getObject() {

}

private boolean isAuthorizedForActions(){
Task checkApproveRejectAuthTask = getPageBase().createSimpleTask(OPERATION_CHECK_SUBMIT_AUTHORIZATION);
Task checkDelegateAuthTask = getPageBase().createSimpleTask(OPERATION_CHECK_DELEGATE_AUTHORIZATION);
private boolean isAuthorizedForActions() {
Task task = getPageBase().createSimpleTask(OPERATION_CHECK_ACTIONS_AUTHORIZATION);
OperationResult result = task.getResult();
try {
boolean isAuthorizedToSubmit = getPageBase().getWorkflowManager().isCurrentUserAuthorizedToSubmit(getModelObject(),
checkApproveRejectAuthTask, checkApproveRejectAuthTask.getResult());
boolean isAuthorizedToDelegate = getPageBase().getWorkflowManager().isCurrentUserAuthorizedToDelegate(getModelObject(),
checkDelegateAuthTask, checkDelegateAuthTask.getResult());
boolean isAuthorizedToClaim = getPageBase().getWorkflowManager().isCurrentUserAuthorizedToClaim(getModelObject());
return isAuthorizedToSubmit || isAuthorizedToClaim || isAuthorizedToDelegate;
} catch (Exception ex){
return WebComponentUtil.runUnderPowerOfAttorneyIfNeeded(() ->
getPageBase().getWorkflowManager().isCurrentUserAuthorizedToSubmit(getModelObject(), task, result) ||
getPageBase().getWorkflowManager().isCurrentUserAuthorizedToDelegate(getModelObject(), task, result) ||
getPageBase().getWorkflowManager().isCurrentUserAuthorizedToClaim(getModelObject()),
getPowerDonor(), getPageBase(), task, result);
} catch (Exception ex) {
LOGGER.error("Unable to check user authorization for workitem actions, ", ex.getLocalizedMessage());
}
return false;
}

protected PrismObject<UserType> getPowerDonor() {
return null;
}

// Expects that we deal with primary changes of the focus (i.e. not of projections)
// Beware: returns the full object; regardless of the security settings
public ObjectType getCaseFocusObject(CaseType caseType) {
Expand Down
Expand Up @@ -120,6 +120,13 @@ public static void assertReferenceValues(PrismReference ref, String... oids) {
}
}

public static void assertReferenceValues(List<? extends Referencable> refs, String... oids) {
assert oids.length == refs.size() : "Wrong number of values in "+refs+"; expected "+oids.length+" but was "+refs.size();
for (String oid: oids) {
assertReferenceValue(refs, oid);
}
}

public static void assertReferenceValue(PrismReference ref, String oid) {
for (PrismReferenceValue val: ref.getValues()) {
if (oid.equals(val.getOid())) {
Expand All @@ -129,6 +136,15 @@ public static void assertReferenceValue(PrismReference ref, String oid) {
fail("Oid "+oid+" not found in reference "+ref);
}

public static void assertReferenceValue(List<? extends Referencable> refs, String oid) {
for (Referencable ref: refs) {
if (oid.equals(ref.getOid())) {
return;
}
}
fail("Oid "+oid+" not found among references "+refs);
}

public static void assertItems(PrismContainer<?> object, int expectedNumberOfItems) {
List<PrismContainerValue> values = (List)object.getValues();
if (expectedNumberOfItems == 0) {
Expand Down
Expand Up @@ -64,10 +64,14 @@ public static CaseWorkItemType getWorkItem(CaseType aCase, long id) {
return null;
}

public static boolean isCaseWorkItemNotClosed(CaseWorkItemType workItem){
public static boolean isCaseWorkItemNotClosed(CaseWorkItemType workItem) {
return workItem != null && workItem.getCloseTimestamp() == null;
}

public static boolean isCaseWorkItemClosed(CaseWorkItemType workItem) {
return workItem != null && workItem.getCloseTimestamp() != null;
}

public static boolean isWorkItemClaimable(CaseWorkItemType workItem){
return workItem != null && (workItem.getOriginalAssigneeRef() == null || StringUtils.isEmpty(workItem.getOriginalAssigneeRef().getOid()))
&& !doesAssigneeExist(workItem) && CollectionUtils.isNotEmpty(workItem.getCandidateRef());
Expand Down
Expand Up @@ -27,7 +27,10 @@
import com.evolveum.midpoint.security.api.MidPointPrincipal;
import com.evolveum.midpoint.security.enforcer.api.ItemSecurityConstraints;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.CheckedProducer;
import com.evolveum.midpoint.util.DisplayableValue;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.Producer;
import com.evolveum.midpoint.util.annotation.Experimental;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ExecuteCredentialResetRequestType;
Expand Down Expand Up @@ -151,7 +154,7 @@ <F extends ObjectType> ModelContext<F> previewChanges(
<H extends AssignmentHolderType, R extends AbstractRoleType> RoleSelectionSpecification getAssignableRoleSpecification(PrismObject<H> assignmentHolder, Class<R> targetType, int assignmentOrder, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, ConfigurationException, ExpressionEvaluationException, CommunicationException, SecurityViolationException;

/**
* Returns filter for lookup of donors or power of attorney. The donors are the users that have granted
* Returns filter for lookup of donors of power of attorney. The donors are the users that have granted
* the power of attorney to the currently logged-in user.
*
* TODO: authorization limitations
Expand Down Expand Up @@ -355,6 +358,14 @@ MidPointPrincipal assumePowerOfAttorney(PrismObject<UserType> donor, Task task,
MidPointPrincipal dropPowerOfAttorney(Task task, OperationResult result)
throws SchemaException, SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException;

<T> T runUnderPowerOfAttorney(Producer<T> producer, PrismObject<UserType> donor, Task task, OperationResult result)
throws SchemaException, SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException;

default <T> T runUnderPowerOfAttorneyChecked(CheckedProducer<T> producer, PrismObject<UserType> donor, Task task, OperationResult result)
throws CommonException {
return MiscUtil.runChecked((p) -> runUnderPowerOfAttorney(p, donor, task, result), producer);
}

// Maybe a bit of hack: used to deduplicate processing of localizable message templates
@NotNull
LocalizableMessageType createLocalizableMessageType(LocalizableMessageTemplateType template,
Expand Down
Expand Up @@ -29,6 +29,7 @@
import com.evolveum.midpoint.schema.cache.CacheConfigurationManager;
import com.evolveum.midpoint.schema.util.*;
import com.evolveum.midpoint.security.enforcer.api.FilterGizmo;
import com.evolveum.midpoint.util.*;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.commons.lang.BooleanUtils;
Expand Down Expand Up @@ -141,13 +142,6 @@
import com.evolveum.midpoint.security.enforcer.api.ObjectSecurityConstraints;
import com.evolveum.midpoint.security.enforcer.api.SecurityEnforcer;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.DisplayableValue;
import com.evolveum.midpoint.util.LocalizableMessage;
import com.evolveum.midpoint.util.LocalizableMessageBuilder;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.annotation.Experimental;
import com.evolveum.midpoint.util.exception.CommonException;
import com.evolveum.midpoint.util.exception.CommunicationException;
Expand Down Expand Up @@ -1535,6 +1529,19 @@ public MidPointPrincipal dropPowerOfAttorney(Task task, OperationResult result)
return previousPrincipal;
}

@Override
public <T> T runUnderPowerOfAttorney(Producer<T> producer,
PrismObject<UserType> donor, Task task, OperationResult result)
throws SchemaException, SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException,
CommunicationException, ConfigurationException {
assumePowerOfAttorney(donor, task, result);
try {
return producer.run();
} finally {
dropPowerOfAttorney(task, result);
}
}

@Override
@NotNull
public LocalizableMessageType createLocalizableMessageType(LocalizableMessageTemplateType template,
Expand Down
Expand Up @@ -26,11 +26,7 @@
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AuthorizationPhaseType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.OrderConstraintsType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

/**
* @author Radovan Semancik
Expand Down Expand Up @@ -78,7 +74,7 @@ <O extends ObjectType, T extends ObjectType> void authorize(String operationUrl,
/**
* Returns a filter that applies to all the objects/targets for which the principal is authorized.
*
* E.g. it can return a filter of all assignable roles for a principlal. In that case #assign authorization is used,
* E.g. it can return a filter of all assignable roles for a principal. In that case #assign authorization is used,
* and object is the user which should hold the assignment.
*
* If it returns NoneFilter then no search should be done. The principal is not authorized for this operation at all.
Expand Down

0 comments on commit 251129f

Please sign in to comment.