cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Operations in IdentityNow Transforms

Operations in IdentityNow Transforms

The transform documentation listed here is outdated and is no longer actively maintained. Please refer to https://developer.sailpoint.com/idn/docs/transforms for IdentityNow Transform documentation.

Labels (1)
Comments

A small note about the dateCompare transform. The NOW keyword includes a time element. So comparing a date without a time element to NOW will not return equal in most cases.

 

However, you can use the dateFormat transform to transform the NOW keyword to a date without a time element.

 

for example:

{
          "attributes": {
	        "firstDate": "2019-08-30T13:00:00+00:00",
	        "negativeCondition": "negative",
	        "operator": "GTE",
	        "positiveCondition": "positive",
	        "secondDate": {
              "attributes": {
                "values": "now",
                "inputFormat": "yyyy-MM-dd",
                "outputFormat": "ISO8601"
              },
              "type": "dateFormat"
            }
	        },    
	      "type": "dateCompare"
        
		}

 

// NJ, NY -> US
// India -> Asia
// UK,France -> Europe
// Other

We have a requirement, if any Attribute
* Input is NJ OR NY should come up as US.
* If Input is India or Sri Lanka should come up as Asia.
* Input is UK OR France should come up as UK and
* rest other value to come up as Other.

The below transformation will work for it.

{
"attributes": {
"values": [
{
"attributes": {
"attributeName": "location",
},
"type": "identityAttribute"
},
"table": {
"NJ","NY": "US",
"India": "Asia",
"UK","France": "Europe",
"default": "Other"
}
]
},

"id": "SailPoint Location",
"type": "lookup"
},

Please Suggest Thanks.

What if you use this table instead?

 

"table": {
"NJ": "US",
"NY": "US",
"India": "Asia",
"UK": "Europe",
"France": "Europe",
"default": "Other"
}

What can i do if i want to pass the current date when the condition is positive?

{
          "attributes": {
	        "firstDate": "2019-08-30T13:00:00+00:00",
	        "negativeCondition": "negative",
	        "operator": "GTE",
	        "positiveCondition": "positive", //instead of positive i need the current date
	        "secondDate": {
              "attributes": {
                "values": "now",
                "inputFormat": "yyyy-MM-dd",
                "outputFormat": "ISO8601"
              },
              "type": "dateFormat"
            }
	        },    
	      "type": "dateCompare"
        
		}

 

That's not possible.

Is there a way capitalize the first character of a string? e.g. transform john to John

@niharikagurjar , the dateFormat transform does not have access to the "now" keyword at this time, so what you have written will not work. The "now" keyword is currently only available to the dateCompare transform.

Please correct the links under "Primitive Operations" to link to page anchors on current page, instead of linking users to other pages they cannot access.

Is there a Camel case transform available?

@vkoldenh Can you help with the example you've posted here for the "now" variable? I've tried it several ways and can't get it to work:

Specifically:

1) Why did you use "yyyy-MM-dd" as the inputFormat when we know the "now" variable has a time element? How can that possibly be the correct input format? FWIW, I tried using ISO8601 as the outputFormat and having no inputFormat because that's option, but this didn't work.

2) I did test to see if your example should be switched, and perhaps the "now" variable needs to have an inputFormat of ISO8601 and an outputFormat of yyyy-MM-dd in order to strip that time stamp, but that didn't work for me either, as I assume that secondDate value HAS to be ISO8601 based on this document.

3) Can you even use the "values" attribute on the dateFormat transform? Don't you need to have it as "input" in some way? I only ask because no matter how I try to utilize a dateFormat for "now," it doesn't work for my data. I'm getting a null pointer exception, which in all honesty I would expect due to the format of what you've provided, but I can't seem to do any better so I'm asking for clarity.

Thanks in advance!

 

@cassidiopia  The point I wanted to make is that the NOW keyword contains a time element. So comparing NOW to 31-08-2020 will never be true (except at midnight) as the comparison will add a time element of 00:00.000 to the date.

As I do not know what you are trying to do, here is an example I use to determine the status of a identity.

 

"attributes": {
                "firstDate": {
                    "attributes": {
                        "values": [
                            {
                                "attributes": {
                                    "values": [
                                        {
                                            "attributes": {
                                                "name": "endDate"
                                            },
                                            "type": "identityAttribute"
                                        },
                                        "2999-12-31"
                                    ]
                                },
                                "type": "firstValid"
                            },
                            "T23:59:59.000Z"
                        ]
                    },
                    "type": "concat"
                },
                "negativeCondition": "leaver",
                "operator": "GTE",
                "positiveCondition": "active",
                "secondDate": "now"
            },
            "type": "dateCompare"

 

