Skip to content

Commit

Permalink
Merge branch 'post-3.7-fixes' of https://github.com/Evolveum/midpoint
Browse files Browse the repository at this point in the history
…into post-3.7-fixes
  • Loading branch information
KaterynaHonchar committed Feb 21, 2018
2 parents 1ac4bc4 + 9d7ae7e commit 71fe9b5
Show file tree
Hide file tree
Showing 62 changed files with 3,379 additions and 87 deletions.
Expand Up @@ -112,4 +112,8 @@ public class ExpressionConstants {

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");

public static final QName VAR_PERFORMER = new QName(SchemaConstants.NS_C, "performer");
public static final QName VAR_OUTPUT = new QName(SchemaConstants.NS_C, "output");
public static final QName VAR_EVENT = new QName(SchemaConstants.NS_C, "event");
}
Expand Up @@ -205,6 +205,8 @@ public abstract class SchemaConstants {
public static final ItemPath PATH_PASSWORD = new ItemPath(C_CREDENTIALS, CredentialsType.F_PASSWORD);
public static final ItemPath PATH_PASSWORD_VALUE = new ItemPath(C_CREDENTIALS, CredentialsType.F_PASSWORD,
PasswordType.F_VALUE);
public static final ItemPath PATH_PASSWORD_FORCE_CHANGE = new ItemPath(C_CREDENTIALS, CredentialsType.F_PASSWORD,
PasswordType.F_FORCE_CHANGE);
public static final ItemPath PATH_PASSWORD_METADATA = new ItemPath(C_CREDENTIALS, CredentialsType.F_PASSWORD,
PasswordType.F_METADATA);
public static final ItemPath PATH_NONCE = new ItemPath(C_CREDENTIALS, CredentialsType.F_NONCE);
Expand Down
Expand Up @@ -532,5 +532,39 @@
</xsd:complexType>
<xsd:element name="policyItemTarget" type="tns:PolicyItemTargetType"/>


<xsd:complexType name="ExecuteCredentialResetRequestType">
<xsd:annotation>
<xsd:documentation>
</xsd:documentation>
<xsd:appinfo>
<a:container/>
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="resetMethod" type="xsd:string" minOccurs="0">
</xsd:element>
<xsd:element name="password" type="xsd:string" minOccurs="0">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="executeCredentialResetRequest" type="tns:ExecuteCredentialResetRequestType"/>

<xsd:complexType name="ExecuteCredentialResetResponseType">
<xsd:annotation>
<xsd:documentation>
</xsd:documentation>
<xsd:appinfo>
<a:container/>
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="message" type="c:LocalizableMessageType" minOccurs="0">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="executeCredentialResetResponse" type="tns:ExecuteCredentialResetResponseType"/>


</xsd:schema>

Expand Up @@ -1355,6 +1355,18 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="reviewerCommentsFormatting" minOccurs="0" type="tns:PerformerCommentsFormattingType">
<xsd:annotation>
<xsd:documentation>
Instructions how to format reviewers comments before storing them into metadata.
EXPERIMENTAL
</xsd:documentation>
<xsd:appinfo>
<a:experimental>true</a:experimental>
<a:since>3.7.1</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

Expand Down
Expand Up @@ -14586,7 +14586,9 @@
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="name" type="xsd:string" minOccurs="0">
<xsd:element name="name" type="xsd:string" minOccurs="0">
</xsd:element>
<xsd:element name="forceChange" type="xsd:boolean" minOccurs="0" maxOccurs="1" default="false">
</xsd:element>
<xsd:element name="securityQuestionReset" type="tns:SecurityQuestionsResetPolicyType" minOccurs="0">
</xsd:element>
Expand Down
Expand Up @@ -647,11 +647,61 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="approverCommentsFormatting" minOccurs="0" type="tns:PerformerCommentsFormattingType">
<xsd:annotation>
<xsd:documentation>
Instructions how to format approvers comments before storing them into metadata.
EXPERIMENTAL
</xsd:documentation>
<xsd:appinfo>
<a:experimental>true</a:experimental>
<a:since>3.7.1</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="primaryChangeProcessor" minOccurs="0" type="tns:PrimaryChangeProcessorConfigurationType" />
<xsd:element name="generalChangeProcessor" minOccurs="0" type="tns:GeneralChangeProcessorConfigurationType" />
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="PerformerCommentsFormattingType">
<xsd:annotation>
<xsd:documentation>
Instructions how to format approvers/reviewers comments before storing them into metadata.
Normally midPoint stores comments as they were entered by performers. However, each deployment can
tailor these e.g. by including performer name along with the comment.
EXPERIMENTAL
</xsd:documentation>
<xsd:appinfo>
<a:experimental>true</a:experimental>
<a:since>3.7.1</a:since>
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="value" type="tns:ExpressionType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
How to construct the comment. For example: performer.fullName + ': ' + output.comment.

Available variables:
- performer (i.e. reviewer or approver),
- output (of AbstractWorkItemOutputType),
- workItem (of AbstractWorkItemType - only for certification),
- event (of WorkItemCompletionEventType - only for approvals).
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="condition" type="tns:ExpressionType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Whether to include the particular output in comments. For example: output.comment != null.
Null or empty values are skipped regardless of the condition.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="WfExecutionTasksConfigurationType">
<xsd:annotation>
<xsd:documentation>
Expand Down
7 changes: 6 additions & 1 deletion model/certification-impl/pom.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2010-2017 Evolveum
~ Copyright (c) 2010-2018 Evolveum
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -67,6 +67,11 @@
<artifactId>model-impl</artifactId>
<version>3.7-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.evolveum.midpoint.model</groupId>
<artifactId>model-common</artifactId>
<version>3.7-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.evolveum.midpoint.infra</groupId>
<artifactId>common</artifactId>
Expand Down
Expand Up @@ -16,6 +16,7 @@
package com.evolveum.midpoint.certification.impl;

import com.evolveum.midpoint.certification.api.OutcomeUtils;
import com.evolveum.midpoint.model.common.SystemObjectCache;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ItemDelta;
Expand All @@ -35,6 +36,8 @@
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.wf.api.WorkflowManager;
import com.evolveum.midpoint.wf.util.PerformerCommentsFormatter;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
import org.apache.commons.lang.StringUtils;
Expand Down Expand Up @@ -67,6 +70,8 @@ public class AccessCertificationClosingTaskHandler implements TaskHandler {
@Autowired private AccCertGeneralHelper helper;
@Autowired private PrismContext prismContext;
@Autowired private AccCertQueryHelper queryHelper;
@Autowired private SystemObjectCache objectCache;
@Autowired private WorkflowManager workflowManager;
@Autowired @Qualifier("cacheRepositoryService") private RepositoryService repositoryService;

private static final transient Trace LOGGER = TraceManager.getTrace(AccessCertificationClosingTaskHandler.class);
Expand Down Expand Up @@ -105,17 +110,23 @@ public TaskRunResult run(Task task) {

AccessCertificationCampaignType campaign;
List<AccessCertificationCaseType> caseList;
PrismObject<SystemConfigurationType> systemConfigurationObject;
try {
campaign = helper.getCampaign(campaignOid, null, task, opResult);
caseList = queryHelper.searchCases(campaignOid, null, null, opResult);
systemConfigurationObject = objectCache.getSystemConfiguration(opResult);
} catch (ObjectNotFoundException|SchemaException e) {
opResult.computeStatus();
runResult.setRunResultStatus(TaskRunResultStatus.PERMANENT_ERROR);
LoggingUtils.logUnexpectedException(LOGGER, "Closing task couldn't start for campaign {} because of unexpected exception", e, campaignOid);
return runResult;
}

RunContext runContext = new RunContext(task);
PerformerCommentsFormattingType formatting = systemConfigurationObject != null &&
systemConfigurationObject.asObjectable().getAccessCertification() != null ?
systemConfigurationObject.asObjectable().getAccessCertification().getReviewerCommentsFormatting() : null;
PerformerCommentsFormatter commentsFormatter = workflowManager.createPerformerCommentsFormatter(formatting);
RunContext runContext = new RunContext(task, commentsFormatter);
caseList.forEach(aCase -> prepareMetadataDeltas(aCase, campaign, runContext, opResult));
runContext.objectContextMap.forEach((oid, ctx) -> applyMetadataDeltas(ctx, runContext, opResult));

Expand Down Expand Up @@ -193,14 +204,15 @@ private void prepareMetadataDeltas(AccessCertificationCaseType aCase, AccessCert
}

try {
objectCtx.modifications.addAll(createMetadataDeltas(aCase, campaign, objectCtx.object.getClass(), pathPrefix));
objectCtx.modifications.addAll(createMetadataDeltas(aCase, campaign, objectCtx.object.getClass(), pathPrefix, runContext, result));
} catch (SchemaException e) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't create certification metadata for {} {}", e, toShortString(objectCtx.object));
}
}

private List<ItemDelta<?, ?>> createMetadataDeltas(AccessCertificationCaseType aCase, AccessCertificationCampaignType campaign,
Class<? extends ObjectType> objectClass, ItemPath pathPrefix) throws SchemaException {
private List<ItemDelta<?, ?>> createMetadataDeltas(AccessCertificationCaseType aCase,
AccessCertificationCampaignType campaign, Class<? extends ObjectType> objectClass, ItemPath pathPrefix,
RunContext runContext, OperationResult result) throws SchemaException {
String outcome = aCase.getOutcome();
if (OutcomeUtils.isNoneOrNotDecided(outcome)) {
return emptyList();
Expand All @@ -215,8 +227,9 @@ private void prepareMetadataDeltas(AccessCertificationCaseType aCase, AccessCert
boolean commentNotEmpty = StringUtils.isNotEmpty(output.getComment());
if (commentNotEmpty || !OutcomeUtils.isNoneOrNotDecided(output.getOutcome())) {
certifiers.add(workItem.getPerformerRef().clone());
if (commentNotEmpty) {
comments.add(output.getComment());
String formattedComment = runContext.commentsFormatter.formatComment(workItem, runContext.task, result);
if (StringUtils.isNotEmpty(formattedComment)) {
comments.add(formattedComment);
}
}
}
Expand Down Expand Up @@ -281,9 +294,11 @@ private class ObjectContext {
private class RunContext {
final Task task;
final Map<String, ObjectContext> objectContextMap = new HashMap<>();
final PerformerCommentsFormatter commentsFormatter;

RunContext(Task task) {
RunContext(Task task, PerformerCommentsFormatter commentsFormatter) {
this.task = task;
this.commentsFormatter = commentsFormatter;
}
}
}
Expand Up @@ -918,7 +918,7 @@ public void test210CheckAfterClose() throws Exception {
userAdministrator = getUser(USER_ADMINISTRATOR_OID).asObjectable();
display("administrator", userAdministrator);
AssignmentType assignment = findAssignmentByTargetRequired(userAdministrator.asPrismObject(), ROLE_SUPERUSER_OID);
assertCertificationMetadata(assignment.getMetadata(), SchemaConstants.MODEL_CERTIFICATION_OUTCOME_ACCEPT, singleton(USER_ADMINISTRATOR_OID), singleton("no comment"));
assertCertificationMetadata(assignment.getMetadata(), SchemaConstants.MODEL_CERTIFICATION_OUTCOME_ACCEPT, singleton(USER_ADMINISTRATOR_OID), singleton("administrator: no comment"));
}

@Test
Expand Down
Expand Up @@ -1025,7 +1025,7 @@ public void test920CheckAfterClose() throws Exception {
display("administrator", userAdministrator);
AssignmentType assignment = findAssignmentByTargetRequired(userAdministrator.asPrismObject(), ROLE_COO_OID);
assertCertificationMetadata(assignment.getMetadata(), SchemaConstants.MODEL_CERTIFICATION_OUTCOME_ACCEPT,
new HashSet<>(asList(USER_ADMINISTRATOR_OID, USER_ELAINE_OID, USER_CHEESE_OID)), singleton("ok"));
new HashSet<>(asList(USER_ADMINISTRATOR_OID, USER_ELAINE_OID, USER_CHEESE_OID)), singleton("administrator: ok"));
}

}
Expand Up @@ -883,6 +883,6 @@ public void test320CheckAfterClose() throws Exception {
roleCoo = getRole(ROLE_COO_OID).asObjectable();
display("COO", roleCoo);
AssignmentType inducement = findInducementByTarget(ROLE_COO_OID, ROLE_SUPERUSER_OID);
assertCertificationMetadata(inducement.getMetadata(), SchemaConstants.MODEL_CERTIFICATION_OUTCOME_ACCEPT, singleton(USER_ADMINISTRATOR_OID), singleton("I'm so procrastinative..."));
assertCertificationMetadata(inducement.getMetadata(), SchemaConstants.MODEL_CERTIFICATION_OUTCOME_ACCEPT, singleton(USER_ADMINISTRATOR_OID), singleton("administrator: I'm so procrastinative..."));
}
}
Expand Up @@ -494,9 +494,9 @@ public void test210CheckAfterClose() throws Exception {
assertCertificationMetadata(findAssignmentByTargetRequired(userJack.asPrismObject(), roleATest2cOid).getMetadata(),
SchemaConstants.MODEL_CERTIFICATION_OUTCOME_ACCEPT, singleton(USER_JACK_OID), emptySet());
assertCertificationMetadata(findAssignmentByTargetRequired(userJack.asPrismObject(), roleATest3aOid).getMetadata(),
SchemaConstants.MODEL_CERTIFICATION_OUTCOME_ACCEPT, singleton(USER_JACK_OID), singleton("OK"));
SchemaConstants.MODEL_CERTIFICATION_OUTCOME_ACCEPT, singleton(USER_JACK_OID), singleton("jack: OK"));
assertCertificationMetadata(findAssignmentByTargetRequired(userJack.asPrismObject(), roleATest3bOid).getMetadata(),
SchemaConstants.MODEL_CERTIFICATION_OUTCOME_ACCEPT, singleton(USER_JACK_OID), singleton("dunno"));
SchemaConstants.MODEL_CERTIFICATION_OUTCOME_ACCEPT, singleton(USER_JACK_OID), singleton("jack: dunno"));
}

}
Expand Up @@ -58,7 +58,7 @@
*
* @author mederly
*/
@ContextConfiguration(locations = {"classpath:ctx-certification-test-with-workflows.xml"})
@ContextConfiguration(locations = {"classpath:ctx-certification-test-main.xml"})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class TestPolicyDrivenRoleLifecycle extends AbstractUninitializedCertificationTest {

Expand Down
Expand Up @@ -45,6 +45,23 @@
<redirectToFile>target/mail-notifications.log</redirectToFile>
</mail>
</notificationConfiguration>
<workflowConfiguration>
<modelHookEnabled>false</modelHookEnabled>
</workflowConfiguration>
<accessCertification>
<reviewerCommentsFormatting>
<value>
<script>
<code>performer.name + ': ' + output.comment</code>
</script>
</value>
<condition>
<script>
<code>output.comment != null &amp;&amp; !output.comment.isEmpty()</code>
</script>
</condition>
</reviewerCommentsFormatting>
</accessCertification>
<globalPolicyRule>
<name>sod-approval</name>
<policyConstraints>
Expand All @@ -63,5 +80,4 @@
<type>RoleType</type>
</targetSelector>
</globalPolicyRule>

</systemConfiguration>
Expand Up @@ -38,6 +38,7 @@
<import resource="ctx-model-common.xml"/>
<import resource="ctx-certification.xml"/>
<import resource="ctx-notifications.xml"/>
<import resource="ctx-workflow.xml"/>
<import resource="classpath*:ctx-repository-test.xml"/>
<import resource="ctx-repo-cache.xml"/>
<import resource="ctx-repo-common.xml"/>
Expand Down

0 comments on commit 71fe9b5

Please sign in to comment.