Skip to content

Commit

Permalink
Certification: using owner/approver defined by ownerRef/approverRef f…
Browse files Browse the repository at this point in the history
…ields, as well as by owner/approver relations.
  • Loading branch information
mederly committed Mar 15, 2017
1 parent 31bd11c commit 46b4d0d
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 25 deletions.
1 change: 1 addition & 0 deletions infra/prism/src/main/resources/xml/ns/public/query-3.xsd
Expand Up @@ -403,6 +403,7 @@
<xsd:complexType name="OrgFilterRefType">
<xsd:sequence>
<xsd:element name="oid" type="xsd:string" />
<xsd:element name="scope" type="tns:OrgFilterScopeType" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>

Expand Down
Expand Up @@ -22,22 +22,28 @@
import com.evolveum.midpoint.model.impl.expr.ModelExpressionThreadLocalHolder;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.builder.QueryBuilder;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.constants.ExpressionConstants;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.CertCampaignTypeUtil;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.schema.util.ResourceTypeUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

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

Expand All @@ -47,6 +53,8 @@
@Component
public class AccCertReviewersHelper {

private static final transient Trace LOGGER = TraceManager.getTrace(AccCertReviewersHelper.class);

@Autowired
@Qualifier("cacheRepositoryService")
private RepositoryService repositoryService;
Expand Down Expand Up @@ -192,31 +200,43 @@ protected List<ObjectReferenceType> getTargetObjectOwners(AccessCertificationCas
}
ObjectType target = resolveReference(_case.getTargetRef(), ObjectType.class, result);
if (target instanceof AbstractRoleType) {
ObjectReferenceType ownerRef = ((AbstractRoleType) target).getOwnerRef();
if (ownerRef != null) {
return Arrays.asList(ownerRef);
} else {
return null;
}
return getAssignees((AbstractRoleType) target, SchemaConstants.ORG_OWNER, task, result);
} else if (target instanceof ResourceType) {
return ResourceTypeUtil.getOwnerRef((ResourceType) target);
} else {
return null;
}
}