It uses the enddate and adds the 23:59 time part to it. As our system gives us the last working day we want the user to be active the whole day. Then we compare it with NOW.

NOTE: This sniplet is part of a bigger static transform, so there might be some syntax error due to copy/paste.

Hope this help, otherwise you might need to contact support. I do not work for Sailpoint.

Thanks, @vkoldenh that's much more helpful. I ended up going that same route after many failed attempts to format the now keyword.

I appreciate it!

Just to help others, you can do very cool stuff using the static transform. For instance, getting an attribute from the manager of an identity you can use the following:

 

{
    "attributes": {
        "value": "$identity.getManager().getAttribute(\"someattribute\")"
    },
    "id": "get Manager Attribute",
    "type": "static"
}

Hi,

I am trying to generate the userid in identity now using ransforms which is a numeral  for example 555. I want a condition where if I create the next user the userid should be userid + 1. Which in our case would be 556. Subequently the userid generated for new users should be 557, 558.....

 

I have built this logic below.  Please validate it. 

 

Thanks

 

{
  "attributes": {
    "cloudMaxSize": "100",
    "cloudMaxUniqueChecks": "10",
    "cloudRequired": "true"
  },
  "name": "NumericID",
  "transform": {
    "type": "usernameGenerator",
    "attributes": {
      "sourceCheck": true,
      "patterns": [
        "$fi{uniqueCounter}"
      ],
      "ln": {
        "type": "identityAttribute",
        "attributes": {
          "name": "lastname"
        }
      },
      "fi": {
        "type": "substring",
        "attributes": {
          "input": {
            "type": "identityAttribute",
            "attributes": {
              "name": "firstname"
            }
          },
          "begin": 0,
          "end": 1
        }
      }
    }
  },
  "type": "usernameGenerator"
}

using info from "vkoldenh" above, wrapped get manager attribute in a firstValid transform in case that the attribute comes as null / unavailable which causes an error.

 

{
    "attributes": {
        "values": [
            {
                "attributes": {
                    "value""$identity.getManager().getAttribute(\"distinguishedName\")"
                },
                "type""static"
            },
            {
                "attributes": {
                    "value"""
                },
                "type""static"
            }
        ]
    },
    "type""firstValid",
    "name""Managers DistinguishedName Transform"
}
 

Can you cascade primitives within one Transform? I've encountered phone data with a forward slash delimiter between the area code and the exchange. I think it is giving the E.164 transform trouble.  Can you run "Replace" and replace / with a space, then run the E.164?

@david_wardeI believe that it's possible. The example in the E.164 transform has an example which contains a static transform. Change that to the replace transform and the proper regex and it might just work. Otherwise, please post the transform, and i will have a look.

Hi @vkoldenh 

Could you help me reference the $oldValue of an identity attribute in a transform?

It is mentioned in the documentation but no methodology has been shared. I have unable to get it to work.

Reference: https://developer.sailpoint.com/idn/docs/transforms/operations/identity-attribute

Hi @ksbagade 

 

The oldValue variable is available, but might only be useful in a static transform. Below is a transform which is using the oldValue variable to verify if there has been a previous value or not.

{
            "attributes": {
                "preactiveoffset": {
                    "attributes": {
                        "expression": "now+2h/m",
                        "roundUp": true
                    },
                    "type": "dateMath"
                },
                "current_lcs": {
                    "attributes": {
                        "values": [
                            {
                                "attributes": {
                                    "name": "currentLifecyclestate"
                                },
                                "type": "identityAttribute"
                            },
                            "empty"
                        ]
                    },
                    "type": "firstValid"
                },
                "value": "#if(${current_lcs} eq \"prehire\" && ${oldValue} eq \"1900-01-01T00:00Z\")${preactiveoffset}#{elseif}(${current_lcs} eq \"prehire\")${oldValue}#{else}1900-01-01T00:00Z#end"
            },
            "id": "Determine PreActive offsetDate",
            "type": "static"
        },

 

If you explain what you might want to achieve I can help you if needed. But in short, the oldValue is filled with the current value of the attribute, so before the transform has changed it to something new. However, when the Identity Profile is created for a Identity the initial value of the oldValue variable is null. So keep that in mind please.

Hi @vkoldenh,

Thank you for the detailed response.

I am working on a use case that requires evaluation of the $oldValue of a specific Identity Attribute in a Transform being attached to another Identity Attribute in the Identity Profile.

Is it possible to call the $oldValue of another Identity Attribute apart from the one the transform is attached to?

Hi @ksbagade 

 

