> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/whats-new-in-openiam/earlier-releases/2025/v4-2-1-12.md).

# 4.2.1.12

Released 13 January 2025

Version 4.2.1.12 contains minor upgrades and security and vulnerability fixes. 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](https://bitbucket.org/openiam/conf/src/RELEASE-4.2.1.12/iamscripts/mail/custom/content/CreateUserRequestApproversApprovedEmail.groovy).

2. 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>
```

3. 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](https://bitbucket.org/openiam/conf/src/RELEASE-4.2.1.12/iamscripts/recon/).

2. 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);
    }
}
```

3. The `iamscripts/AM/AuthenticationLoginCustomHandler.groovy` was added into DefaultLoginModule. The script can be found [here](https://bitbucket.org/openiam/conf/src/RELEASE-4.2.1.12/iamscripts/AM/AuthenticationLoginCustomHandler.groovy).
4. A new groovy script was added: `iamscripts/bpm/certification/CustomCertificationHelper.groovy` to support customization of user selection in UAR campaign.&#x20;

```
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)
    }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/whats-new-in-openiam/earlier-releases/2025/v4-2-1-12.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
