New in v4.2.1.12

Version 4.2.1.12 contains minor upgrades and security and vulnerability fixes. The full set of changes can be found in the change log. The sections below provide an overview of the improvements and steps required after upgrading.

Bug fixes

  1. The changes are made to the iamscripts/mail/custom/content/CreateUserRequestApproversApprovedEmail.groovy script. The line
String pLang = user.getAttribute("PREFERRED_LANGUAGE") ?: "en_EN"

was changed to

String pLang = user.getAttribute("PREFERRED_LANGUAGE")?.getFirstValue() ?: "en_EN"

The full script can be found here.

  1. The bug for incorrect behavior of termination request to be approved by role with two members was fixed by changing the lines ...
<loopDataInputRef>ApproverCardindality</loopDataInputRef>
<inputDataItem name="cardinalityObject" />

... to one line.

<loopCardinality>${CountOfApproverSteps}</loopCardinality>

The complete file looks as follows.

<?xml version="1.0" encoding="UTF-8"?>
<definitions id="definitions"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="reviewAccessOnPositionChange">
<process id="reviewAccessOnPositionChange">
<startEvent id="start" name="Initialize Process" />
<sequenceFlow id="subProcessFlow" sourceRef="start" targetRef="subProcess" />
<subProcess id="subProcess" name="Start Approval Flow">
<multiInstanceLoopCharacteristics isSequential="true">
<loopCardinality>${CountOfApproverSteps}</loopCardinality>
<completionCondition>${!IsTaskApproved}</completionCondition>
</multiInstanceLoopCharacteristics>
<startEvent id="subProcessStart" />
<sequenceFlow id="subProcessStartFlow" sourceRef="subProcessStart" targetRef="sendRequests" />
<serviceTask id="sendRequests" activiti:class="org.openiam.workflow.activiti.delegate.entitlements.BasicEntitlementsRequestDelegate" name="Send Requests to Candidate Users" />
<sequenceFlow id="makeRequestDecisionFlow" sourceRef="sendRequests" targetRef="makeRequestDecision" />
<userTask id="makeRequestDecision" name="Make Decision">
<extensionElements>
<activiti:taskListener event="create" class="org.openiam.workflow.activiti.tasklistener.BasicCandidateTaskListener" />
</extensionElements>
</userTask>
<sequenceFlow id="preSubProcessEnd" sourceRef="makeRequestDecision" targetRef="subProcessEnd" />
<endEvent id="subProcessEnd" />
</subProcess>
<sequenceFlow id="afterSubProcess" sourceRef="subProcess" targetRef="approveOrRequestGateway" />
<exclusiveGateway id="approveOrRequestGateway" name="Perform Service task based on Decision" />
<sequenceFlow id="gateflow1" sourceRef="approveOrRequestGateway" targetRef="entitlementsOperation">
</sequenceFlow>
<serviceTask id="entitlementsOperation" activiti:class="org.openiam.workflow.activiti.delegate.entitlements.EntityMembershipDelegate" name="Task Accepted - Review All Access" />
<sequenceFlow id="gateflow2" sourceRef="approveOrRequestGateway" targetRef="rejectRequest">
</sequenceFlow>
<serviceTask id="rejectRequest" activiti:class="org.openiam.workflow.activiti.delegate.entitlements.RejectEntitlementsNotifierDelegate" name="Task Rejected" />
<sequenceFlow id="acceptRequestJoin" sourceRef="entitlementsOperation" targetRef="notifyAccepted" />
<serviceTask id="notifyAccepted" activiti:class="org.openiam.workflow.activiti.delegate.entitlements.AcceptEntitlementsNotifierDelegate" name="Send Notifications" />
<sequenceFlow id="rejectRequestJoin" sourceRef="rejectRequest" targetRef="finish" />
<sequenceFlow id="afterNotifyAccepted" sourceRef="notifyAccepted" targetRef="finish" />
<endEvent id="finish" name="Task Completed" />
</process>
</definitions>
  1. The same was done to activiti/terminateUser.bpmn20.xml file. The lines ...
               <loopDataInputRef>ApproverCardindality</loopDataInputRef>
              <inputDataItem name="cardinalityObject" />

... were changed to one line.

                        <loopCardinality>${CountOfApproverSteps}</loopCardinality>

The complete file is as given below.