I don't think that is possible. The Identity Attributes are all evaluated in a random order (except for the LifeCycleState attribute which is always done last). So even if it was possible you have no knowledge if the oldValue of the other Identity Attibute is really the oldValue or has already been evaluated.

I think you can try to use an additional Identity Attribute which has the oldValue set and refer to that identityAttribute. But this depends on how the attribute should be filled.

You can also make a bigger transform and reuse the transfrom from the other Identity Attribute which you want to use. But getting the oldValue might be tricky.

Alternatively, you can try a rule but you need SailPoint Professional Services for that.

Hope this helps.

Regards,

Vincent

Hi @ksbagade

One issue I believe that is encountered with $oldValue is that the attribute containing $oldValue does not work very well when the related attribute changes a second time and you want to track changes over time. I have a potential solution for this which is having two additional identity fields. One that tracks the primary attribute old value and one that has an attribute change date that is used to reset the old value after a defined period of time. If you want to use transforms like this be sure to do some thorough testing including adding new identities and changes to in-situ identities to make sure it is working for you. I just created these transforms so that have not gone through a lot of testing.

(1) Transform for setting change date.

{
    "name""Test HR Department Changed Date Transform",
    "type""static",
    "attributes": {
        "Dept": {
            "attributes": {
                "values": [
                    {
                        "attributes": {
                            "attributeName""Org Level 2",
                            "sourceName""Test HR"
                        },
                        "type""accountAttribute"
                    },
                    "no department"
                ]
            },
            "type""firstValid"
        },
        "PrevDept": {
            "attributes": {
                "values": [
                    {
                        "attributes": {
                            "name""departmentPrevious"
                        },
                        "type""identityAttribute"
                    },
                    "no department"
                ]
            },
            "type""firstValid"
        },
        "Date": {
            "attributes": {
                "expression""now",
                "roundUp"false
            },
            "type""dateMath"
        },
        "value""#if($PrevDept != $Dept)$Date#{else}9999-01-01T00:00Z#end"
    }
}
 
(2) Transform for setting $oldValue
 
{
    "name""Test HR Previous Value Department",
    "type""firstValid",
    "attributes": {
        "values": [
            {
                "attributes": {
                    "firstDate": {
                        "attributes": {
                            "expression""+1h/m",
                            "input": {
                                "attributes": {
                                    "name""departmentChangedDate"
                                },
                                "type""identityAttribute"
                            }
                        },
                        "type""dateMath"
                    },
                    "secondDate""now",
                    "operator""lt",
                    "positiveCondition": {
                        "attributes": {
                            "attributeName""Org Level 2",
                            "sourceName""Test HR"
                        },
                        "type""accountAttribute"
                    },
                    "negativeCondition""$oldValue"
                },
                "type""dateCompare"
            },
            "$oldValue",
            {
                "attributes": {
                    "attributeName""Org Level 2",
                    "sourceName""Test HR"
                },
                "type""accountAttribute"
            },
            "none"
        ],
        "ignoreErrors""true"
    }
}
 

 

 

 

Hi @MikeHamilton 

I've been trying to get the last previous value of an attribute. So if there was a modification from values X01 to X02 and finally X03, i always need to read the n-1 previous value, that would be X02 here.

I tried using this transform, but i always get the first value there was in this attribute, for example X01. Code attached. Any idea? Thanks!

{
  "attributes": {
    "values": [
      "$oldValue",
      {
        "attributes": {
          "sourceName": "Mock-SAIP",
          "attributeName": "storeID"
        },
        "type": "accountAttribute"
      }
    ]
  },
  "type": "firstValid",
  "name": "oldValue firstValid"
}

 

@Augusto-Dallape Interesting requirement: Did you find a way to get the (n-1)th value?

I am testing the below transform. Trying to define 3 states for a Display name:

State A - regular employee, no changes

State B - Contractor in a specific Cost center - First Name Last Name (XYC-C Contractor)

State C - Contractor in any other cost center than above - First Name Last Name (Contractor)

 

Below is the json which is not showing any errors but when I test in my sandbox I get this error. Is it an error in the code or is it something else?

"There was an exception while calculating the value for this attribute. Error rendering template: #if($userType=='Contingent Worker'& $cost_center== '63032')${displayName} (IBM-C Contractor) #if($userType=='Contingent Worker'& $cost_center!== '63032')${displayName} (Contractor) #{else}${displayName}#end"

 