protected List<ObjectReferenceType> getObjectOwners(AccessCertificationCaseType _case, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException {
private List<ObjectReferenceType> getAssignees(AbstractRoleType role, QName relation, Task task, OperationResult result)
throws SchemaException {
List<ObjectReferenceType> rv = new ArrayList<>();
if (SchemaConstants.ORG_OWNER.equals(relation)) {
CollectionUtils.addIgnoreNull(rv, role.getOwnerRef());
} else if (SchemaConstants.ORG_APPROVER.equals(relation)) {
rv.addAll(role.getApproverRef());
} else {
throw new AssertionError(relation);
}
// TODO in theory, we could look for approvers/owners of UserType, right?
PrismReferenceValue ref = new PrismReferenceValue(role.getOid());
ref.setRelation(relation);
ObjectQuery query = QueryBuilder.queryFor(FocusType.class, prismContext)
.item(FocusType.F_ROLE_MEMBERSHIP_REF).ref(ref)
.build();
List<PrismObject<FocusType>> assignees = repositoryService.searchObjects(FocusType.class, query, null, result);
LOGGER.trace("Looking for '{}' of {} using {}: found: {}", relation.getLocalPart(), role, query, assignees);
assignees.forEach(o -> rv.add(ObjectTypeUtil.createObjectRef(o)));
return rv;
}

protected List<ObjectReferenceType> getObjectOwners(AccessCertificationCaseType _case, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException {
if (_case.getObjectRef() == null) {
return null;
}
ObjectType object = resolveReference(_case.getObjectRef(), ObjectType.class, result);
if (object instanceof AbstractRoleType) {
ObjectReferenceType ownerRef = ((AbstractRoleType) object).getOwnerRef();
if (ownerRef != null) {
return Arrays.asList(ownerRef);
} else {
return null;
}
return getAssignees((AbstractRoleType) object, SchemaConstants.ORG_OWNER, task, result);
} else {
return null;
}
Expand All @@ -228,7 +248,7 @@ private Collection<ObjectReferenceType> getTargetObjectApprovers(AccessCertifica
}
ObjectType target = resolveReference(_case.getTargetRef(), ObjectType.class, result);
if (target instanceof AbstractRoleType) {
return ((AbstractRoleType) target).getApproverRef();
return getAssignees((AbstractRoleType) target, SchemaConstants.ORG_APPROVER, task, result);
} else if (target instanceof ResourceType) {
return ResourceTypeUtil.getApproverRef((ResourceType) target);
} else {
Expand All @@ -242,7 +262,7 @@ private Collection<ObjectReferenceType> getObjectApprovers(AccessCertificationCa
}
ObjectType object = resolveReference(_case.getObjectRef(), ObjectType.class, result);
if (object instanceof AbstractRoleType) {
return ((AbstractRoleType) object).getApproverRef();
return getAssignees((AbstractRoleType) object, SchemaConstants.ORG_APPROVER, task, result);
} else {
return null;
}
Expand Down
Expand Up @@ -117,6 +117,7 @@ public class AbstractCertificationTest extends AbstractModelIntegrationTest {
protected static final String ORG_SECURITY_TEAM_OID = "e015eb10-1426-4104-86c0-eb0cf9dc423f";

public static final File ROLE_EROOT_USER_ASSIGNMENT_CAMPAIGN_OWNER_FILE = new File(COMMON_DIR, "role-eroot-user-assignment-campaign-owner.xml");
protected static final String ROLE_EROOT_USER_ASSIGNMENT_CAMPAIGN_OWNER_OID = "00000000-d34d-b33f-f00d-ffffffff0001";

public static final File ROLE_SUPERUSER_FILE = new File(COMMON_DIR, "role-superuser.xml");
protected static final String ROLE_SUPERUSER_OID = "00000000-0000-0000-0000-000000000004";
Expand Down Expand Up @@ -234,6 +235,16 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti
resourceDummyBlackType = resourceDummyBlack.asObjectable();
dummyResourceCtlBlack.setResource(resourceDummyBlack);

// Recompute relevant objects
recomputeUser(USER_JACK_OID, initTask, initResult);
recomputeUser(USER_ELAINE_OID, initTask, initResult);
recomputeUser(USER_GUYBRUSH_OID, initTask, initResult);
recomputeFocus(RoleType.class, ROLE_CEO_OID, initTask, initResult);
recomputeFocus(RoleType.class, ROLE_COO_OID, initTask, initResult);
recomputeFocus(RoleType.class, ROLE_CTO_OID, initTask, initResult);
recomputeFocus(RoleType.class, ROLE_REVIEWER_OID, initTask, initResult);
recomputeFocus(RoleType.class, ROLE_EROOT_USER_ASSIGNMENT_CAMPAIGN_OWNER_OID, initTask, initResult);
recomputeFocus(OrgType.class, ORG_SECURITY_TEAM_OID, initTask, initResult);
}

protected AccessCertificationCaseType checkCase(Collection<AccessCertificationCaseType> caseList, String subjectOid, String targetOid, FocusType focus, String campaignOid) {
Expand Down Expand Up @@ -360,13 +371,13 @@ protected void assertDefinitionAndOwner(AccessCertificationCampaignType campaign

protected void assertCaseReviewers(AccessCertificationCaseType _case, AccessCertificationResponseType currentStageOutcome,
int currentStage, List<String> reviewerOidList) {
assertEquals("wrong current stage outcome", currentStageOutcome, _case.getCurrentStageOutcome());
assertEquals("wrong current stage number", currentStage, _case.getCurrentStageNumber());
assertEquals("wrong current stage outcome for "+_case, currentStageOutcome, _case.getCurrentStageOutcome());
assertEquals("wrong current stage number for "+_case, currentStage, _case.getCurrentStageNumber());
Set<String> realReviewerOids = new HashSet<>();
for (ObjectReferenceType ref : _case.getCurrentReviewerRef()) {
realReviewerOids.add(ref.getOid());
}
assertEquals("wrong reviewer oids", new HashSet<>(reviewerOidList), realReviewerOids);
assertEquals("wrong reviewer oids for "+_case, new HashSet<>(reviewerOidList), realReviewerOids);
}

protected void recordDecision(String campaignOid, AccessCertificationCaseType _case, AccessCertificationResponseType response, String comment,
Expand Down
Expand Up @@ -964,7 +964,7 @@ public void test900StartRemediation() throws Exception {

userElaine = getUser(USER_ELAINE_OID).asObjectable();
display("userElaine", userElaine);
assertEquals("wrong # of userElaine's assignments", 4, userElaine.getAssignment().size());
assertEquals("wrong # of userElaine's assignments", 5, userElaine.getAssignment().size());

userGuybrush = getUser(USER_GUYBRUSH_OID).asObjectable();
display("userGuybrush", userGuybrush);
Expand Down
Expand Up @@ -168,7 +168,7 @@ public void test020OpenFirstStage() throws Exception {
assertCaseOutcome(caseList, ROLE_COO_OID, RESOURCE_DUMMY_BLACK_OID, ACCEPT, ACCEPT, null);
assertCaseOutcome(caseList, ROLE_COO_OID, ROLE_SUPERUSER_OID, ACCEPT, ACCEPT, null);
assertCaseOutcome(caseList, ROLE_SUPERUSER_OID, RESOURCE_DUMMY_OID, ACCEPT, ACCEPT, null);
assertPercentComplete(campaign, 20, 100, 0); // preliminary outcomes for all aases are "ACCEPT"
assertPercentComplete(campaign, 20, 100, 0); // preliminary outcomes for all cases are "ACCEPT"
}

protected void checkAllCases(Collection<AccessCertificationCaseType> caseList, String campaignOid) {
Expand Down
Expand Up @@ -55,7 +55,9 @@ jack->CTO none (A) -> A none (A) -> A | A
<script>
<code>
role = midpoint.resolveReferenceIfExists(assignment.targetRef)
return role != null &amp;&amp; role.riskLevel == 'critical'
role != null &amp;&amp; role.riskLevel == 'critical' &amp;&amp;
assignment.targetRef != null &amp;&amp;
(assignment.targetRef.relation == null || assignment.targetRef.relation.localPart != 'owner')
</code>
</script>
</itemSelectionExpression>
Expand Down
Expand Up @@ -27,8 +27,8 @@
<objectType>UserType</objectType>
<searchFilter>
<q:org>
<q:path>parentOrgRef</q:path>
<q:orgRef oid="00000000-8888-6666-0000-300000000000">
<q:orgRef>
<q:oid>00000000-8888-6666-0000-300000000000</q:oid>
<q:scope>SUBTREE</q:scope>
</q:orgRef>
</q:org>
Expand Down
Expand Up @@ -81,8 +81,16 @@ Superuser-Dummy: - -> A jack:A,administrator:nul
<reviewerExpression>
<script>
<code>
import com.evolveum.midpoint.schema.util.ObjectTypeUtil
import com.evolveum.midpoint.schema.constants.ObjectTypes

role = midpoint.resolveReference(certificationCase.objectRef)
role.ownerRef?.clone()
if (role.oid != '00000000-d34d-b33f-f00d-000000000001') {
role.ownerRef?.clone()
} else {
// hack: elaine's ownership of CEO role is defined by assignment[owner], not by ownerRef
ObjectTypeUtil.createObjectRef('c0c010c0-d34d-b33f-f00d-11111111111e', ObjectTypes.USER)
}
</code>
</script>
</reviewerExpression>
Expand Down
Expand Up @@ -130,6 +130,9 @@
<assignment>
<targetRef oid="00000000-d34d-b33f-f00d-000000000001" type="c:RoleType"/> <!-- CEO -->
</assignment>
<assignment>
<targetRef oid="00000000-d34d-b33f-f00d-000000000001" type="c:RoleType" relation="owner"/> <!-- CEO (intentionally without 'org' prefix) -->
</assignment>
<assignment>
<targetRef oid="00000000-d34d-b33f-f00d-ffffffff0000" type="c:RoleType"/> <!-- reviewer -->
</assignment>
Expand Down
Expand Up @@ -25,7 +25,7 @@
</construction>
</inducement>
<riskLevel>critical</riskLevel>
<ownerRef oid="c0c010c0-d34d-b33f-f00d-11111111111e" type="UserType" /> <!-- elaine -->
<!-- elaine is set as owner by including assignment with relation="owner" in her user record -->
<approverRef oid="c0c010c0-d34d-b33f-f00d-11111111111e" type="UserType" /> <!-- elaine -->
<approverRef oid="c0c010c0-d34d-b33f-f00d-111111111111" type="UserType" /> <!-- jack -->
</role>
Expand Up @@ -823,6 +823,10 @@ protected void recomputeUser(String userOid, Task task, OperationResult result)
modelService.recompute(UserType.class, userOid, null, task, result);
}

protected void recomputeFocus(Class<? extends FocusType> clazz, String userOid, Task task, OperationResult result) throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException {
modelService.recompute(clazz, userOid, null, task, result);
}

protected void recomputeUser(String userOid, ModelExecuteOptions options, Task task, OperationResult result) throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException {
modelService.recompute(UserType.class, userOid, options, task, result);
}
Expand Down

0 comments on commit 46b4d0d

Please sign in to comment.