# Further information

Further information

# My Profile

## Description

<p class="callout success">My Profile is a part of a the Identity self service that allows to end users config their own profile, update the user info and preferences, change their password, and recover questions.</p>

To view My Profile, you must select the My Profile option that will be displayed when you click on the drop-down menu at the top right. Then Soffid displays a new window that will allow end users to configure their profiles.

## Screen overview

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2025-08/scaled-1680-/kRngWG9pwjs1QpgC-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2025-08/kRngWG9pwjs1QpgC-image.png)

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2025-08/scaled-1680-/0a25o4n9Jgl7X5Kc-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2025-08/0a25o4n9Jgl7X5Kc-image.png)

## Related objects

- [Users](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/users "Users") : to display the roles granted to a user
- [Roles](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/roles "Roles") : to display the roles
- [Information systems](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/information-systems "Information systems") : to display the roles throught the information systems
- [Authorizations](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/authorizations "Authorizations") : to review the authorizations and manage the roles assigned

## Standard attributes

### Basic

#### User Info

- **Last login:** date and time of the user's last login.
- **Last IP connection:** IP of the user's last login.
- **Change password**: allows end-users to change their password.
- **Password recovery questions**: (only when addon retrieve passwords is configured) allows end-users to config their own questions to recover their passwords.

<p class="callout info">For more info about password recovery, you can visit the [Password recovery questions page](https://bookstack.soffid.com/books/password-recovery/page/password-recovery-questions "Password recovery questions").</p>

#### Preferences

- **Language:** allows end-users to select their preferred language.
- **Time zone:** allows end-users to select their time zone.
- **Date format:** allows end-users to select the format date.
- **Sample:** displays how the date will be displayed in Soffid Console
- **Time format:** allows end-users to select the format time
- **Sample:** displays how the time will be displayed in Soffid Console
- **Enable desktop notifications in this browser**: enable desktop notifications in this browser
- **Display**: Light (backgroud in white), dark (background in dark)

### Authorizations

Display a list with the user authorizations.

- **Role**: role granted
- **Authorization \[domain value\]**: authrization description
- **ITS Scope**: authorization scope
- **Domain value**: domain where the role granted is assigned (\* when there is no domain)

### Application consents

Displays a list of all the user's consents given, and the user can see all of them. Users can remove the consent at any time as well.

When the user connects to a new application, the IdP will indicate which data will be shared with this application. That information is defined in the Attribute sharing policies page of the Federation.

<p class="callout info">For more info about password recovery, you can visit the [Attribute sharing policies page.](https://bookstack.soffid.com/books/federation/page/attribute-sharing-policies "Attribute sharing policies")</p>

## Actions

<table border="1" id="bkmrk-change-pasword-allow" style="border-collapse: collapse; width: 100%; height: 89.1051px;"><colgroup><col style="width: 30.2804%;"></col><col style="width: 69.7088%;"></col></colgroup><tbody><tr style="height: 29.7017px;"><td style="height: 29.7017px;">**Change pasword**</td><td style="height: 29.7017px;">Allows the user to change their current password.

The pop-up will display the restrictions applied according to your password policy.

You must enter your current password. If you cannot remember it, it is best to use the password recovery option when logging in to the Console. This option is included in the password recovery add-on.

</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">**Undo**</td><td style="height: 29.7017px;">Allows you to undo any changes made.</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">**Apply changes**</td><td style="height: 29.7017px;">Allows you to save the data. Once you apply changes, the details page will be closed.</td></tr></tbody></table>

# Soffid Objects (for agent mappings)

---

You can consult the list of Soffid attributes:

1. [User Object](https://bookstack.soffid.com/link/75#bkmrk-user-object)
2. [Account Object](https://bookstack.soffid.com/link/75#bkmrk-account-object)
3. [Group Object](https://bookstack.soffid.com/link/75#bkmrk-group-object)
4. [Role Object](https://bookstack.soffid.com/link/75#bkmrk-role-object)
5. [Grant Object](https://bookstack.soffid.com/link/75#bkmrk-grant-object)
6. [Maillist Object](https://bookstack.soffid.com/link/75#bkmrk-maillist-object)
7. [Membership Object](https://bookstack.soffid.com/link/75#bkmrk-membership-object)
8. [dispatcherService](#bkmrk-dispatcherservice)
9. [Authoritative change object](#bkmrk-%C2%A0-4)

---

## User object

A user objects are maps that hold the information belonging to a single user account.

<table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" id="bkmrk-attribute-type-descr" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row" style="height: 29px;"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" style="height: 29px; width: 141px;" tabindex="0"><div>**Attribute**</div></th><th aria-disabled="false" aria-label="Type: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" style="height: 29px; width: 183px;" tabindex="0"><div>**Type**</div></th><th aria-disabled="false" aria-label="Description: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="2" role="columnheader" scope="col" style="height: 29px; width: 485px;" tabindex="0"><div>**Description**</div></th></tr></thead><thead class="tableFloatingHeader"></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">id</td><td class="confluenceTd" style="height: 29px; width: 183px;">Long</td><td class="confluenceTd" style="height: 29px; width: 485px;">user id</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">accountId</td><td class="confluenceTd" style="height: 29px; width: 183px;">Long</td><td class="confluenceTd" style="height: 29px; width: 485px;">account id</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">accountName</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">account name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">system</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">managed system (agent) name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">accountDescription</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">account description</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">active</td><td class="confluenceTd" style="height: 29px; width: 183px;">Boolean</td><td class="confluenceTd" style="height: 29px; width: 485px;">true if user is active</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">accountDisabled</td><td class="confluenceTd" style="height: 29px; width: 183px;">Boolean</td><td class="confluenceTd" style="height: 29px; width: 485px;">true if account is diabled</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">mailAlias</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">blank separated mails</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">userName</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">primaryGroup</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user's primary group name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">comments</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user's comments</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">createdOn</td><td class="confluenceTd" style="height: 29px; width: 183px;">Date</td><td class="confluenceTd" style="height: 29px; width: 485px;">user creation date</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">modifiedOn</td><td class="confluenceTd" style="height: 29px; width: 183px;">Date</td><td class="confluenceTd" style="height: 29px; width: 485px;">user last modification date</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">mailDomain</td><td class="confluenceTd" style="height: 29px; width: 183px;">Date</td><td class="confluenceTd" style="height: 29px; width: 485px;">user mail domain ( email right side of @)</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">fullName</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user full name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">shortName</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user mail name (email left side of @)</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">firstName</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user first name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">lastName</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user last name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">lastName2</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user second last name (when applicable)</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">mailServer</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">mail server host name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">homeServer</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">home drive server host name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">profileServer</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">roaming profile server host name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">phone</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user's phone number</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">userType</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user type</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">createdBy</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user name creator of this user</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">modifiedBy</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 485px;">user name modifier of this user</td></tr><tr role="row" style="height: 57px;"><td class="confluenceTd" style="height: 57px; width: 141px;">secondaryGroups</td><td class="confluenceTd" style="height: 57px; width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" style="height: 57px; width: 485px;">list of [groups](#bkmrk-group-object) the user belongs to, including primary group

The attributes of the inner map are described later

</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">attributes</td><td class="confluenceTd" style="height: 29px; width: 183px;">Map&lt;String,String&gt;</td><td class="confluenceTd" style="height: 29px; width: 485px;">additional user attributes</td></tr><tr role="row" style="height: 35px;"><td class="confluenceTd" style="height: 35px; width: 141px;">grantedRoles</td><td class="confluenceTd" style="height: 35px; width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" style="height: 35px; width: 485px;">list of [grants](#bkmrk-grant-object) directly granted to the user</td></tr><tr role="row" style="height: 35px;"><td class="confluenceTd" style="height: 35px; width: 141px;">allGrantedRoles</td><td class="confluenceTd" style="height: 35px; width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" style="height: 35px; width: 485px;">list of [grants](#bkmrk-grant-object) directly on indirectly granted to the user</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">granted</td><td class="confluenceTd" style="height: 29px; width: 183px;">List&lt;String&gt;</td><td class="confluenceTd" style="height: 29px; width: 485px;">list of role names and group names directly granted to the user</td></tr><tr role="row" style="height: 45px;"><td class="confluenceTd" style="height: 45px; width: 141px;">allGranted</td><td class="confluenceTd" style="height: 45px; width: 183px;">List&lt;String&gt;</td><td class="confluenceTd" style="height: 45px; width: 485px;">list of role names and group names directly or indirectly granted to the user</td></tr></tbody></table>

## Account object

An account object holds the information belonging to an account.

<table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" id="bkmrk-attribute-type-descr-0" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" style="width: 148px;" tabindex="0"><div>**Attribute**</div></th><th aria-disabled="false" aria-label="Type: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" style="width: 183px;" tabindex="0"><div>**Type**</div></th><th aria-disabled="false" aria-label="Description: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="2" role="columnheader" scope="col" style="width: 475px;" tabindex="0"><div>**Description**</div></th></tr></thead><thead class="tableFloatingHeader"></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd" style="width: 148px;">accountDescription</td><td class="confluenceTd" style="width: 183px;">String</td><td class="confluenceTd" style="width: 475px;">account description</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">accountDisabled</td><td class="confluenceTd" style="width: 183px;">Boolean</td><td class="confluenceTd" style="width: 475px;">true if account is diabled</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">accountId</td><td class="confluenceTd" style="width: 183px;">Long</td><td class="confluenceTd" style="width: 475px;">account id</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">accountName</td><td class="confluenceTd" style="width: 183px;">String</td><td class="confluenceTd" style="width: 475px;">account name</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">allGranted</td><td class="confluenceTd" style="width: 183px;">List&lt;String&gt;</td><td class="confluenceTd" style="width: 475px;">list of role names directly or indirectly granted to the user</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">allGrantedRoles</td><td class="confluenceTd" style="width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" style="width: 475px;">list of [grants](#bkmrk-grant-object) directly on indirectly granted to the user</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">attributes</td><td class="confluenceTd" style="width: 183px;">Map&lt;String,String&gt;</td><td class="confluenceTd" style="width: 475px;">additional account attributes</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">granted</td><td class="confluenceTd" style="width: 183px;">List&lt;String&gt;</td><td class="confluenceTd" style="width: 475px;">list of role names directly granted to the user</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">grantedRoles</td><td class="confluenceTd" style="width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" style="width: 475px;">list of [grants](#bkmrk-grant-object) directly granted to the user</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">lastLogin</td><td class="confluenceTd" style="width: 183px;">Calendar</td><td class="confluenceTd" style="width: 475px;">lastLogin</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">lastPasswordUpdate</td><td class="confluenceTd" style="width: 183px;">Calendar</td><td class="confluenceTd" style="width: 475px;">lastPasswordUpdate</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">lastUpdate</td><td class="confluenceTd" style="width: 183px;">Calendar</td><td class="confluenceTd" style="width: 475px;">lastUpdate</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">passwordExpiration</td><td class="confluenceTd" style="width: 183px;">Calendar</td><td class="confluenceTd" style="width: 475px;">passwordExpiration</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">passwordPolicy</td><td class="confluenceTd" style="width: 183px;">String</td><td class="confluenceTd" style="width: 475px;">password policy</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">system</td><td class="confluenceTd" style="width: 183px;">String</td><td class="confluenceTd" style="width: 475px;">managed system (agent) name</td></tr><tr role="row"><td class="confluenceTd" style="width: 148px;">type</td><td class="confluenceTd" style="width: 183px;">AccountType</td><td class="confluenceTd" style="width: 475px;">"U"=user, "S"=shared, "P"=privileged, "I=ignored</td></tr></tbody></table>

## Group object

An group object holds the information belonging to a group.

<table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" id="bkmrk-attribute-type-descr-1" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row" style="height: 29px;"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" style="height: 29px; width: 140px;" tabindex="0"><div>**Attribute**</div></th><th aria-disabled="false" aria-label="Type: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" style="height: 29px; width: 183px;" tabindex="0"><div>**Type**</div></th><th aria-disabled="false" aria-label="Description: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="2" role="columnheader" scope="col" style="height: 29px; width: 492px;" tabindex="0"><div>**Description**</div></th></tr></thead><thead class="tableFloatingHeader"></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">groupId</td><td class="confluenceTd" style="height: 29px; width: 183px;">Long</td><td class="confluenceTd" style="height: 29px; width: 492px;">group id</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">name</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 492px;">group name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">description</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 492px;">group description</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">parent</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 492px;">parent group name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">server</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 492px;">home server host name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">disabled</td><td class="confluenceTd" style="height: 29px; width: 183px;">boolean</td><td class="confluenceTd" style="height: 29px; width: 492px;">true if the group is disabled</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">accountingGroup</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 492px;">group accounting information</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">type</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 492px;">group type</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">driveLetter</td><td class="confluenceTd" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" style="height: 29px; width: 492px;">home server letter to connect to</td></tr><tr role="row" style="height: 35px;"><td class="confluenceTd" style="height: 35px; width: 140px;">users</td><td class="confluenceTd" style="height: 35px; width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" style="height: 35px; width: 492px;">list of [users](#bkmrk-user-object) belonging to this group</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">userNames</td><td class="confluenceTd" style="height: 29px; width: 183px;">List&lt;String&gt;</td><td class="confluenceTd" style="height: 29px; width: 492px;">list of user names belonging to this group</td></tr><tr role="row" style="height: 35px;"><td class="confluenceTd" style="height: 35px; width: 140px;">allUsers</td><td class="confluenceTd" style="height: 35px; width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" style="height: 35px; width: 492px;">list of [users](#bkmrk-user-object) directly or indirectly belonging to this group</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">allUserNames</td><td class="confluenceTd" style="height: 29px; width: 183px;">List&lt;String&gt;</td><td class="confluenceTd" style="height: 29px; width: 492px;">list of user names either directly or indirectly grantee of this role</td></tr><tr role="row" style="height: 35px;"><td class="confluenceTd" style="height: 35px; width: 140px;">grantedRoles</td><td class="confluenceTd" style="height: 35px; width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" style="height: 35px; width: 492px;">list of [roles](#bkmrk-role-object) granted to this group</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 140px;">grantedRoleNames</td><td class="confluenceTd" style="height: 29px; width: 183px;">List&lt;String&gt;</td><td class="confluenceTd" style="height: 29px; width: 492px;">list of role names granted to this group</td></tr></tbody></table>

## Role object

An role object holds the information belonging to a role.

<table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" id="bkmrk-attribute-type-descr-2" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div>**Attribute**</div></th><th aria-disabled="false" aria-label="Type: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div>**Type**</div></th><th aria-disabled="false" aria-label="Description: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="2" role="columnheader" scope="col" tabindex="0"><div>**Description**</div></th></tr></thead><thead class="tableFloatingHeader"></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">roleId</td><td class="confluenceTd">Long</td><td class="confluenceTd">role id</td></tr><tr role="row"><td class="confluenceTd">system</td><td class="confluenceTd">String</td><td class="confluenceTd">managed system (agent) name</td></tr><tr role="row"><td class="confluenceTd">name</td><td class="confluenceTd">String</td><td class="confluenceTd">role name</td></tr><tr role="row"><td class="confluenceTd">application</td><td class="confluenceTd">String</td><td class="confluenceTd">application system name</td></tr><tr role="row"><td class="confluenceTd">category</td><td class="confluenceTd">String</td><td class="confluenceTd">role category</td></tr><tr role="row"><td class="confluenceTd">passwordProtected</td><td class="confluenceTd">boolean</td><td class="confluenceTd">true if role should be password protected (where applicable)</td></tr><tr role="row"><td class="confluenceTd">description</td><td class="confluenceTd">String</td><td class="confluenceTd">Role description</td></tr><tr role="row"><td class="confluenceTd">wfmanaged</td><td class="confluenceTd">boolean</td><td class="confluenceTd">true if role should be displayed in self service requests</td></tr><tr role="row"><td class="confluenceTd">domain</td><td class="confluenceTd">String</td><td class="confluenceTd">custom domain for this role: Use com.soffid.iam.api.DomainType constants or configured custom domain</td></tr><tr role="row"><td class="confluenceTd">ownedRoles</td><td class="confluenceTd">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd">list of[ roles granted](#bkmrk-grant-object) to this one</td></tr><tr role="row"><td class="confluenceTd">ownerRoles</td><td class="confluenceTd">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd">list of [roles grantee](#bkmrk-grant-object) of this one</td></tr><tr role="row"><td class="confluenceTd">ownerGroups</td><td class="confluenceTd">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd">list of [groups](#bkmrk-group-object) grantee of this role</td></tr><tr role="row"><td class="confluenceTd">grantedAccountNames</td><td class="confluenceTd">List&lt;String&gt;</td><td class="confluenceTd">list of account names directly grantee of this role</td></tr><tr role="row"><td class="confluenceTd">grantedAccounts</td><td class="confluenceTd">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd">list of [users](#bkmrk-user-object) directly grantee of this role</td></tr><tr role="row"><td class="confluenceTd">allGrantedAccountNames</td><td class="confluenceTd">List&lt;String&gt;</td><td class="confluenceTd">list of account names either directly or indirectly grantee of this role</td></tr><tr role="row"><td class="confluenceTd">allGrantedAccounts</td><td class="confluenceTd">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd">list of [users](#bkmrk-user-object) either directly or indirectly grantee of this role</td></tr><tr role="row"><td class="confluenceTd">attributes</td><td class="confluenceTd">Map&lt;String,Object&gt;</td><td class="confluenceTd">role's custom attributes</td></tr></tbody></table>

## Grant object

### Grant, grantedRole &amp; allGrantedRoles

The objects grant, grantedRole and allGrantedRoles are used to assing roles to accounts and roles.

<table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" id="bkmrk-attribute-type-descr-3" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: Ascending sort applied, activate to apply a descending sort" aria-sort="ascending" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerAsc" data-column="0" role="columnheader" scope="col" style="width: 193px;" tabindex="0"><div>**Attribute**</div></th><th aria-disabled="false" aria-label="Type: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" style="width: 166px;" tabindex="0"><div>**Type**</div></th><th aria-disabled="false" aria-label="Description: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" colspan="1" data-column="2" role="columnheader" scope="col" style="width: 457px;" tabindex="0"><div>**Description**</div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">domainValue</td><td class="confluenceTd" colspan="1" style="width: 166px;">String</td><td class="confluenceTd" colspan="1" style="width: 457px;">grant value (if any)</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">grantedRole</td><td class="confluenceTd" colspan="1" style="width: 166px;">String</td><td class="confluenceTd" colspan="1" style="width: 457px;">granted role name</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">grantedRoleId</td><td class="confluenceTd" colspan="1" style="width: 166px;">Long</td><td class="confluenceTd" colspan="1" style="width: 457px;">granted role id</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">grantedRoleObject</td><td class="confluenceTd" colspan="1" style="width: 166px;">[role object](#bkmrk-role-object)</td><td class="confluenceTd" colspan="1" style="width: 457px;">granted role</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">grantedRoleSystem</td><td class="confluenceTd" colspan="1" style="width: 166px;">String</td><td class="confluenceTd" colspan="1" style="width: 457px;">granted role managed system (agent) name</td></tr><tr role="row"><td class="confluenceTd" style="width: 193px;">id</td><td class="confluenceTd" style="width: 166px;">Long</td><td class="confluenceTd" colspan="1" style="width: 457px;">grant id</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">ownerAccount</td><td class="confluenceTd" colspan="1" style="width: 166px;">String</td><td class="confluenceTd" colspan="1" style="width: 457px;">grantee account name</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">ownerAccountObject</td><td class="confluenceTd" colspan="1" style="width: 166px;">[account object](#bkmrk-account-object)</td><td class="confluenceTd" colspan="1" style="width: 457px;">grantee account</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">ownerGroup</td><td class="confluenceTd" colspan="1" style="width: 166px;">String</td><td class="confluenceTd" colspan="1" style="width: 457px;">grantee group name</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">ownerRoleId</td><td class="confluenceTd" colspan="1" style="width: 166px;">String</td><td class="confluenceTd" colspan="1" style="width: 457px;">grantee role id</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">ownerRoleName</td><td class="confluenceTd" colspan="1" style="width: 166px;">String</td><td class="confluenceTd" colspan="1" style="width: 457px;">grantee role name</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">ownerSystem</td><td class="confluenceTd" colspan="1" style="width: 166px;">String</td><td class="confluenceTd" colspan="1" style="width: 457px;">grantee account or role managed system name</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 193px;">ownerUser</td><td class="confluenceTd" colspan="1" style="width: 166px;">String</td><td class="confluenceTd" colspan="1" style="width: 457px;">grantee user name</td></tr></tbody></table>

#### Examples

##### Grant

Example to map a grant object (assign a role to an account):

<table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" id="bkmrk-system-attribute-dir" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="System attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted align-center" data-column="0" role="columnheader" scope="col" style="width: 153px;" tabindex="0"><div>**System attribute**</div></th><th aria-disabled="false" aria-label="Direction: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted align-center" data-column="1" role="columnheader" scope="col" style="width: 87px;" tabindex="0"><div>**Direction**</div></th><th aria-disabled="false" aria-label="Soffid attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted align-center" data-column="2" role="columnheader" scope="col" style="width: 167px;" tabindex="0"><div>**Soffid attribute**</div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd" style="width: 153px;">role\_name</td><td class="confluenceTd align-center" style="width: 87px;">=&gt;</td><td class="confluenceTd" style="width: 167px;">grantedRole</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 153px;">account\_name</td><td class="confluenceTd align-center" colspan="1" style="width: 87px;">=&gt;</td><td class="confluenceTd" colspan="1" style="width: 167px;">ownerAccount</td></tr></tbody></table>

##### GrantedRole

Example to map a grantedRole object (assign a role as a child of another role):

<table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" id="bkmrk-system-attribute-dir-0" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="System attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted align-center" data-column="0" role="columnheader" scope="col" style="width: 150px;" tabindex="0"><div>**System attribute**</div></th><th aria-disabled="false" aria-label="Direction: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted align-center" data-column="1" role="columnheader" scope="col" style="width: 88px;" tabindex="0"><div>**Direction**</div></th><th aria-disabled="false" aria-label="Soffid attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted align-center" data-column="2" role="columnheader" scope="col" style="width: 168px;" tabindex="0"><div>**Soffid attribute**</div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd" style="width: 150px;">role\_name</td><td class="confluenceTd align-center" style="width: 88px;">=&gt;</td><td class="confluenceTd" style="width: 168px;">grantedRole</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 150px;">parent\_role\_name</td><td class="confluenceTd align-center" colspan="1" style="width: 88px;">=&gt;</td><td class="confluenceTd" colspan="1" style="width: 168px;">ownerRoleName</td></tr></tbody></table>

##### AllGrantedRoles

Example to map a allGrantedRoles object in a holderGroup (assign a role to an account in a specific group):

<table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" id="bkmrk-system-attribute-dir-1" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row" style="height: 29px;"><th aria-disabled="false" aria-label="System attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted align-center" data-column="0" role="columnheader" scope="col" style="width: 149px; height: 29px;" tabindex="0"><div>**System attribute**</div></th><th aria-disabled="false" aria-label="Direction: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted align-center" data-column="1" role="columnheader" scope="col" style="width: 89px; height: 29px;" tabindex="0"><div>**Direction**</div></th><th aria-disabled="false" aria-label="Soffid attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted align-center" data-column="2" role="columnheader" scope="col" style="width: 170px; height: 29px;" tabindex="0"><div>**Soffid attribute**</div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row" style="height: 29px;"><td class="confluenceTd" style="width: 149px; height: 29px;">role\_name</td><td class="confluenceTd align-center" style="width: 89px; height: 29px;">=&gt;</td><td class="confluenceTd" style="width: 170px; height: 29px;">grantedRole</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="width: 149px; height: 29px;">parent\_role\_name</td><td class="confluenceTd align-center" colspan="1" style="width: 89px; height: 29px;">=&gt;</td><td class="confluenceTd" colspan="1" style="width: 170px; height: 29px;">ownerRoleName</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="width: 149px; height: 29px;">group\_code</td><td class="confluenceTd align-center" colspan="1" style="width: 89px; height: 29px;">=&gt;</td><td class="confluenceTd" colspan="1" style="width: 170px; height: 29px;">domainValue</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="width: 149px; height: 29px;">group\_code</td><td class="confluenceTd align-center" colspan="1" style="width: 89px; height: 29px;">=&gt;</td><td class="confluenceTd" colspan="1" style="width: 170px; height: 29px;">holderGroup</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="width: 149px; height: 29px;">userName</td><td class="confluenceTd align-center" colspan="1" style="width: 89px; height: 29px;">=&gt;</td><td class="confluenceTd" colspan="1" style="width: 170px; height: 29px;">ownerUser</td></tr></tbody></table>

## Maillist object

<table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" id="bkmrk-attribute-type-descr-4" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" style="width: 172px;" tabindex="0"><div>**Attribute**</div></th><th aria-disabled="false" aria-label="Type: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" style="width: 101px;" tabindex="0"><div>**Type**</div></th><th aria-disabled="false" aria-label="Description: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" colspan="1" data-column="2" role="columnheader" scope="col" style="width: 553px;" tabindex="0"><div>**Description**</div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd" style="width: 172px;">id</td><td class="confluenceTd" style="width: 101px;">Long</td><td class="confluenceTd" colspan="1" style="width: 553px;">internal mail list id</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 172px;">name</td><td class="confluenceTd" colspan="1" style="width: 101px;">String</td><td class="confluenceTd" colspan="1" style="width: 553px;">mail list name ( the initial part, before the @ sign)</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 172px;">domain</td><td class="confluenceTd" colspan="1" style="width: 101px;">String</td><td class="confluenceTd" colspan="1" style="width: 553px;">mail list domain ( the remaining part after the @ sign)</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 172px;">system</td><td class="confluenceTd" colspan="1" style="width: 101px;">String</td><td class="confluenceTd" colspan="1" style="width: 553px;">managed system (agent) name</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 172px;">description</td><td class="confluenceTd" colspan="1" style="width: 101px;">String</td><td class="confluenceTd" colspan="1" style="width: 553px;">mail list description</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 172px;">users</td><td class="confluenceTd" colspan="1" style="width: 101px;">String array</td><td class="confluenceTd" colspan="1" style="width: 553px;">user names that are bound to this mail list</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 172px;">groups</td><td class="confluenceTd" colspan="1" style="width: 101px;">String array</td><td class="confluenceTd" colspan="1" style="width: 553px;">group names thta are subscribed to this mai list</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 172px;">roles</td><td class="confluenceTd" colspan="1" style="width: 101px;">String array</td><td class="confluenceTd" colspan="1" style="width: 553px;">role names that grant access to this mail list</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 172px;">lists</td><td class="confluenceTd" colspan="1" style="width: 101px;">String array</td><td class="confluenceTd" colspan="1" style="width: 553px;">Nested mail lists</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 172px;">explodedUsers</td><td class="confluenceTd" colspan="1" style="width: 101px;">String array</td><td class="confluenceTd" colspan="1" style="width: 553px;">Names of the users that should be subscribed to this mail list, including the users that should be subscribed due to group or role membership</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 172px;">explodedUserAddresses</td><td class="confluenceTd" colspan="1" style="width: 101px;">String array</td><td class="confluenceTd" colspan="1" style="width: 553px;">Mail addresses of any exploded User</td></tr></tbody></table>

## Membership object

A membership object contains the user account information as well as the group the user belongs to.

<table class="wrapped confluenceTable tablesorter tablesorter-default" id="bkmrk-attribute-type-descr-5" role="grid"><colgroup><col></col><col></col><col></col></colgroup><thead><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" style="width: 154px;" tabindex="0"><div>**Attribute**</div></th><th aria-disabled="false" aria-label="Type: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" style="width: 166px;" tabindex="0"><div>**Type**</div></th><th aria-disabled="false" aria-label="Description: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" colspan="1" data-column="2" role="columnheader" scope="col" style="width: 508px;" tabindex="0"><div>**Description**</div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd" colspan="1" style="width: 154px;">userName</td><td class="confluenceTd" colspan="1" style="width: 166px;">String</td><td class="confluenceTd" colspan="1" style="width: 508px;">User name</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 154px;">user</td><td class="confluenceTd" colspan="1" style="width: 166px;">Map&lt;String,Object&gt;</td><td class="confluenceTd" colspan="1" style="width: 508px;">[user object](#bkmrk-user-object)</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 154px;">groupName</td><td class="confluenceTd" colspan="1" style="width: 166px;">String</td><td class="confluenceTd" colspan="1" style="width: 508px;">Group name</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 154px;">group</td><td class="confluenceTd" colspan="1" style="width: 166px;">Map&lt;String,Object&gt;</td><td class="confluenceTd" colspan="1" style="width: 508px;">[group object](#bkmrk-group-object)</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 154px;">attributes</td><td class="confluenceTd" colspan="1" style="width: 166px;">Map&lt;String,Object&gt;</td><td class="confluenceTd" colspan="1" style="width: 508px;">Membership custom attributes</td></tr></tbody></table>

## dispatcherService

dispatcherService is an object available from agents' attribute translation rules.

This object contains four methods:

<div id="bkmrk-method-name-paramete"><div><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="method name: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" style="width: 116px;" tabindex="0"><div>**method name**</div></th><th aria-disabled="false" aria-label="parameters: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted align-center" data-column="1" role="columnheader" scope="col" style="width: 227px;" tabindex="0"><div>**parameters**</div></th><th aria-disabled="false" aria-label="result type: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted align-center" data-column="2" role="columnheader" scope="col" style="width: 126px;" tabindex="0"><div>**result type**</div></th><th aria-disabled="false" aria-label="comments: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="3" role="columnheader" scope="col" style="width: 367px;" tabindex="0"><div>**comments**</div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd" colspan="1" style="width: 116px;">soffidToSystem</td><td class="confluenceTd" colspan="1" style="width: 227px;">[ExtensibleObject](http://www.soffid.org/doc/console/2.0.0-2/iam-common/apidocs/com/soffid/iam/sync/intf/ExtensibleObject.html) soffidObject</td><td class="confluenceTd" colspan="1" style="width: 126px;">[ExtensibleObject](http://www.soffid.org/doc/console/2.0.0-2/iam-common/apidocs/com/soffid/iam/sync/intf/ExtensibleObject.html)</td><td class="confluenceTd" colspan="1" style="width: 367px;">Uses attribute translation tables to transform a soffid object to a target system object.

Mind to fill-in objectType property to use the proper object mapping

</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 116px;">systemToSoffid</td><td class="confluenceTd" colspan="1" style="width: 227px;">[ExtensibleObject](http://www.soffid.org/doc/console/2.0.0-2/iam-common/apidocs/com/soffid/iam/sync/intf/ExtensibleObject.html) systemObject</td><td class="confluenceTd" colspan="1" style="width: 126px;">[ExtensibleObject](http://www.soffid.org/doc/console/2.0.0-2/iam-common/apidocs/com/soffid/iam/sync/intf/ExtensibleObject.html)</td><td class="confluenceTd" colspan="1" style="width: 367px;">Uses attribute translation tables to transform a target system object to a Soffid object.

Mind to fill-in objectType property to use the proper object mapping

</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 116px;">search</td><td class="confluenceTd" colspan="1" style="width: 227px;">[ExtensibleObject](http://www.soffid.org/doc/console/2.0.0-2/iam-common/apidocs/com/soffid/iam/sync/intf/ExtensibleObject.html) exampleObject</td><td class="confluenceTd" colspan="1" style="width: 126px;">[ExtensibleObject](http://www.soffid.org/doc/console/2.0.0-2/iam-common/apidocs/com/soffid/iam/sync/intf/ExtensibleObject.html)</td><td class="confluenceTd" colspan="1" style="width: 367px;">Uses the exampleObject to perform a query by example on the target system. If the object exists on the target system, it is returned.

Mind to fill-in objectType property with the desired system object type

</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 116px;">invoke</td><td class="confluenceTd" colspan="1" style="width: 227px;">String verb

String action

Map parameters

</td><td class="confluenceTd" colspan="1" style="width: 126px;">List of Map</td><td class="confluenceTd" colspan="1" style="width: 367px;">This method allows arbitrary executions on the target system, but it semantics can change depending on the connector used.

For instance, it can be used to perform a GET on the target system in REST connector, can issue an LDAP query on ActiveDirectory connector, can execute a SELECT sentence on a SQL connector, or can execute an operating system command in Shell connector.

The results are returned as a list of objects (map).

</td></tr></tbody></table>

</div></div>#### Examples

##### Snippet to query the sys\_id attribute for a grant owner

```Java
System.out.println("Searching id for "+ownerRoleName);
com.soffid.iam.sync.intf.ExtensibleObject eo = new com.soffid.iam.sync.intf.ExtensibleObject();
eo.setObjectType("ROLE");
eo{"name"} = ownerRoleName;
eo = dispatcherService.search(eo);
System.out.println("FOUND "+eo{"sys_id"});
return eo{"sys_id"};
```

##### Snippet that performs a REST query to get group to role assignments in ServiceNow

```Java
list = dispatcherService.invoke ("GET",
  "https://arxusdev.service-now.com/api/now/table/sys_group_has_role?sysparm_exclude_reference_link=true&amp;sysparm_display_value=all&amp;sysparm_fields=role%2Cgroup&amp;sysparm_query=group="+sys_id,
  null).
  get(0).get("result")
  
r = new java.util.LinkedList();
for ( d: list)
{
  grant = new java.util.HashMap();
  grant{"grantedRole"} = d.get("role").get("display_value");
  grant{"grantedRoleSystem"} = "ServiceNow";
  grant{"ownerRoleName"} = name;
  grant{"ownerSystem"} = "ServiceNow";
  r.add  (grant);
}
return r;
```

##### Snippet of invoke usage on a relational database

```Java
// Table ITREPRT
role = source{"granted"}.size() == 0 ? "" : source{"granted"}.get(0);
System.out.println ("************** ROLE "+role);
args = new java.util.HashMap();
args.put("user", source{"accountName"}.toUpperCase());
if (role.equals ("Receptores PR") || role.equals("Jefes_Personal")) {
  r = dispatcherService.invoke("select", "* from ITREPRT where IDUSER=:user", args);
  if (r.size() == 0) {
    dispatcherService.invoke("insert", "into ITREPRT(IDUSER,NOMECO) values (:user, 1)", args);
  } 
} else {
  dispatcherService.invoke("delete", "from ITREPRT where IDUSER=:user", args);
}
// TABLE MRGEUCT
cc = source{"attributes"}{"dominio"};
if ( source{"userType"} .equals ("T")) {
  cc = source{"userName"}.substring(1); 
}
while (cc != null && cc.startsWith("0")) cc = cc.substring(1);
System.out.println ("************** COST CENTER "+cc);
if (cc != null && ! cc.trim().isEmpty())
{
  args = new java.util.HashMap();
  args.put("user", source{"accountName"}.toUpperCase());
  args.put("cc", cc);
  r = dispatcherService.invoke("SELECT", "* from MRGEUCT where IDUSER=:user and MOARPR=:cc", args);
  if (r.size() == 0) {
    dispatcherService.invoke("INSERT", "into MRGEUCT(MOARPR,CENTRA, IDUSER, NOTIFI ) "+
                             "values ('II', :cc, :user, 'S')", args);
    dispatcherService.invoke("INSERT", "into MRGEUCT(MOARPR,CENTRA, IDUSER, NOTIFI ) "+
                             "values ('BM', :cc, :user, 'S')", args);
    dispatcherService.invoke("DELETE", "FROM MRGEUCT WHERE CENTRA!=:cc AND IDUSER=:user", args);
  } 
}
return true;
```

##### Snippet of invoke usage on a Active Directory I

```javascript
hashMap = new java.util.HashMap();
list = serviceLocator.getDispatcherService().invoke("AD soffid.pat", 
                                                    "select", 
                                                    "(&(objectClass=user))", 
                                                    hashMap);
out.println("** list.size -- " + list.size());
```

##### Snippet of invoke usage on a Active Directory II

```javascript
ACC = source{"accountName"};
la = dispatcherService.invoke("AD soffid.pat", "(&(objectClass=user)(sAMAccountName=userName))", new java.util.HashMap());
```

## Authoritative change object

A user objects are maps that hold the information belonging to a single user account

<table class="confluenceTable tablesorter tablesorter-default" id="bkmrk-attribute-type-descr-6" role="grid"><colgroup><col></col><col></col><col></col></colgroup><thead><tr class="tablesorter-headerRow" role="row" style="height: 29px;"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" style="height: 29px; width: 141px;" tabindex="0"><div>**Attribute**</div></th><th aria-disabled="false" aria-label="Type: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" style="height: 29px; width: 183px;" tabindex="0"><div>**Type**</div></th><th aria-disabled="false" aria-label="Description: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" colspan="1" data-column="2" role="columnheader" scope="col" style="height: 29px; width: 485px;" tabindex="0"><div>**Description**</div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row" style="height: 29px;"><td class="confluenceTd" style="height: 29px; width: 141px;">id</td><td class="confluenceTd" style="height: 29px; width: 183px;">Long</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user id</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">accountId</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">Long</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">account id</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">accountName</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">account name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">system</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">managed system (agent) name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">accountDescription</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">account description</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">active</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">Boolean</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">true if user is active</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">accountDisabled</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">Boolean</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">true if account is diabled</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">mailAlias</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">blank separated mails</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">userName</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">primaryGroup</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user's primary group name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">comments</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user's comments</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">createdOn</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">Date</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user creation date</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">modifiedOn</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">Date</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user last modification date</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">mailDomain</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">Date</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user mail domain ( email right side of @)</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">fullName</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user full name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">shortName</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user mail name (email left side of @)</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">firstName</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user first name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">lastName</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user last name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">lastName2</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user second last name (when applicable)</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">mailServer</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">mail server host name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">homeServer</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">home drive server host name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">profileServer</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">roaming profile server host name</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">phone</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user's phone number</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">userType</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user type</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">createdBy</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user name creator of this user</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">modifiedBy</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">String</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">user name modifier of this user</td></tr><tr role="row" style="height: 57px;"><td class="confluenceTd" colspan="1" style="height: 57px; width: 141px;">secondaryGroups</td><td class="confluenceTd" colspan="1" style="height: 57px; width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" colspan="1" style="height: 57px; width: 485px;">list of [groups](https://confluence.soffid.com/display/SOF/group+object) the user belongs to, including primary group

The attributes of the inner map are described in the link

</td></tr><tr role="row" style="height: 57px;"><td class="confluenceTd" colspan="1" style="height: 57px; width: 141px;">secondariGroups2</td><td class="confluenceTd" colspan="1" style="height: 57px; width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" colspan="1" style="height: 57px; width: 485px;">list of user [memberships](https://confluence.soffid.com/display/SOF/membership+object), excluding primary group

The attributes of the inner map are described link

</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">attributes</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">Map&lt;String,String&gt;</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">additional user attributes</td></tr><tr role="row" style="height: 35px;"><td class="confluenceTd" colspan="1" style="height: 35px; width: 141px;">grantedRoles</td><td class="confluenceTd" colspan="1" style="height: 35px; width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" colspan="1" style="height: 35px; width: 485px;">list of [grants](https://confluence.soffid.com/display/SOF/grant+object) directly granted to the user</td></tr><tr role="row" style="height: 35px;"><td class="confluenceTd" colspan="1" style="height: 35px; width: 141px;">allGrantedRoles</td><td class="confluenceTd" colspan="1" style="height: 35px; width: 183px;">List&lt;Map&lt;String,Object&gt;&gt;</td><td class="confluenceTd" colspan="1" style="height: 35px; width: 485px;">list of [grants](https://confluence.soffid.com/display/SOF/grant+object) directly on indirectly granted to the user</td></tr><tr role="row" style="height: 29px;"><td class="confluenceTd" colspan="1" style="height: 29px; width: 141px;">granted</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 183px;">List&lt;String&gt;</td><td class="confluenceTd" colspan="1" style="height: 29px; width: 485px;">list of role names and group names directly granted to the user</td></tr><tr role="row" style="height: 45px;"><td class="confluenceTd" colspan="1" style="height: 45px; width: 141px;">allGranted</td><td class="confluenceTd" colspan="1" style="height: 45px; width: 183px;">List&lt;String&gt;</td><td class="confluenceTd" colspan="1" style="height: 45px; width: 485px;">list of role names and group names directly or indirectly granted to the user</td></tr></tbody></table>

# Sample scripts

## Introduction

<p class="callout info">Note that Soffid supports different scripting languages, you can configure it in the [Smart engine settings](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/smart-engine-settings "Smart engine settings") screen. **Soffid 4** configures the smart engine with **Javascript** scripting language as the default.</p>

Additionally, in the initial configuration of the container, we can configure the SOFFID\_TRUSTED\_SCRIPTS environment variable to allow the use of insecure classes. You can find this information visiting [the Installing IAM Console page](https://bookstack.soffid.com/link/27#bkmrk-4.-installation).

## Custom scripts page

The following **examples** of custom scripts can be run directly on the [Custom script](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/custom-scripts-addon-admin "Custom scripts (addon admin)") page.

These scripts can also be used in any other Soffid script component.

The scripts have been generated for the **Javascript engine**.

### Identity scripts

#### Recover a user for userName

```Java
var u = serviceLocator.getUserService().findUserByUserName("admin");
out.print("User: " + u.firstName);
```

#### Print some attributes

```Java
var u = serviceLocator.getUserService().findUserByUserName("test");
out.println("UserName: " + u.userName);
out.println("Name: " + u.firstName);
out.println("LastName: " + u.lastName);
```

#### Print by user the email

```Java
var u = serviceLocator.getUserService().findUserByUserName("test");
out.print("Email: " + u.shortName + "@" + u.mailDomain);
```

#### Print by user some additional data

```Java
llistaDadesUsuari = serviceLocator.getUserService().findUserDataByUserName("test");
for (var i=0; i<llistaDadesUsuari.size(); i++) {
  var dadaUsuari = llistaDadesUsuari.get(i);
  out.println("Atributs " + dadaUsuari.attribute + " = " + dadaUsuari.value);
}
```



#### Recover users from a json query with AI

```Java
/** Print on screen the names of all users whose username contains the letter a
 **/
var userService = serviceLocator.getService("com.soffid.iam.base.service.UserService");
var query = new com.soffid.zkdb.api.Query();
query.setFilter('userName co "a"'); // SCIM filter for username containing 'a'

var pagedResult = userService.findUsers(query);
var users = pagedResult.getResources();

if (users && users.size() > 0) {
  out.println("Users whose username contains 'a':");
  for (var i = 0; i < users.size(); i++) {
    var user = users.get(i);
    out.println(user.userName);
  }
} else {
  out.println("No users found with 'a' in their username.");
}
```

#### Create a new identity

```Java
var newUser = new com.soffid.iam.base.api.User();

newUser.userName = "jkepler";
newUser.firstName = "Johannes";
newUser.lastName = "Kepler";
newUser.userType = "I";
newUser.primaryGroup = "world";
newUser.active = true;
 
serviceLocator.getUserService().create(newUser);
out.println("Created "+newUser.userName);
```

#### Update an identity

```Java
var  u = serviceLocator.getUserService().findUserByUserName("jkepler");
u.userType = "E";
u = serviceLocator.getUserService().update(u);
out.println("Updated "+u.userName);
```

#### Delete an identity

```Java
var u = serviceLocator.getUserService().findUserByUserName("jkepler");
if (u!=null) {
  serviceLocator.getUserService().delete(u);
  out.println("Deleted "+u.userName);
} else {
  out.println("User not found");
}
```

### Account scripts

#### Recover accounts of users in Soffid 3

```Java
la = serviceLocator.getAccountService().findAccountByJsonQuery("users.user.userName eq \"02\" ");
for(a:la) {
  out.println("Cuenta: " + a.name);
  out.println("ID: " + a.id);
  out.println("System: " + a.system + "\n");
}
```

#### Recover accounts of users in Soffid 4 with AI with pagination

```Java
/** search all account whose owner's userName contains the letter 'd' and print the name of the account and the system by the screen
 **/
var query = new com.soffid.zkdb.api.Query();
query.filter = "users.user.userName co \"a\"";
query.pageSize = 2;
query.startIndex = 0;

var pagedResult;
do {
    pagedResult = serviceLocator.getAccountService().findAccounts(query);
    var accounts = pagedResult.resources;

    for (var i = 0; i < accounts.size(); i++) {
        var account = accounts.get(i);
        out.println("Account: " + account.name + ", System: " + account.system);
    }

    query.startIndex += query.pageSize;
} while (query.startIndex < pagedResult.totalResults);
```

#### Remove attribute values of a metadata in Soffid 3

```Java
public void removeUnAttributeValues(String attribute, String system) {
  la = serviceLocator.getAccountService().findAccountByJsonQuery("system eq \""+system+"\"");
  for (a : la) {
    laa = serviceLocator.getAccountService().getAccountAttributes(a);
    for (aa : laa) {
      if (aa.attribute.equals(attribute)) {
        if (aa.value!=null) {
          out.print("accountName: "+accountName+", attribute.value: "+aa.value);
          serviceLocator.getAccountService().removeAccountAttribute(aa);
          out.println(" ---> removed");
        }
      }
    }
  }
}
removeUnAttributeValues("manager","AD");
```

#### Remove attribute values of a metadata in Soffid 4

```javascript
function removeUnAttributeValues(attribute, system) {
  var query = new com.soffid.zkdb.api.Query();
  query.filter = "system eq \"" + system + "\"";
  
  var pagedResult = serviceLocator.getAccountService().findAccounts(query);
  var la = pagedResult.getResources();
  
  for (var i = 0; i < la.size(); i++) {
    var a = la.get(i);
    var laa = serviceLocator.getAccountService().getAccountAttributes(a);
    for (var j = 0; j < laa.size(); j++) {
      var aa = laa.get(j);
      if (aa.attribute == attribute) {
        if (aa.value != null) {
          out.print("accountName: " + a.name + ", attribute.value: " + aa.value);
          serviceLocator.getAccountService().removeAccountAttribute(aa);
          out.println(" ---> removed");
        }
      }
    }
  }
}
removeUnAttributeValues("manager", "AD");
```

### Role scripts

#### Recover roles of a user

```Java
user = serviceLocator.getUserService().findUserByUserName("Ivan");
out.println("Usuari: " + user.userName + "\n");
rolsUser = serviceLocator.getUserService().findUserRolesHierachyByUserName(user.userName);
for(listrRolsUser:rolsUser){
  out.println("Nombre: " + listrRolsUser.name);
  out.println("Descripcion: " + listrRolsUser.description);
  out.println();
}
```

#### Print the associated roles for each account


```Java
var queryUsuaris = new com.soffid.zkdb.api.Query();
queryUsuaris.filter = "userName eq \"david.gomez\"";
var pagedUsuaris = serviceLocator.getUserService().findUsers(queryUsuaris);
var llistaUsuaris = pagedUsuaris.getResources();

for (var i = 0; i < llistaUsuaris.size(); i++) {
  var usuari = llistaUsuaris.get(i);

  var queryComptes = new com.soffid.zkdb.api.Query();
  queryComptes.filter = "users.user.userName eq \"" + usuari.userName + "\"";
  var pagedComptes = serviceLocator.getAccountService().findAccounts(queryComptes);
  var llisstacuentas = pagedComptes.getResources();

  for (var j = 0; j < llisstacuentas.size(); j++) {
    var cuenta = llisstacuentas.get(j);
    out.print("   Cuenta : " + cuenta.name);

    var llistaRole = serviceLocator.getApplicationService().findRoleAccountByAccount(cuenta.id);
    for (var k = 0; k < llistaRole.size(); k++) {
      var role = llistaRole.get(k);
      out.print("      Role: " + role.roleName + "\n");
    }
  }
}
```

#### Print for an account the roles and applications for each of them


```Java
var queryUsuaris = new com.soffid.zkdb.api.Query();
queryUsuaris.filter = "userName eq \"david.gomez\"";
var pagedUsuaris = serviceLocator.getUserService().findUsers(queryUsuaris);
var llistaUsuaris = pagedUsuaris.getResources();

for (var i = 0; i < llistaUsuaris.size(); i++) {
  var usuari = llistaUsuaris.get(i);

  var queryComptes = new com.soffid.zkdb.api.Query();
  queryComptes.filter = "users.user.userName eq \"" + usuari.userName + "\"";
  var pagedComptes = serviceLocator.getAccountService().findAccounts(queryComptes);
  var llisstacuentas = pagedComptes.getResources();

  for (var j = 0; j < llisstacuentas.size(); j++) {
    var cuenta = llisstacuentas.get(j);
    out.print("   Cuenta : " + cuenta.name);
    out.println("   ID: " + cuenta.id);

    var llistaRole = serviceLocator.getApplicationService().findRoleAccountByAccount(cuenta.id);
    for (var k = 0; k < llistaRole.size(); k++) {
      var role = llistaRole.get(k);
      out.print("      Role: " + role.roleName + "\n");
      out.println("          Aplicacion: " + role.informationSystemName);
    }
  }
}
```

#### Print the roles associated with each account


```Java
var query = new com.soffid.zkdb.api.Query();
query.filter = "";
var paged = serviceLocator.getUserService().findUsers(query);
var usuCuenta = paged.getResources();

for (var i = 0; i < usuCuenta.size(); i++) {
  var listaUsuCuenta = usuCuenta.get(i);

  out.println("Usuario: " + listaUsuCuenta.userName);
  out.println("Nombre: " + listaUsuCuenta.firstName);

  var rolsUser = serviceLocator.getUserService().findUserRolesHierachyByUserName(listaUsuCuenta.userName);
  for (var j = 0; j < rolsUser.size(); j++) {
    var listaRolsUser = rolsUser.get(j);
    out.println("Nombre del Rol: " + listaRolsUser.name);
    out.println("Descripcion: " + listaRolsUser.description);
    out.println();
  }
}
```

#### Create a new role

```Java
try {
  var newRol = new com.soffid.iam.iga.api.Role();  
  newRol.name = "Rol_New_Script";
  newRol.description = "Rol Script";
  newRol.informationSystemName = "SOFFID";
  newRol.system = "soffid";
  serviceLocator.getApplicationService().create(newRol);
  out.println("Created: " + newRol.name);

} catch(e) {
    out.println("Error: " + e);
}
```

#### Update a role

```Java
var query = new com.soffid.zkdb.api.Query();
query.filter = "name eq \"Rol editado por script\" and informationSystemName eq \"APPLICATION01\"";

var pagedResult = serviceLocator.getApplicationService().findRoles(query);
var editRole = pagedResult.getResources();

for (var i = 0; i < editRole.size(); i++) {
    var role = editRole.get(i);
    out.println(role.name);
    role.name = "ROL01";
    try {
        role = serviceLocator.getApplicationService().update(role);
        out.println(role.name);
    } catch(e) {
        out.println("Error: " + e.message);
        out.println("Stack: " + e.stack);
    }
}
```

#### Delete a role

```Java
try {
  var editRole = serviceLocator.getApplicationService().findRoleById(16576);
  serviceLocator.getApplicationService().delete(editRole);
} catch(e) {
    out.println("Error: " + e.message);
}
```

#### List the roles of an application

```Java
var query = new com.soffid.zkdb.api.Query();
query.filter = "informationSystemName eq \"SOFFID\"";

var pagedResult = serviceLocator.getApplicationService().findRoles(query);
var list = pagedResult.getResources();

for (var i = 0; i < list.size(); i++) {
    var role = list.get(i);
    out.println(role.name);
}
```

### Mail scripts

#### Send a simple email

```Java
serviceLocator.getMailService().sendTextMail("user@domian.com", "Test", "Hello world!");
out.println("Mail sent!");
```

#### Send emails with attached files

```JavaScript
import javax.mail.BodyPart;
import javax.mail.internet.MimeBodyPart;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import java.util.ArrayList;
path = "/tmp/";
name = "file.txt";
BodyPart att = new MimeBodyPart();
att.setDataHandler(new DataHandler(new FileDataSource(path+name)));
att.setFileName(name);
to = "aretha@soffid.com";
cc = "etaylor@soffid.com";
subject = "This is an email with attachment ";
body = "In this email you can see an attachment.";
mimeBodyParts = new ArrayList();
mimeBodyParts.add(att);

serviceLocator.getMailService().sendHtmlMail(to, subject, body, mimeBodyParts);
serviceLocator.getMailService().sendHtmlMail(to, cc, subject, body, mimeBodyParts);
serviceLocator.getMailService().sendTextMailToActors(new String[]{"aretha"}, subject, body, mimeBodyParts);
serviceLocator.getMailService().sendTextMailToActors(new String[]{"aretha"}, cc, subject, body, mimeBodyParts);
out.println("Mails sent!");
```

### Event Sample scripts

#### On grant permission

Update a user attribute when assigning a specific permission

```shell
if (grant.roleName.equals("RS002")) {
  user = serviceLocator.getUserService().findUserByUserName(grant.user);
  if (user != null) {
    attributes = serviceLocator.getUserService().findUserAttributes(user.userName);
    if (attributes == null) {
        attributes = new HashMap();
    }
    attributes.put("language", "Spanish");
    serviceLocator.getUserService().updateUserAttributes(user.userName, attributes); 
  } 
}
```

#### On user change

Run a Python script when the user has assigned an specific role

```javascript
if (user != null) {
  roleGrantList = serviceLocator.getApplicationService().findEffectiveRoleGrantByUser(user.id);
  for(roleGrant:roleGrantList){
    if (roleGrant.roleName.equals("SOFFID_TEST")) {
      // RUN SCRIPT
      String command = "python3 /opt/soffid/iam-console-3/conf/exampleScript.py > /opt/soffid/iam-console-3/conf/resultscript01.txt";
      Process process = Runtime.getRuntime().exec(command);
      user.comments = "ADD comments";
      user = serviceLocator.getUserService().update(user);
    }
  }
}
```

### Agent scripts

#### User full name

```Java
return firstName + lastName;
```

#### Create mainDomain if it doesn't exit

```Java
var mailDomain = "exampledomain";
if (mailDomain != null && mailDomain.contains("@")) {
    var mailTokens = email.split("@");
    mailDomain = mailTokens[1];
}

var service = serviceLocator.getMailListsService();
var domain = service.findMailDomainByName(mailDomain);

if (domain == null) {
    domain = new com.soffid.iam.iga.api.MailDomain();  // ← iga.api
    domain.setCode(mailDomain);
    domain.setDescription(mailDomain);
    domain.setObsolete(new java.lang.Boolean(false));
    domain = service.create(domain);
}

return mailDomain;
```

#### Recover active agents

```Java
var llistaAgents = serviceLocator.getDispatcherService().findAllActiveDispatchers();
for (var i = 0; i < llistaAgents.size(); i++) {
    var agent = llistaAgents.get(i);
    out.println("Nom: " + agent.name);
    out.println("Class Name: " + agent.className + "\n");
}
```

#### Show by a user the agents that have associates

```Java
var queryUsuaris = new com.soffid.zkdb.api.Query();
queryUsuaris.filter = "userName eq \"admin\"";
var pagedUsuaris = serviceLocator.getUserService().findUsers(queryUsuaris);
var llistaUsuaris = pagedUsuaris.getResources();

for (var i = 0; i < llistaUsuaris.size(); i++) {
    var usuari = llistaUsuaris.get(i);
    out.println("Usuario: " + usuari.userName);

    var queryComptes = new com.soffid.zkdb.api.Query();
    queryComptes.filter = "users.user.userName eq \"" + usuari.userName + "\"";
    var pagedComptes = serviceLocator.getAccountService().findAccounts(queryComptes);
    var llisstacuentas = pagedComptes.getResources();

    for (var j = 0; j < llisstacuentas.size(); j++) {
        var cuenta = llisstacuentas.get(j);
        out.print("   Cuenta : " + cuenta.name);
        out.println("   ID: " + cuenta.id);

        var llistaRole = serviceLocator.getApplicationService().findRoleAccountByAccount(cuenta.id);
        for (var k = 0; k < llistaRole.size(); k++) {
            var role = llistaRole.get(k);
            out.print("      Role: " + role.roleName + "\n");
            out.println("          Aplicacion: " + role.informationSystemName);
            out.println("             Agente: " + role.system);
        }
    }
}
```

# Utility classes

## Crypt

Crypt allows to encrypt text with different algorithms and verify the resulting hash.

To use this class: `com.soffid.iam.crypt.Crypt`

All methods are static:

```Java
hash(String algorithm, String text) -> String
pBKDF2Sha256(String text, String utf8Salt, int iterations) -> String
pBKDF2Sha256(String text, byte []salt, int iterations) -> String
pBKDF2Sha1(String text, String utf8Salt, int iterations) -> String
pBKDF2Sha1(String text, byte []salt, int iterations) -> String
genSaltBytes() -> byte[] // 8 bytes
genSaltBytes(int size) -> byte[]
genSalt() -> String // 8 bytes
genSalt(int size) -> String
verify(String algorithm, String text, String hash) -> boolean

```

The algorithms allowed are:

- bcrypt
- pBKDF2Sha256
- pBKDF2Sha1 (or pBKDF2)
- Base64 (used by default is the algorithm is not in the previous list)

One example:

```Java
String myText = "abcd";
String myAlgorithm = "bcrypt";
String myHash = com.soffid.iam.crypt.Crypt.hash(myAlgorithm, myText);
boolean isVerified = com.soffid.iam.crypt.Crypt.verify(myAlgorithm, myText, myHash);
if (isVerified) {
    return myHash;
} else {
    return null;
}
```

## CalendarConverter

CalendarConverter allows to covert Calendar into String.

To use this class: `com.soffid.iam.json.CalendarConverter`

The methods (non static):

```Java
toString(Calendar instance) -> String
fromString(final String text) -> Calendar
```

One example:

```Java
out.println(new com.soffid.iam.json.CalendarConverter().toString(date));
```

# Beanshell vs Javascript

## Description

<p class="callout info">Soffid 4 configures the smart engine with **Javascript** scripting language as the default. See [Smart engine settings](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/smart-engine-settings "Smart engine settings").</p>

<p class="callout warning">Previously, the default engine was Beanshell, and many scripts will need to be adapted.</p>

This page lists these differences.

## Related objects

- [Smart engine settings](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/smart-engine-settings "Smart engine settings") : where the engine is configured.
- Where we can use scripts: 
    - [Agents](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/agents "Agents") : properties, mappings and triggers
    - [Custom scripts](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/sample-scripts "Sample scripts") : all the scripts
    - [Account naming rules](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/account-naming-rules "Account naming rules") : script to validate and set name
    - [Role assignment rules](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/role-assignment-rules "Role assignment rules") : script to validate
    - [BPM editor](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/bpm-editor-addon-bpm "BPM editor (addon bpm)") : visualization, triggers, transitions
    - [Password policies](https://bookstack.soffid.com/books/soffid-4-reference-guide/page/password-policies "Password policies") : optional script

## Table of differences

<table border="1" id="bkmrk-topic-beanshell-java" style="border-collapse: collapse; width: 100%; height: 604.438px;"><colgroup><col style="width: 17.519%;"></col><col style="width: 35.4103%;"></col><col style="width: 47.0599%;"></col></colgroup><tbody><tr style="height: 29.875px;"><td style="height: 29.875px;">**Topic**</td><td style="height: 29.875px;">**Beanshell**</td><td style="height: 29.875px;">**Javascript**</td></tr><tr style="height: 130.578px;"><td style="height: 130.578px;">variable</td><td style="height: 130.578px;">s = "text";</td><td style="height: 130.578px;">// The use of var should be mandatory,

//but it almost always works without using it.

var s = "text";

or

s = "text";

</td></tr><tr style="height: 80.2344px;"><td style="height: 80.2344px;">function</td><td style="height: 80.2344px;">public void doSomething(String system) {  
 ...  
}  
doSomething("APP\_USERS");</td><td style="height: 80.2344px;">function doSomething(system) {  
 ...  
}  
doSomething("APP\_USERS");</td></tr><tr style="height: 63.4375px;"><td style="height: 63.4375px;">for</td><td style="height: 63.4375px;">for (user : listOfUsers) {

 ...

}

</td><td style="height: 63.4375px;">for (var i=0; i&lt;listOgUsers.size(); i++) {  
 ...  
} </td></tr><tr style="height: 29.875px;"><td style="height: 29.875px;">equals</td><td style="height: 29.875px;">user == null

</td><td style="height: 29.875px;">user === null</td></tr><tr style="height: 29.875px;"><td style="height: 29.875px;">equals</td><td style="height: 29.875px;">userName.equals("myName")

</td><td style="height: 29.875px;">userName === "myName"</td></tr><tr style="height: 164.172px;"><td style="height: 164.172px;">java class</td><td style="height: 164.172px;">es.caib.seycon.ng.comu.AccountType

</td><td style="height: 164.172px;">Java.type("es.caib.seycon.ng.comu.AccountType")

// We can also generate objects without Java.type

query = new com.soffid.zkdb.api.Query();

or

Query = Java.type("com.soffid.zkdb.api.Query");

query = new Query();

</td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;">catch / printStackTrace</td><td style="height: 46.5938px;">} catch(Exception e) {  
 e.printStackTrace(out);

}

</td><td style="height: 46.5938px;">} catch(e) {  
 out.println(e.message);

}

</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">e.printStackTrace(out)

</td><td style="height: 29.7969px;">out.println(e.message) + out.println(e.stack)

</td></tr></tbody></table>

## Search in Soffid 4

<p class="callout warning">In Soffid 4 the findObjectByJsonQuery method no longers exits, it has been replaced by findObjects with or without pagination.</p>

List users

```
q = new com.soffid.zkdb.api.Query();
pr = serviceLocator.getUserService().findUsers(q);
lu = pr.getResources();
for (i=0; i<lu.size(); i++) {
  u = lu.get(i);
  out.println(u.userName);
}
```

List users with pagination

```
us = serviceLocator.getUserService();
q = new com.soffid.zkdb.api.Query();
q.startIndex = 0;
q.pageSize = 2;
do {
  out.println("Searching...");
  pr = us.findUsers(q);
  lu = pr.getResources();
  for (i=0; i<lu.size(); i++) {
    u = lu.get(i);
    out.println("   "+u.userName);
  }
  q.startIndex = q.startIndex+pr.itemsPerPage;
} while (q.startIndex<pr.totalResults);
```

# Office 365 as External SAML identity provider

### Introduction

Steps to configure Office 365 as External SAML identity provider.

### Step-by-Step

> <span style="color: #a6d100; font-weight: bold; font-size: 18px;">1.</span> Open a [https://portal.azure.com](https://portal.azure.com)

<span style="color: #a6d100; font-weight: bold; font-size: 18px;">2.</span> Open **Microsoft Entra ID** and then select **Enterprise applications** option

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/WP18dhnYbR5sissf-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/WP18dhnYbR5sissf-image.png)

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/ftXynvrNNSko2rqR-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/ftXynvrNNSko2rqR-image.png)

<span style="color: #a6d100; font-weight: bold; font-size: 18px;">3.</span> Select **All applications** and click **New Application**

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/yyrrWOSNAdSagMvk-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/yyrrWOSNAdSagMvk-image.png)

<span style="color: #a6d100; font-weight: bold; font-size: 18px;">4.</span> Select Create your own application

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/iiJbB8yPOkNYRsqu-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/iiJbB8yPOkNYRsqu-image.png)

<span style="color: #a6d100; font-weight: bold; font-size: 18px;">5.</span> Type the name of your app and select the "Integrate any other application you don't find in the gallery (Non-gallery)" option

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/QhkBvx4Q45jUmT05-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/QhkBvx4Q45jUmT05-image.png)

<span style="color: #a6d100; font-weight: bold; font-size: 18px;">6.</span> Click on **Set up single sign on**

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/e1skoCZPf4zZjV82-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/e1skoCZPf4zZjV82-image.png)

<span style="color: #a6d100; font-weight: bold; font-size: 18px;">7.</span> Click the **SAML** option

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/r5MkyeviYSsOOWc4-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/r5MkyeviYSsOOWc4-image.png)

<span style="color: #a6d100; font-weight: bold; font-size: 18px;">8.</span> Enter the **Basic SAML Configuration** and Save:

- **Identifier**: https://&lt;YOUR-SERVER&gt;/soffid-iam-console
- **Reply URL**: https://&lt;YOUR-SERVER&gt;/soffid/saml/log/post
- **Sign on URL**: https://&lt;YOUR-SERVER&gt;/soffid/
- **Logout URL**: https://&lt;YOUR-SERVER&gt;/soffid/saml/slo/post

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/i7MpGYZxvPsuxic9-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/i7MpGYZxvPsuxic9-image.png)

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/UOno0UL4YCZYlwk7-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/UOno0UL4YCZYlwk7-image.png)

<span style="color: #a6d100; font-weight: bold; font-size: 18px;">9.</span> Configure **Attributes &amp; Claims** and change the attributes and claims to send the mailnickname as the user identifier (nameid)

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/R7CiZlxc1glst8R5-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/R7CiZlxc1glst8R5-image.png)

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/PGVAYF1lyqHFdQzb-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/PGVAYF1lyqHFdQzb-image.png)

<span style="color: #a6d100; font-weight: bold; font-size: 18px;">10.</span> Copy the App Federation Metadata Url

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/gCTtECJIn6LVAtTA-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/gCTtECJIn6LVAtTA-image.png)

<span style="color: #a6d100; font-weight: bold; font-size: 18px;">11.</span> Configure the **External SAML identity Provider** in the Soffid Console Authentication page

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/9RM5fLEWNrbGQAMi-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/9RM5fLEWNrbGQAMi-image.png)

<span style="color: #a6d100; font-weight: bold; font-size: 18px;">12.</span> Optional, **enable any user to login**

[![image.png](https://bookstack.soffid.com/uploads/images/gallery/2024-10/scaled-1680-/1SLfqFQMZAWcPJKc-image.png)](https://bookstack.soffid.com/uploads/images/gallery/2024-10/1SLfqFQMZAWcPJKc-image.png)