{
    "id": "test",
    "name": "setDisplayNameWorkday",
    "type": "static",
    "attributes": {
        "displayName": {
            "attributes": {
                "attributeName": "WORKER_NAME",
                "sourceName": "Workday"
            },
            "type": "accountAttribute"
        },
        "userType": {
            "attributes": {
                "attributeName": "EMPLOYEE_OR_CONTRACTOR__c",
                "sourceName": "Workday"
            },
            "type": "accountAttribute"
        },
        "value": "#if($userType=='Contingent Worker'& $cost_center== '12345')${displayName} (XYZ-C Contractor) #if($userType=='Contingent Worker'& $cost_center!== '12345')${displayName} (Contractor) #{else}${displayName}#end"
    },
    "internal": false
}

@nathanwray  Try using "&&" instead of "&" for your AND logic, and use an "elseif" instead of a second "if." You might also need to define $cost_center as an account attribute from Workday to use it in the "value" statement, I usually do. Might also want to play with the brackets around $displayName? I don't think I've combined a string and variable like that before. You could always use a concatenation in the attributes section as well, using something like $displayName1 and $displayName2?

I would write it like this to start:
"value": "#if($userType=='Contingent Worker'( && ($cost_center== '12345')${displayName} (XYZ-C Contractor) #elseif($userType=='Contingent Worker' && $cost_center!== '12345')${displayName} (Contractor) #{else}${displayName}#end"

@nathanwray  Sorry, typos in above:

"value": "#if($userType=='Contingent Worker' && $cost_center== '12345')${displayName} (XYZ-C Contractor) #elseif($userType=='Contingent Worker' && $cost_center!== '12345')${displayName} (Contractor) #{else}${displayName}#end"

@Auscornu 

 

I have the attributes included in the transform but still getting the same error

 

{
"id": "410ae3b6-fb9f-4b1a-89d0-b59ebae917bd",
"name": "setDisplayNameWorkday",
"type": "static",
"attributes": {
"displayName": {
"attributes": {
"attributeName": "WORKER_NAME",
"sourceName": "Workday"
},
"type": "accountAttribute"
},
"userType": {
"attributes": {
"attributeName": "EMPLOYEE_OR_CONTRACTOR__c",
"sourceName": "Workday"
},
"type": "accountAttribute"
},
"costCenter": {
"attributes": {
"attributeName": "COST_CENTER_REFERENCE_ID",
"sourceName": "Workday"
},
"type": "accountAttribute"
},
"value": "#if($userType=='Contingent Worker' && $costCenter== '12345')${displayName} (XYZ-C Contractor) #elseif($userType=='Contingent Worker' && $costCenter!== '12345')${displayName} (Contractor) #{else}${displayName}#end"
},
"internal": false
}

 

 

@nathanwray 

Try this for your value -

"value": "#if($userType=='Contingent Worker' && $costCenter== '12345')$displayName (XYZ-C Contractor) #elseif($userType=='Contingent Worker' && $costCenter!= '12345')$displayName (Contractor) #{else}$displayName#end"

I tested it and seemed to work. The NOT EQUALS being !== instead of != seemed to be the issue... I don't think the brackets around dsplayName matter.

That is correct. !== is not a valid comparison.

 

Taken from the Velocity Template documentation https://velocity.apache.org/engine/1.7/vtl-reference.html

To prevent XML parsing problem you might want to use eq,ne, gt alternative symbols instead.

 

Examples (showing different operators):

Operator Name Symbol Alternative Symbol Example

Equals Number==eq#if( $foo == 42 )
Equals String==eq#if( $foo == "bar" )
Object Equivalence==eq#if( $foo == $bar )
Not Equals!=ne#if( $foo != $bar )
Greater Than>gt#if( $foo > 42 )
Less Than<lt#if( $foo < 42 )
Greater Than or Equal To>=ge#if( $foo >= 42 )
Less Than or Equal To<=le#if( $foo <= 42 )
Boolean NOT!not#if( !$foo )

How to call transforms with in a transform like i need to implement , when workerType= Employee then one transform , workerType=Contractor then one transform , workerType=Joiner then another transform , Please help. I have 3 separate transforms with me , but now need to consolidate a single transform so that this gets called based on workerType

 

Revisiting this transform and getting an exception error.

 

There was an exception while calculating the value for this attribute. Error rendering template: #if($userType=='Contingent Worker' && $costCenter== ’12345')$displayName (XYZ Contractor) #elseif($userType=='Contingent Worker' && $costCenter!= ‘12345')$displayName (Contractor) #{else}$displayName#end

 

Any suggestion on what the error is in the syntax of the JSON or if I am overlooking something obvious?

Version history
Revision #:
30 of 30
Last update:
‎Aug 23, 2023 06:36 AM
Updated by: