Skip to content

Commit

Permalink
Resolve deprecated approvalWorkItems container
Browse files Browse the repository at this point in the history
OtherPrivilegesLimitationType.approvalWorkItems was deprecated in 4.0,
but it was - by mistake - in use up to (excluding) 4.8. This commit
tries to resolve this: The legacy form is used just as a default value
for the new one (caseManagementWorkItems). This is a preparation for
complete removal of the item in the future.

Other changes:

- Workflow tests are adapted to the recent changes in authorization
processing.
  • Loading branch information
mederly committed Jun 7, 2023
1 parent 6dff79b commit c9f3fec
Show file tree
Hide file tree
Showing 24 changed files with 240 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,7 @@ protected String load() {
try {
Task task = getPageBase().createSimpleTask(OPERATION_LOAD_WORK_ITEM_COUNT);
S_FilterEntryOrEmpty q = getPrismContext().queryFor(CaseWorkItemType.class);
ObjectQuery query = QueryUtils.filterForAssignees(q, getPageBase().getPrincipal(),
OtherPrivilegesLimitationType.F_APPROVAL_WORK_ITEMS, getPageBase().getRelationRegistry())
ObjectQuery query = QueryUtils.filterForCaseAssignees(q, getPageBase().getPrincipal())
.and()
.item(CaseWorkItemType.F_CLOSE_TIMESTAMP)
.isNull()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,15 +151,14 @@ public static AssignmentEditorDto createDtoAddFromSelectedObject(ObjectType obje
AssignmentEditorDto dto = createDtoFromObject(object, UserDtoStatus.ADD, relation, pageBase);
dto.setDelegationOwner(delegationOwner);
if (pageBase.getRelationRegistry().isDelegation(relation)) {
OtherPrivilegesLimitationType limitations = new OtherPrivilegesLimitationType();

WorkItemSelectorType approvalWorkItemSelector = new WorkItemSelectorType();
approvalWorkItemSelector.all(Boolean.TRUE);
limitations.setApprovalWorkItems(approvalWorkItemSelector);

WorkItemSelectorType certificationWorkItemSelector = new WorkItemSelectorType();
certificationWorkItemSelector.all(Boolean.TRUE);
limitations.setCertificationWorkItems(certificationWorkItemSelector);
OtherPrivilegesLimitationType limitations = new OtherPrivilegesLimitationType()
// "approval work items" item is deprecated, "case management" is the replacement
.caseManagementWorkItems(
new WorkItemSelectorType()
.all(true))
.certificationWorkItems(
new WorkItemSelectorType()
.all(true));

dto.setPrivilegesLimitation(limitations);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
</div>
<div>
<input type="checkbox" wicket:id="approvalWorkItems"/>
<wicket:message key="DelegationEditorPanel.delegateApprovalWorkItems"/>
<wicket:message key="DelegationEditorPanel.delegateCaseWorkItems"/>
</div>
<div>
<input class="pull-left" type="checkbox" wicket:id="certificationWorkItems"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,36 +344,46 @@ public boolean isVisible(){
labelContainer.add(limitPrivilegesButton);

AjaxCheckBox approvalRights = new AjaxCheckBox(ID_DELEGATE_APPROVAL_WI,
new IModel<Boolean>(){
new IModel<>() {
private static final long serialVersionUID = 1L;

@Override
public Boolean getObject(){
public Boolean getObject() {
AssignmentEditorDto dto = getModelObject();
if (dto.getPrivilegesLimitation() == null ||
dto.getPrivilegesLimitation().getApprovalWorkItems() == null ||
dto.getPrivilegesLimitation().getApprovalWorkItems().isAll() == null){
OtherPrivilegesLimitationType limitation = dto.getPrivilegesLimitation();
if (limitation == null) {
return false;
}
var newForm = limitation.getCaseManagementWorkItems();
if (newForm != null) {
return Boolean.TRUE.equals(newForm.isAll());
}
var legacyForm = limitation.getApprovalWorkItems();
if (legacyForm != null) {
return Boolean.TRUE.equals(legacyForm.isAll());
} else {
return false;
}
return dto.getPrivilegesLimitation().getApprovalWorkItems().isAll();
}

@Override
public void setObject(Boolean value){
public void setObject(Boolean value) {
AssignmentEditorDto dto = getModelObject();
OtherPrivilegesLimitationType limitations = dto.getPrivilegesLimitation();
if (limitations == null ){
if (limitations == null) {
limitations = new OtherPrivilegesLimitationType();
dto.setPrivilegesLimitation(limitations);
}

WorkItemSelectorType workItemSelector = new WorkItemSelectorType();
workItemSelector.all(value);
limitations.setApprovalWorkItems(workItemSelector);
// "approval work items" item is deprecated, "case management" is the replacement
limitations.setCaseManagementWorkItems(
new WorkItemSelectorType()
.all(value));
limitations.setApprovalWorkItems(null); // removing the legacy form
}

@Override
public void detach(){
public void detach() {
}
}) {
private static final long serialVersionUID = 1L;
Expand All @@ -398,36 +408,36 @@ public boolean isEnabled(){
body.add(approvalRights);

AjaxCheckBox certificationRights = new AjaxCheckBox(ID_DELEGATE_CERTIFICATION_WI,
new IModel<Boolean>(){
new IModel<>() {
private static final long serialVersionUID = 1L;

@Override
public Boolean getObject(){
public Boolean getObject() {
AssignmentEditorDto dto = getModelObject();
if (dto.getPrivilegesLimitation() == null ||
dto.getPrivilegesLimitation().getCertificationWorkItems() == null ||
dto.getPrivilegesLimitation().getCertificationWorkItems().isAll() == null){
dto.getPrivilegesLimitation().getCertificationWorkItems().isAll() == null) {
return false;
}
return dto.getPrivilegesLimitation().getCertificationWorkItems().isAll();
}

@Override
public void setObject(Boolean value){
public void setObject(Boolean value) {
AssignmentEditorDto dto = getModelObject();
OtherPrivilegesLimitationType limitations = dto.getPrivilegesLimitation();
if (limitations == null ){
if (limitations == null) {
limitations = new OtherPrivilegesLimitationType();
dto.setPrivilegesLimitation(limitations);
}

WorkItemSelectorType workItemSelector = new WorkItemSelectorType();
workItemSelector.all(value);
limitations.setCertificationWorkItems(workItemSelector);
limitations.setCertificationWorkItems(
new WorkItemSelectorType()
.all(value));
}

@Override
public void detach(){
public void detach() {
}
}) {
private static final long serialVersionUID = 1L;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ public MyCaseWorkItemsPanel(String id, AssignmentHolderDetailsModel model, Conta
}

protected ObjectFilter getCaseWorkItemsFilter() {
return QueryUtils.filterForNotClosedStateAndAssignees(getPrismContext().queryFor(CaseWorkItemType.class),
return QueryUtils.filterForNotClosedStateAndAssignees(
getPrismContext().queryFor(CaseWorkItemType.class),
AuthUtil.getPrincipalUser(),
OtherPrivilegesLimitationType.F_APPROVAL_WORK_ITEMS, getPageBase().getRelationRegistry())
OtherPrivilegesLimitationType.F_CASE_MANAGEMENT_WORK_ITEMS)
.desc(F_CREATE_TIMESTAMP)
.buildFilter();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ public PageCaseWorkItemsAllocatedToMe() {
}

@Override
protected ObjectFilter getCaseWorkItemsFilter(){
return QueryUtils.filterForNotClosedStateAndAssignees(getPrismContext().queryFor(CaseWorkItemType.class),
AuthUtil.getPrincipalUser(),
OtherPrivilegesLimitationType.F_APPROVAL_WORK_ITEMS, getRelationRegistry())
protected ObjectFilter getCaseWorkItemsFilter() {
return QueryUtils.filterForNotClosedStateAndAssignees(
getPrismContext().queryFor(CaseWorkItemType.class),
AuthUtil.getPrincipalUser(),
OtherPrivilegesLimitationType.F_CASE_MANAGEMENT_WORK_ITEMS)
.desc(F_CREATE_TIMESTAMP)
.buildFilter();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
import javax.xml.namespace.QName;
import java.util.List;

/**
*
*/
public class SchemaDeputyUtil {

/**
* The limitations list contains all "filters" that should be applied. This means that if a single record blocks the
* flow, the overall answer is negative.
*/
public static boolean limitationsAllow(List<OtherPrivilegesLimitationType> limitations, QName itemName) {
for (OtherPrivilegesLimitationType limitation : limitations) {
@SuppressWarnings({ "unchecked", "raw" })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8455,6 +8455,7 @@
</xsd:documentation>
<xsd:appinfo>
<a:deprecated>true</a:deprecated>
<!-- Note: it was deprecated, but the midPoint still used it up to (excluding) 4.8 -->
<a:deprecatedSince>4.0</a:deprecatedSince>
</xsd:appinfo>
</xsd:annotation>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,48 +15,63 @@
import com.evolveum.midpoint.prism.query.builder.S_FilterExit;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.RelationRegistry;
import com.evolveum.midpoint.schema.SchemaService;
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.ObjectTypeUtil;
import com.evolveum.midpoint.schema.util.SchemaDeputyUtil;
import com.evolveum.midpoint.security.api.DelegatorWithOtherPrivilegesLimitations;
import com.evolveum.midpoint.security.api.MidPointPrincipal;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseWorkItemType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemObjectsType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

/**
* TODO move to more appropriate place (common for both wf and certifications)
*/
public class QueryUtils {

/**
* The call to {@link #filterForAssignees(S_FilterEntryOrEmpty, MidPointPrincipal, QName)},
* for case management work items.
*/
public static S_FilterExit filterForCaseAssignees(S_FilterEntryOrEmpty q, MidPointPrincipal principal) {
return filterForAssignees(q, principal, OtherPrivilegesLimitationType.F_CASE_MANAGEMENT_WORK_ITEMS);
}

/**
* The call to {@link #filterForAssignees(S_FilterEntryOrEmpty, MidPointPrincipal, QName)},
* for access certification work items.
*/
public static S_FilterExit filterForCertificationAssignees(S_FilterEntryOrEmpty q, MidPointPrincipal principal) {
return filterForAssignees(q, principal, OtherPrivilegesLimitationType.F_CERTIFICATION_WORK_ITEMS);
}

/**
* Augments work item query by including filter to see only work items assigned to the current user or any of his delegators,
* providing that the limitation(s) allow it.
*
* Note that work item limitations are supported only in the current (crude) form: all or none.
*/
public static S_FilterExit filterForAssignees(S_FilterEntryOrEmpty q, MidPointPrincipal principal,
QName limitationItemName, RelationRegistry relationRegistry) {
@SuppressWarnings("WeakerAccess") // for compatibility purposes
public static S_FilterExit filterForAssignees(
S_FilterEntryOrEmpty q, MidPointPrincipal principal, QName limitationItemName) {
if (principal == null) {
return q.none();
} else {
return q.item(CaseWorkItemType.F_ASSIGNEE_REF).ref(getPotentialAssigneesForUser(principal, limitationItemName, relationRegistry));
return q.item(CaseWorkItemType.F_ASSIGNEE_REF)
.ref(getPotentialAssigneesForUser(principal, limitationItemName));
}
}

public static S_FilterExit filterForNotClosedStateAndAssignees(S_FilterEntryOrEmpty q, MidPointPrincipal principal,
QName limitationItemName, RelationRegistry relationRegistry) {
public static S_FilterExit filterForNotClosedStateAndAssignees(
S_FilterEntryOrEmpty q, MidPointPrincipal principal, QName limitationItemName) {
if (principal == null) {
return q.none();
} else {
return q.item(CaseWorkItemType.F_ASSIGNEE_REF)
.ref(getPotentialAssigneesForUser(principal, limitationItemName, relationRegistry))
.ref(getPotentialAssigneesForUser(principal, limitationItemName))
.and()
.item(CaseWorkItemType.F_CLOSE_TIMESTAMP)
.isNull();
Expand All @@ -76,14 +91,14 @@ public static S_FilterExit filterForClaimableItems(S_FilterEntryOrEmpty q, Strin
.isNull();
}

private static List<PrismReferenceValue> getPotentialAssigneesForUser(MidPointPrincipal principal,
QName limitationItemName, RelationRegistry relationRegistry) {
private static List<PrismReferenceValue> getPotentialAssigneesForUser(
MidPointPrincipal principal, QName limitationItemName) {
// As for relations, WorkItem.assigneeRef should contain only the default ones.
QName defaultRelation = relationRegistry.getDefaultRelation();
QName defaultRelation = SchemaService.get().relationRegistry().getDefaultRelation();
List<PrismReferenceValue> rv = new ArrayList<>();
rv.add(ObjectTypeUtil.createObjectRef(principal.getOid(), ObjectTypes.USER).relation(defaultRelation).asReferenceValue());
for (DelegatorWithOtherPrivilegesLimitations delegator : principal.getDelegatorWithOtherPrivilegesLimitationsCollection()) {
if (SchemaDeputyUtil.limitationsAllow(delegator.getLimitations(), limitationItemName)) {
if (delegator.limitationsAllow(limitationItemName)) {
rv.add(ObjectTypeUtil.createObjectRef(delegator.getDelegator(), defaultRelation).asReferenceValue());
}
}
Expand Down

0 comments on commit c9f3fec

Please sign in to comment.