<?xml version="1.0" encoding="UTF-8"?>
<definitions id="definitions"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="terminateUserProcess">
<process id="terminateUserProcess">
<startEvent id="start" name="Initialize Process" />
<sequenceFlow id="subProcessFlow" sourceRef="start" targetRef="subProcess" />
<subProcess id="subProcess" name="Start Approval Flow">
<multiInstanceLoopCharacteristics isSequential="true">
<loopCardinality>${CountOfApproverSteps}</loopCardinality>
<completionCondition>${!IsTaskApproved}</completionCondition>
</multiInstanceLoopCharacteristics>
<startEvent id="subProcessStart" />
<sequenceFlow id="subProcessStartFlow" sourceRef="subProcessStart" targetRef="sendRequests" />
<serviceTask id="sendRequests" activiti:class="org.openiam.workflow.activiti.delegate.entitlements.BasicEntitlementsRequestDelegate" name="Send Requests to Candidate Users" />
<sequenceFlow id="makeRequestDecisionFlow" sourceRef="sendRequests" targetRef="makeRequestDecision" />
<userTask id="makeRequestDecision" name="Make Decision">
<extensionElements>
<activiti:taskListener event="create" class="org.openiam.workflow.activiti.tasklistener.BasicCandidateTaskListener" />
</extensionElements>
</userTask>
<sequenceFlow id="preSubProcessEnd" sourceRef="makeRequestDecision" targetRef="subProcessEnd" />
<endEvent id="subProcessEnd" />
</subProcess>
<sequenceFlow id="afterSubProcess" sourceRef="subProcess" targetRef="approveOrRequestGateway" />
<exclusiveGateway id="approveOrRequestGateway" name="Perform Service task based on Decision" />
<sequenceFlow id="gateflow1" sourceRef="approveOrRequestGateway" targetRef="terminateUserTask">
<conditionExpression xsi:type="tFormalExpression">
${IsTaskApproved}
</conditionExpression>
</sequenceFlow>
<serviceTask id="terminateUserTask" activiti:class="org.openiam.workflow.activiti.delegate.user.edit.TerminateUser" name="Task Accepted - Terminate User" />
<sequenceFlow id="gateflow2" sourceRef="approveOrRequestGateway" targetRef="rejectRequest">
<conditionExpression xsi:type="tFormalExpression">
${!IsTaskApproved}
</conditionExpression>
</sequenceFlow>
<serviceTask id="rejectRequest" activiti:class="org.openiam.workflow.activiti.delegate.user.edit.RejectTerminateUserNotifierDelegate" name="Task Rejected" />
<sequenceFlow id="acceptRequestJoin" sourceRef="terminateUserTask" targetRef="notifyAccepted" />
<serviceTask id="notifyAccepted" activiti:class="org.openiam.workflow.activiti.delegate.user.edit.AcceptTerminateUserNotifierDelegate" name="Send Notifications" />
<sequenceFlow id="rejectRequestJoin" sourceRef="rejectRequest" targetRef="finish" />
<sequenceFlow id="afterNotifyAccepted" sourceRef="notifyAccepted" targetRef="finish" />
<endEvent id="finish" name="Task Completed" />
</process>
</definitions>

Improvements

  1. After refactoring conf method definitions the following groovy scripts were changed.
  • iamscripts/recon/DoNothingGroupCommand.groovy
  • iamscripts/recon/CreateIdmGroupCommand/CreateIdmGroupCommand.groovy
  • iamscripts/recon/CreateIdmGroupCommand/UpdateIdmGroupCommand.groovy
  • iamscripts/recon/CreateIdmGroupCustomCommand/CreateIdmGroupCustomCommand.groovy
  • iamscripts/recon/CreateIdmGroupCustomCommand/UpdateIdmGroupCustomCommand.groovy

They all can be found in this repository.

  1. To support the ability of the URIFederation scripts to get additional parameters about the request, which is in param. The params parameter was added as the last argument to the iamscripts/AM/ExampleURIFederationGroovyProcessor.groovy script.

Namely, the string...

getValue(String userId, ContentProvider contentProvider, URIPattern pattern, AbstractPatternMetaValue metaValue, URI uri) {

... was changed to the following.

String getValue(String userId, ContentProvider contentProvider, URIPattern pattern, AbstractPatternMetaValue metaValue, URI uri, AdaptiveAuthenticationExtraDataRequest params) {

And the new import was added.

import org.openiam.base.request.AdaptiveAuthenticationExtraDataRequest;

The complete script looks as follows.

import org.openiam.am.srvc.dto.AbstractPatternMetaValue
import org.openiam.am.srvc.dto.ContentProvider
import org.openiam.am.srvc.dto.URIPattern
import org.openiam.am.srvc.groovy.URIFederationGroovyProcessor
import org.openiam.esb.core.service.LoginDataService
import org.openiam.base.request.AdaptiveAuthenticationExtraDataRequest;
class GetPassword extends URIFederationGroovyProcessor {
private final static String MANAGED_SYS_ID = "0";
@Override
String getValue(String userId, ContentProvider contentProvider, URIPattern pattern, AbstractPatternMetaValue metaValue, URI uri, AdaptiveAuthenticationExtraDataRequest params) {
final LoginDataService loginDataService = context.getBean(LoginDataService.class);
if (!userId) {
return null;
}
String password = loginDataService.getByUserIdManagedSys(userId, MANAGED_SYS_ID)?.getPassword();
if (!password) {
return null;
}
return loginDataService.decryptPassword(userId, password);
}
}
  1. The iamscripts/AM/AuthenticationLoginCustomHandler.groovy was added into DefaultLoginModule. The script can be found here.

  2. A new groovy script was added: iamscripts/bpm/certification/CustomCertificationHelper.groovy to support customization of user selection in UAR campaign. 

package org.openiam.esb.core.batch.tasks
import org.openiam.idm.searchbeans.UserSearchBean
import org.openiam.idm.srvc.user.dto.User
class CustomCertificationHelper extends AccessCertificationHelper {
@Override
protected List<User> getData(UserSearchBean userSearchBean, int from, int size) {
/*
//example of getting only users with attrbute TEST_USER=true, if UAR name contains word 'TEST'
if (accessCertification && accessCertification.getName().contains("TEST")) {
userSearchBean.addAttribute("TEST_USER", "true")
return userWebService.findBeans(userSearchBean,
[UserCollection.GROUPS, UserCollection.ROLES,
UserCollection.PRINCIPALS, UserCollection.EMAILS,
UserCollection.ORGANIZATIONS, UserCollection.SUPERVISORS] as UserCollection[], from, size).getList();
} else super.getData(userSearchBean, from, size)
*/
super.getData(userSearchBean, from, size)
}
}