> For the complete documentation index, see [llms.txt](https://docs-beta.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-beta.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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
