---
title: Delegated administration
description: Delegated administration lets you give fine-grained administrative access to specific users, based on a privilege mechanism.
component: pingidm
version: 8.1
page_id: pingidm:auth-guide:delegated-admin
canonical_url: https://docs.pingidentity.com/pingidm/8.1/auth-guide/delegated-admin.html
keywords: ["Delegated Administration", "Privileges"]
section_ids:
  using-privileges: How privileges restrict administrative access
  determining-access-privileges: Determine access privileges
  creating-privileges: Create privileges
  adding_privileges_using_the_admin_ui: Adding privileges using the admin UI
  adding_privileges_using_rest: Adding privileges using REST
  privilege-policies: Policies related to privileges
  getting-privilege-resources: Get privileges on a resource
  using-delegated-admin: Create a delegated administrator
  configure_search_ui_for_delegated_administrators: Configure search UI for delegated administrators
  da-min-filter-length: Minimum filter search length
  da-disable-sort-filter-collections: Disable sort and filter for resource collections
---

# Delegated administration

Delegated administration lets you give fine-grained administrative access to specific users, based on a *privilege* mechanism.

## How privileges restrict administrative access

*Privileges* enable you to grant administrative access to specific endpoints and objects, without needing to grant full administrative access to the server. For example, you might want to allow users with a help desk or support role to update the information of another user, without allowing them to delete user accounts or change the IDM system configuration.

You can use privileges to delegate specific administrative capabilities to non-administrative users, without exposing the admin UI to those users. For example, if a user has been granted a privilege that allows them to access a list of users and user information, they can access this list directly through the end-user UI.

|   |                                                                                                                                                                                                                                                                                                              |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|   | A delegated administrator does not have access to the same methods over REST as a regular administrator. IDM does not allow delegated administrator requests such as POST or DELETE. To add or remove relationships, use PATCH. For examples, refer to [Managed roles](../objects-guide/managed-roles.html). |

The privilege mechanism requires dynamic role calculation, which is disabled by default. To enable it, set the `enableDynamicRoles` property to `true` in your `conf/authentication.json` file, or select Configure > Authentication > Session > Enable Dynamic Roles in the admin UI. For more information about dynamic role calculation, refer to [Dynamic Role Calculation](authentication-and-roles.html#dynamic-role-calculation).

For more information on managing privileges over REST, refer to [Privileges](../rest-api-reference/endpoints/rest-privileges.html).

## Determine access privileges

IDM determines what access a user has as follows:

1. IDM checks the `onRequest` script specified in `router.json` . By default, this script calls `router-authz.js` .

2. If access requirements are not satisfied, IDM then checks for any privileges associated with the user's roles.

`onResponse` and `onFailure` scripts are supported when using privileges. `onFailure` scripts are called only if both the `onRequest` script *and* the privilege filter fail. `onRequest`, `onResponse`, and `onFailure` scripts are not required for the privilege mechanism.

## Create privileges

Privileges are assigned to internal roles. A privilege specifies the following information:

* The service path where users with that internal role have access.

* The methods and actions allowed on that service path.

* The specific attributes of the objects at that service path where access is allowed.

You can use a query filter within a privilege so that the privilege applies to a subset of managed objects only.

The `privileges` property is an array and can contain multiple privileges. Each privilege can contain:

* accessFlags

  A list of attributes within a managed object that you want to give access to. Each attribute has two fields:

  | Field                | Description                                          |
  | -------------------- | ---------------------------------------------------- |
  | `attribute`          | The name of the property you are granting access to. |
  | `readOnly` (boolean) | Determines what level of access is allowed.          |

  * Attributes marked as `"readOnly": true` can be viewed, but not edited.

  * Attributes marked as `"readOnly": false` can be viewed and edited.

  * Attributes that aren't listed in the `accessFlags` array cannot be viewed or edited.

    |   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
    | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    |   | * Privileges aren't automatically aware of changes to the managed object schema. If new properties are added, removed, or made mandatory, you must update any existing privileges to account for these changes. When a new property is added, it has a default permission level of `NONE` in existing privileges, including when the privilege is set to access all attributes.

    * PingIDM applies policy validation when creating or updating a privilege to ensure that all required properties are writable when the `CREATE` permission is assigned. This validation doesn't run when schema changes are made, so you must verify that any existing privileges adhere to defined policies. |

* actions

  A list of the specific actions allowed if the `ACTION` permission has been specified.

  |   |                                            |
  | - | ------------------------------------------ |
  |   | Allowed actions must be explicitly listed. |

* description (optional)

  A description of the privilege.

* filter (optional)

  This property lets you apply a static or dynamic query filter to the privilege, which can be used to limit the scope of what the privilege allows the user to access.

  Static filter example

  To allow a delegated administrator to access information only about users for the `stateProvince` of Washington, include a static filter, such as:

  ```json
  filter : "stateProvince eq \"Washington\""
  ```

  Dynamic filter example

  []()Dynamic filters insert values from the authenticated resource. To allow a delegated administrator to access information only about users in their own `stateProvince`, include a dynamic filter by wrapping the parameter in curly braces:

  ```json
  filter : "stateProvince eq \"{{stateProvince}}\""
  ```

  Users with query filter privileges can't edit the properties specified in the filter in ways that would cause the privilege to lose access to the object. For example, if a user with either of the preceding example privileges attempted to edit another user's `stateProvince` field to a value not matching the query filter, the request would return a `403 Forbidden` error.

  |   |                                                                                                                                                                                                                                                                                                                            |
  | - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | Fields must be *searchable* by PingIDM to be used in a privilege filter. Ensure that the field you are filtering has `"searchable" : true` set in the `repo.jdbc.json` file.Privilege filters are an additional layer of filter to any other query filters you create. Any output must satisfy all filters to be included. |

* name

  The name of the privilege.

* path

  The path to the service that you want to allow members of this privilege to access. For example, `managed/user`.

* permissions

  A list of permissions this privilege allows for the given path. The following permissions are available:

  |          |                                                                                         |
  | -------- | --------------------------------------------------------------------------------------- |
  | `VIEW`   | Allows reading and querying the path, such as viewing and querying managed users.       |
  | `CREATE` | Allows creation at the path, such as creating new managed users.                        |
  | `UPDATE` | Allows updating or patching existing information, such as editing managed user details. |
  | `DELETE` | Allows deletion, such as deleting users from `managed/user`.                            |
  | `ACTION` | Allows users to perform actions at the given path, such as custom scripted actions.     |

  |   |                                                                   |
  | - | ----------------------------------------------------------------- |
  |   | If you use an `ACTION`, there can be no filters on the privilege. |

### Adding privileges using the admin UI

1. From the navigation bar, click Manage > Role.

2. On the Roles page, click the Internal tab, and then click an existing role or create a new role.

3. On the Role Name page, click the Privileges tab.

   PingIDM displays the current privileges for the role.

4. To add privileges, click Add Privileges.

   * In the Add a privilege window, enter information, as necessary, and click Add.

### Adding privileges using REST

The following example creates a new `support` role with privileges that let members view, create, and update information about users, but not delete users:

```
curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--cacert ca-cert.pem \
--request PUT \
--data '{
  "name": "support",
  "description": "Support Role",
  "privileges": [ {
    "name": "support",
    "description": "Support access to user information.",
    "path": "managed/user",
    "permissions": [
      "VIEW", "UPDATE", "CREATE"
    ],
    "actions": [],
    "filter": null,
    "accessFlags": [
      {
        "attribute" : "userName",
        "readOnly" : false
      },
      {
        "attribute" : "mail",
        "readOnly" : false
      },
      {
        "attribute" : "givenName",
        "readOnly" : false
      },
      {
        "attribute" : "sn",
        "readOnly" : false
      },
      {
        "attribute" : "accountStatus",
        "readOnly" : true
      }
    ]
  } ]
}' \
"https://localhost:8443/openidm/internal/role/support"
{
  "_id": "support",
  "_rev": "00000000bfbac2ed",
  "name": "support",
  "description": "Support Role",
  "temporalConstraints": [],
  "condition": null,
  "privileges": [
    {
      "name": "support",
      "description": "Support access to user information.",
      "path": "managed/user",
      "permissions": [
        "VIEW",
        "UPDATE",
        "CREATE"
      ],
      "actions": [],
      "filter": null,
      "accessFlags": [
        {
          "attribute": "userName",
          "readOnly": false
        },
        {
          "attribute": "mail",
          "readOnly": false
        },
        {
          "attribute": "givenName",
          "readOnly": false
        },
        {
          "attribute": "sn",
          "readOnly": false
        },
        {
          "attribute": "accountStatus",
          "readOnly": true
        }
      ]
    }
  ]
}
```

### Policies related to privileges

When creating privileges, IDM runs policies found in `policy.json` and `policy.js`, including the five policies used for validating privileges:

* `valid-accessFlags-object`

  Verifies that `accessFlag` objects are correctly formatted. Only two fields are permitted in an `accessFlag` object: `readOnly`, which must be a boolean; and `attribute`, which must be a string.

* `valid-array-items`

  Verifies that each item in an array contains the properties specified in `policy.json`, and that each of those properties satisfies any specific policies applied to it. By default, this is used to verify that each privilege contains `name`, `path`, `accessFlags`, `actions`, and `permissions` properties, and that the `filter` property is valid if included.

* `valid-permissions`

  Verifies that the permissions set on the privilege are all valid and can be achieved with the `accessFlags` that have been set. It checks:

  * `CREATE` permissions must have write access to all properties required to create a new object.

  * `CREATE` and `UPDATE` permissions must have write access to at least one property.

  * `ACTION` permissions must include a list of allowed actions, with at least one action included.

  * If any attributes have write access, then the privilege must also have either `CREATE` or `UPDATE` permission.

  * All permissions listed must be valid types of permission: `VIEW`, `CREATE`, `UPDATE`, `ACTION`, or `DELETE`. Also, no permissions are repeated.

* `valid-privilege-path`

  Verifies that the `path` specified in the privilege is a valid object with a schema for IDM to reference. Only objects with a schema (such as `managed/user`) can have privileges applied to them.

* `valid-query-filter`

  Verifies that the query filter used to filter privileges is a valid query.

For more information about policies and creating custom policies, refer to [Use policies to validate data](../objects-guide/policies.html).

## Get privileges on a resource

To determine which privileges a user has on a service, you can query the privilege endpoint for a given resource path or object, based on the user you are currently logged in as. For example, if a user is a member of the support role mentioned in the previous example, checking the user's privileges for the `managed/user` resource would look like this:

```
curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--cacert ca-cert.pem \
--request GET \
"https://localhost:8443/openidm/privilege/managed/user"
{
  "VIEW": {
    "allowed": true,
    "properties": [
      "userName",
      "givenName",
      "sn",
      "mail",
      "accountStatus"
    ]
  },
  "CREATE": {
    "allowed": true,
    "properties": [
      "userName",
      "givenName",
      "sn",
      "mail"
    ]
  },
  "UPDATE": {
    "allowed": true,
    "properties": [
      "userName",
      "givenName",
      "sn",
      "mail"
    ]
  },
  "DELETE": {
    "allowed": false
  },
  "ACTION": {
    "allowed": false,
    "actions": []
  }
}
```

In the above example, `accountStatus` is listed as a property for `VIEW`, but not for `CREATE` or `UPDATE`, because the privilege sets this property to be read only. Since both `CREATE` and `UPDATE` need the ability to write to a property, setting `readOnly` to false applies to both permissions. If you need more granular control, split these permissions into two privileges.

In addition to checking privileges for a resource, it is also possible to check privileges for specific objects within a resource, such as `managed/user/scarter`.

## Create a delegated administrator

You can use the IDM REST API to create an `internal/role` with privileges that have object, array, and relationship type attribute access. You can then use that role as a delegated administrator to perform operations on those attributes.

|   |                                                                                                                                                                                                                  |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | If you want to experiment with delegated administrators in [Postman](https://www.postman.com/), download and import this [Postman collection](../_attachments/Delegated-Administration.postman_collection.json). |

Use the following example to create a delegated administrator:

> **Collapse: Step 1. Create a Managed Role**
>
> To ensure a role object exists when roles are requested, you must create a managed role.
>
> ```
> curl \
> --header "X-OpenIDM-Username: openidm-admin" \
> --header "X-OpenIDM-Password: openidm-admin" \
> --header "Content-Type: application/json" \
> --header "If-None-Match: *" \
> --request PUT \
> --data '{
>   "name": "testManagedRole",
>   "description": "a managed role for test"
> }' \
> "http://localhost:8080/openidm/managed/role/testManagedRole"
> {
>   "_id": "testManagedRole",
>   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-181",
>   "name": "testManagedRole",
>   "description": "a managed role for test"
> }
> ```

> **Collapse: Step 2. Create a  User**
>
> ```
> curl \
> --header "X-OpenIDM-Username: openidm-admin" \
> --header "X-OpenIDM-Password: openidm-admin" \
> --header "Content-Type: application/json" \
> --request POST \
> --data '{
>   "userName": "psmith",
>   "sn": "Smith",
>   "givenName": "Patricia",
>   "mail": "psmith@example.com",
>   "telephoneNumber": "082082082",
>   "password": "Passw0rd"
> }' \
> "http://localhost:8080/openidm/managed/user/?_action=create"
> {
>   "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
>   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
>   "userName": "psmith",
>   "sn": "Smith",
>   "givenName": "Patricia",
>   "mail": "psmith@example.com",
>   "telephoneNumber": "082082082",
>   "accountStatus": "active",
>   "effectiveRoles": [],
>   "memberOfOrgIDs": [],
>   "effectiveAssignments": []
> }
> ```

> **Collapse: Step 3. Create Additional Users**
>
> In this step, you'll create two users with the following attributes:
>
> * `preferences`
>
> * `manager`
>
> * `roles`
>
> ```
> curl \
> --header "X-OpenIDM-Username: openidm-admin" \
> --header "X-OpenIDM-Password: openidm-admin" \
> --header "Content-Type: application/json" \
> --request POST \
> --data '{
>   "userName": "scarter",
>   "sn": "Carter",
>   "givenName": "Steven",
>   "mail": "scarter@example.com",
>   "telephoneNumber": "082082082",
>   "password": "Passw0rd",
>   "preferences": {
>     "updates": true,
>     "marketing": false
>   },
>   "manager": {"_ref": "managed/user/9cae97b7-3bf3-4107-96d5-39ad153629db"},
>   "roles": [{"_ref": "managed/role/testManagedRole"}]
> }' \
> "http://localhost:8080/openidm/managed/user/?_action=create"
> {
>   "_id": "917bc052-ef39-4add-ae05-0a278e2de9c0",
>   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1238",
>   "userName": "scarter",
>   "sn": "Carter",
>   "givenName": "Steven",
>   "mail": "scarter@example.com",
>   "telephoneNumber": "082082082",
>   "preferences": {
>     "updates": true,
>     "marketing": false
>   },
>   "accountStatus": "active",
>   "effectiveRoles": [
>     {
>       "_refResourceCollection": "managed/role",
>       "_refResourceId": "testManagedRole",
>       "_ref": "managed/role/testManagedRole"
>     }
>   ],
>   "memberOfOrgIDs": [],
>   "effectiveAssignments": []
> }
> ```
>
> ```
> curl \
> --header "X-OpenIDM-Username: openidm-admin" \
> --header "X-OpenIDM-Password: openidm-admin" \
> --header "Content-Type: application/json" \
> --request POST \
> --data '{
>   "userName": "jdoe",
>   "sn": "Doe",
>   "givenName": "John",
>   "mail": "jdoe@example.com",
>   "telephoneNumber": "082082082",
>   "password": "Passw0rd",
>   "preferences": {
>     "updates": true,
>     "marketing": false
>   },
>   "manager": {"_ref": "managed/user/9cae97b7-3bf3-4107-96d5-39ad153629db"},
>   "roles": [{"_ref": "managed/role/testManagedRole"}]
> }' \
> "http://localhost:8080/openidm/managed/user/?_action=create"
> {
>   "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
>   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1267",
>   "userName": "jdoe",
>   "sn": "Doe",
>   "givenName": "John",
>   "mail": "jdoe@example.com",
>   "telephoneNumber": "082082082",
>   "preferences": {
>     "updates": true,
>     "marketing": false
>   },
>   "accountStatus": "active",
>   "effectiveRoles": [
>     {
>       "_refResourceCollection": "managed/role",
>       "_refResourceId": "testManagedRole",
>       "_ref": "managed/role/testManagedRole"
>     }
>   ],
>   "memberOfOrgIDs": [],
>   "effectiveAssignments": []
> }
> ```

> **Collapse: Step 4. Create Another User**
>
> You will delegate an internal/role with privileges to this user in the next step:
>
> ```
> curl \
> --header "X-OpenIDM-Username: openidm-admin" \
> --header "X-OpenIDM-Password: openidm-admin" \
> --header "Content-Type: application/json" \
> --request POST \
> --data '{
>   "userName": "bjensen",
>   "sn": "Jensen",
>   "givenName": "Barbara",
>   "mail": "bjensen@example.com",
>   "telephoneNumber": "082082082",
>   "password": "Passw0rd"
> }' \
> "http://localhost:8080/openidm/managed/user/?_action=create"
> {
>   "_id": "2d726b2a-3324-44b3-ba40-91b154d4f51e",
>   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1291",
>   "userName": "bjensen",
>   "sn": "Jensen",
>   "givenName": "Barbara",
>   "mail": "bjensen@example.com",
>   "telephoneNumber": "082082082",
>   "accountStatus": "active",
>   "effectiveRoles": [],
>   "memberOfOrgIDs": [],
>   "effectiveAssignments": []
> }
> ```

> **Collapse: Step 5. Create an**
>
> This role will have the following privileges:
>
> * A `managed/user` privilege with accessFlags attributes that are of types: "String" , "boolean" , and "number" ; but also for:
>
>   * An object type that is not a relationship (`preferences`).
>
>   * An object type that is a relationship (`manager`).
>
>   * Array types that are relationships (`roles`, `authzRoles`, `reports`).
>
> * A `managed/role` privilege for viewing details of the "roles" property of a managed user.
>
> * An `internal/role` privilege for viewing the details of the "authzRoles" property of a managed user.
>
> |   |                                                                                                                                                                                                                                                                                                                                                                                                              |
> | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
> |   | You can populate the privilege `filter` field to apply a finer level of permissions for what a delegated administrator can access or do with certain objects. The `filter` field is omitted in this example to allow all.For properties that are *not* relationships, such as `preferences`, you can't specify finer-grained permissions. For example, you can't set permissions on `preferences/marketing`. |
>
> ```
> curl \
> --header "X-OpenIDM-Username: openidm-admin" \
> --header "X-OpenIDM-Password: openidm-admin" \
> --header "Content-Type: application/json" \
> --header "If-None-Match: *" \
> --request PUT \
> --data '{
>   "name": "internal_role_with_object_array_and_relationship_privileges",
>   "description": "an internal role that has privileges for object & array types and relationships",
>   "privileges": [
>     {
>       "name": "managed_user_privilege",
>       "path": "managed/user",
>       "permissions": [
>         "VIEW",
>         "CREATE",
>         "UPDATE",
>         "DELETE"
>       ],
>       "actions": [],
>       "accessFlags": [
>         {
>           "attribute": "userName",
>           "readOnly": false
>         },
>         {
>           "attribute": "password",
>           "readOnly": false
>         },
>         {
>           "attribute": "givenName",
>           "readOnly": false
>         },
>         {
>           "attribute": "sn",
>           "readOnly": false
>         },
>         {
>           "attribute": "mail",
>           "readOnly": false
>         },
>         {
>           "attribute": "description",
>           "readOnly": false
>         },
>         {
>           "attribute": "accountStatus",
>           "readOnly": false
>         },
>         {
>           "attribute": "telephoneNumber",
>           "readOnly": false
>         },
>         {
>           "attribute": "postalAddress",
>           "readOnly": false
>         },
>         {
>           "attribute": "city",
>           "readOnly": false
>         },
>         {
>           "attribute": "postalCode",
>           "readOnly": false
>         },
>         {
>           "attribute": "country",
>           "readOnly": false
>         },
>         {
>           "attribute": "stateProvince",
>           "readOnly": false
>         },
>         {
>           "attribute": "preferences",
>           "readOnly": false
>         },
>         {
>           "attribute": "roles",
>           "readOnly": false
>         },
>         {
>           "attribute": "manager",
>           "readOnly": false
>         },
>         {
>           "attribute": "authzRoles",
>           "readOnly": false
>         },
>         {
>           "attribute": "reports",
>           "readOnly": false
>         }
>       ]
>     },
>     {
>       "name": "managed_role_privilege",
>       "path": "managed/role",
>       "permissions": [
>         "VIEW"
>       ],
>       "actions": [],
>       "accessFlags": [
>         {
>           "attribute": "name",
>           "readOnly": true
>         },
>         {
>           "attribute": "description",
>           "readOnly": true
>         }
>       ]
>     },
>     {
>       "name": "internal_role_privilege",
>       "path": "internal/role",
>       "permissions": [
>         "VIEW"
>       ],
>       "actions": [],
>       "accessFlags": [
>         {
>           "attribute": "name",
>           "readOnly": true
>         },
>         {
>           "attribute": "description",
>           "readOnly": true
>         },
>         {
>           "attribute": "authzMembers",
>           "readOnly": true
>         }
>       ]
>     }
>   ]
> }' \
> "http://localhost:8080/openidm/internal/role/testInternalRole"
> {
>   "_id": "testInternalRole",
>   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-300",
>   "name": "internal_role_with_object_array_and_relationship_privileges",
>   "description": "an internal role that has privileges for object & array types and relationships",
>   "temporalConstraints": [],
>   "condition": null,
>   "privileges": [
>     {
>       "name": "managed_user_privilege",
>       "path": "managed/user",
>       "permissions": [
>         "VIEW",
>         "CREATE",
>         "UPDATE",
>         "DELETE"
>       ],
>       "actions": [],
>       "accessFlags": [
>         {
>           "attribute": "userName",
>           "readOnly": false
>         },
>         {
>           "attribute": "password",
>           "readOnly": false
>         },
>         {
>           "attribute": "givenName",
>           "readOnly": false
>         },
>         {
>           "attribute": "sn",
>           "readOnly": false
>         },
>         {
>           "attribute": "mail",
>           "readOnly": false
>         },
>         {
>           "attribute": "description",
>           "readOnly": false
>         },
>         {
>           "attribute": "accountStatus",
>           "readOnly": false
>         },
>         {
>           "attribute": "telephoneNumber",
>           "readOnly": false
>         },
>         {
>           "attribute": "postalAddress",
>           "readOnly": false
>         },
>         {
>           "attribute": "city",
>           "readOnly": false
>         },
>         {
>           "attribute": "postalCode",
>           "readOnly": false
>         },
>         {
>           "attribute": "country",
>           "readOnly": false
>         },
>         {
>           "attribute": "stateProvince",
>           "readOnly": false
>         },
>         {
>           "attribute": "preferences",
>           "readOnly": false
>         },
>         {
>           "attribute": "roles",
>           "readOnly": false
>         },
>         {
>           "attribute": "manager",
>           "readOnly": false
>         },
>         {
>           "attribute": "authzRoles",
>           "readOnly": false
>         },
>         {
>           "attribute": "reports",
>           "readOnly": false
>         }
>       ]
>     },
>     {
>       "name": "managed_role_privilege",
>       "path": "managed/role",
>       "permissions": [
>         "VIEW"
>       ],
>       "actions": [],
>       "accessFlags": [
>         {
>           "attribute": "name",
>           "readOnly": true
>         },
>         {
>           "attribute": "description",
>           "readOnly": true
>         }
>       ]
>     },
>     {
>       "name": "internal_role_privilege",
>       "path": "internal/role",
>       "permissions": [
>         "VIEW"
>       ],
>       "actions": [],
>       "accessFlags": [
>         {
>           "attribute": "name",
>           "readOnly": true
>         },
>         {
>           "attribute": "description",
>           "readOnly": true
>         },
>         {
>           "attribute": "authzMembers",
>           "readOnly": true
>         }
>       ]
>     }
>   ]
> }
> ```

> **Collapse: Step 6. Create the Relationship Between User and**
>
> In this step, assign the internal/role from step 5 to the user created in step 4 by creating a relationship:
>
> ```
> curl \
> --header "X-OpenIDM-Username: openidm-admin" \
> --header "X-OpenIDM-Password: openidm-admin" \
> --header "Content-Type: application/json" \
> --request POST \
> --data '{
>   "_ref": "managed/user/2d726b2a-3324-44b3-ba40-91b154d4f51e",
>   "_refProperties": {}
> }' \
> "http://localhost:8080/openidm/internal/role/testInternalRole/authzMembers?_action=create"
> {
>   "_id": "2e21f423-f934-4ed7-b6fd-9883b69d52d8",
>   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1304",
>   "_ref": "managed/user/2d726b2a-3324-44b3-ba40-91b154d4f51e",
>   "_refResourceCollection": "managed/user",
>   "_refResourceId": "2d726b2a-3324-44b3-ba40-91b154d4f51e",
>   "_refProperties": {
>     "_id": "2e21f423-f934-4ed7-b6fd-9883b69d52d8",
>     "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1304"
>   }
> }
> ```

> **Collapse: Step 7. Perform Operations as a Delegated Administrator**
>
> You can now perform operations as a delegated administrator, such as:
>
> > **Collapse: Query All Users**
> >
> > The query results display all users' properties that are allowed by the privileges:
> >
> > ```
> > curl \
> > --header "X-OpenIDM-Username: bjensen" \
> > --header "X-OpenIDM-Password: Passw0rd" \
> > --request GET \
> > "http://localhost:8080/openidm/managed/user?_queryFilter=true&_pageSize=100&_fields=*,*_ref/*"
> > {
> >   "result": [
> >     {
> >       "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
> >       "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
> >       "userName": "psmith",
> >       "sn": "Smith",
> >       "givenName": "Patricia",
> >       "mail": "psmith@example.com",
> >       "telephoneNumber": "082082082",
> >       "accountStatus": "active",
> >       "reports": [
> >         {
> >           "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1267",
> >           "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
> >           "userName": "jdoe",
> >           "sn": "Doe",
> >           "givenName": "John",
> >           "mail": "jdoe@example.com",
> >           "telephoneNumber": "082082082",
> >           "preferences": {
> >             "updates": true,
> >             "marketing": false
> >           },
> >           "accountStatus": "active",
> >           "_ref": "managed/user/aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
> >           "_refResourceCollection": "managed/user",
> >           "_refResourceId": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
> >           "_refProperties": {
> >             "_id": "e01a922b-a60d-46c2-b6bc-2b821c1580b4",
> >             "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1262"
> >           }
> >         },
> >         {
> >           "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1238",
> >           "_id": "917bc052-ef39-4add-ae05-0a278e2de9c0",
> >           "userName": "scarter",
> >           "sn": "Carter",
> >           "givenName": "Steven",
> >           "mail": "scarter@example.com",
> >           "telephoneNumber": "082082082",
> >           "preferences": {
> >             "updates": true,
> >             "marketing": false
> >           },
> >           "accountStatus": "active",
> >           "_ref": "managed/user/917bc052-ef39-4add-ae05-0a278e2de9c0",
> >           "_refResourceCollection": "managed/user",
> >           "_refResourceId": "917bc052-ef39-4add-ae05-0a278e2de9c0",
> >           "_refProperties": {
> >             "_id": "5bc2c633-8ae1-4ea2-adf6-8aa7ce5f8e70",
> >             "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1233"
> >           }
> >         }
> >       ],
> >       "manager": null,
> >       "roles": [],
> >       "authzRoles": []
> >     },
> >     {
> >       "_id": "917bc052-ef39-4add-ae05-0a278e2de9c0",
> >       "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1238",
> >       "userName": "scarter",
> >       "sn": "Carter",
> >       "givenName": "Steven",
> >       "mail": "scarter@example.com",
> >       "telephoneNumber": "082082082",
> >       "preferences": {
> >         "updates": true,
> >         "marketing": false
> >       },
> >       "accountStatus": "active",
> >       "reports": [],
> >       "manager": {
> >         "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
> >         "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
> >         "userName": "psmith",
> >         "sn": "Smith",
> >         "givenName": "Patricia",
> >         "mail": "psmith@example.com",
> >         "telephoneNumber": "082082082",
> >         "accountStatus": "active",
> >         "_ref": "managed/user/9cae97b7-3bf3-4107-96d5-39ad153629db",
> >         "_refResourceCollection": "managed/user",
> >         "_refResourceId": "9cae97b7-3bf3-4107-96d5-39ad153629db",
> >         "_refProperties": {
> >           "_id": "5bc2c633-8ae1-4ea2-adf6-8aa7ce5f8e70",
> >           "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1233"
> >         }
> >       },
> >       "roles": [
> >         {
> >           "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-181",
> >           "_id": "testManagedRole",
> >           "name": "testManagedRole",
> >           "description": "a managed role for test",
> >           "_ref": "managed/role/testManagedRole",
> >           "_refResourceCollection": "managed/role",
> >           "_refResourceId": "testManagedRole",
> >           "_refProperties": {
> >             "_id": "a33e2de0-83ff-481c-b8a7-8ffbc02d135c",
> >             "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1235"
> >           }
> >         }
> >       ],
> >       "authzRoles": []
> >     },
> >     {
> >       "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
> >       "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1267",
> >       "userName": "jdoe",
> >       "sn": "Doe",
> >       "givenName": "John",
> >       "mail": "jdoe@example.com",
> >       "telephoneNumber": "082082082",
> >       "preferences": {
> >         "updates": true,
> >         "marketing": false
> >       },
> >       "accountStatus": "active",
> >       "reports": [],
> >       "manager": {
> >         "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
> >         "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
> >         "userName": "psmith",
> >         "sn": "Smith",
> >         "givenName": "Patricia",
> >         "mail": "psmith@example.com",
> >         "telephoneNumber": "082082082",
> >         "accountStatus": "active",
> >         "_ref": "managed/user/9cae97b7-3bf3-4107-96d5-39ad153629db",
> >         "_refResourceCollection": "managed/user",
> >         "_refResourceId": "9cae97b7-3bf3-4107-96d5-39ad153629db",
> >         "_refProperties": {
> >           "_id": "e01a922b-a60d-46c2-b6bc-2b821c1580b4",
> >           "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1262"
> >         }
> >       },
> >       "roles": [
> >         {
> >           "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-181",
> >           "_id": "testManagedRole",
> >           "name": "testManagedRole",
> >           "description": "a managed role for test",
> >           "_ref": "managed/role/testManagedRole",
> >           "_refResourceCollection": "managed/role",
> >           "_refResourceId": "testManagedRole",
> >           "_refProperties": {
> >             "_id": "1528ab24-3ec3-4113-ac3f-26cc71a2d678",
> >             "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1264"
> >           }
> >         }
> >       ],
> >       "authzRoles": []
> >     },
> >     {
> >       "_id": "2d726b2a-3324-44b3-ba40-91b154d4f51e",
> >       "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1305",
> >       "userName": "bjensen",
> >       "sn": "Jensen",
> >       "givenName": "Barbara",
> >       "mail": "bjensen@example.com",
> >       "telephoneNumber": "082082082",
> >       "accountStatus": "active",
> >       "reports": [],
> >       "manager": null,
> >       "roles": [],
> >       "authzRoles": [
> >         {
> >           "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-300",
> >           "_id": "testInternalRole",
> >           "name": "internal_role_with_object_array_and_relationship_privileges",
> >           "description": "an internal role that has privileges for object & array types and relationships",
> >           "_ref": "internal/role/testInternalRole",
> >           "_refResourceCollection": "internal/role",
> >           "_refResourceId": "testInternalRole",
> >           "_refProperties": {
> >             "_id": "2e21f423-f934-4ed7-b6fd-9883b69d52d8",
> >             "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1304"
> >           }
> >         }
> >       ]
> >     }
> >   ],
> >   "resultCount": 4,
> >   "pagedResultsCookie": null,
> >   "totalPagedResultsPolicy": "NONE",
> >   "totalPagedResults": -1,
> >   "remainingPagedResults": -1
> > }
> > ```
>
> > **Collapse: Read a Specified User's Preferences Object**
> >
> > ```
> > curl \
> > --header "X-OpenIDM-Username: bjensen" \
> > --header "X-OpenIDM-Password: Passw0rd" \
> > --request GET \
> > "http://localhost:8080/openidm/managed/user/aca0042c-9f4c-4ad5-8cf7-aca0adeb3470?_fields=preferences"
> > {
> >   "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
> >   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1267",
> >   "preferences": {
> >     "updates": true,
> >     "marketing": false
> >   }
> > }
> > ```
>
> > **Collapse: Query a Specified User's Roles**
> >
> > ```
> > curl \
> > --header "X-OpenIDM-Username: bjensen" \
> > --header "X-OpenIDM-Password: Passw0rd" \
> > --request GET \
> > "http://localhost:8080/openidm/managed/user/917bc052-ef39-4add-ae05-0a278e2de9c0/roles?_queryFilter=true&_fields=*"
> > {
> >   "result": [
> >     {
> >       "_id": "a33e2de0-83ff-481c-b8a7-8ffbc02d135c",
> >       "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1235",
> >       "name": "testManagedRole",
> >       "description": "a managed role for test",
> >       "_refResourceCollection": "managed/role",
> >       "_refResourceId": "testManagedRole",
> >       "_refResourceRev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-181",
> >       "_ref": "managed/role/testManagedRole",
> >       "_refProperties": {
> >         "_id": "a33e2de0-83ff-481c-b8a7-8ffbc02d135c",
> >         "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1235"
> >       }
> >     }
> >   ],
> >   "resultCount": 1,
> >   "pagedResultsCookie": null,
> >   "totalPagedResultsPolicy": "NONE",
> >   "totalPagedResults": -1,
> >   "remainingPagedResults": -1
> > }
> > ```
>
> > **Collapse: Read a Specified User's Manager**
> >
> > ```
> > curl \
> > --header "X-OpenIDM-Username: bjensen" \
> > --header "X-OpenIDM-Password: Passw0rd" \
> > --request GET \
> > "http://localhost:8080/openidm/managed/user/917bc052-ef39-4add-ae05-0a278e2de9c0/manager?_fields=*"
> > {
> >   "_id": "5bc2c633-8ae1-4ea2-adf6-8aa7ce5f8e70",
> >   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1233",
> >   "userName": "psmith",
> >   "sn": "Smith",
> >   "givenName": "Patricia",
> >   "mail": "psmith@example.com",
> >   "telephoneNumber": "082082082",
> >   "accountStatus": "active",
> >   "_refResourceCollection": "managed/user",
> >   "_refResourceId": "9cae97b7-3bf3-4107-96d5-39ad153629db",
> >   "_refResourceRev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
> >   "_ref": "managed/user/9cae97b7-3bf3-4107-96d5-39ad153629db",
> >   "_refProperties": {
> >     "_id": "5bc2c633-8ae1-4ea2-adf6-8aa7ce5f8e70",
> >     "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1233"
> >   }
> > }
> > ```
>
> > **Collapse: Update a Specified User's Reports**
> >
> > ```
> > curl \
> > --header "X-OpenIDM-Username: bjensen" \
> > --header "X-OpenIDM-Password: Passw0rd" \
> > --header "Content-Type: application/json" \
> > --request PATCH \
> > --data '[ {
> >    "operation" : "replace",
> >    "field" : "reports",
> >    "value" : [{"_ref" : "managed/user/917bc052-ef39-4add-ae05-0a278e2de9c0"}]
> > } ]' \
> > "http://localhost:8080/openidm/managed/user/9cae97b7-3bf3-4107-96d5-39ad153629db"
> > {
> >   "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
> >   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
> >   "userName": "psmith",
> >   "sn": "Smith",
> >   "givenName": "Patricia",
> >   "mail": "psmith@example.com",
> >   "telephoneNumber": "082082082",
> >   "accountStatus": "active"
> > }
> > ```
>
> > **Collapse: Assign a Specified User's Manager**
> >
> > ```
> > curl \
> > --header "X-OpenIDM-Username: bjensen" \
> > --header "X-OpenIDM-Password: Passw0rd" \
> > --header "Content-Type: application/json" \
> > --request PATCH \
> > --data '[
> >   {
> >     "operation": "add",
> >     "field": "manager",
> >     "value": {"_ref" : "managed/user/9cae97b7-3bf3-4107-96d5-39ad153629db"}
> >   }
> > ]' \
> > "http://localhost:8080/openidm/managed/user/aca0042c-9f4c-4ad5-8cf7-aca0adeb3470"
> > {
> >   "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
> >   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1517",
> >   "userName": "jdoe",
> >   "sn": "Doe",
> >   "givenName": "John",
> >   "mail": "jdoe@example.com",
> >   "telephoneNumber": "082082082",
> >   "preferences": {
> >     "updates": true,
> >     "marketing": false
> >   },
> >   "accountStatus": "active"
> > }
> > ```
>
> > **Collapse: Remove a Specified User's Manager**
> >
> > ```
> > curl \
> > --header "X-OpenIDM-Username: bjensen" \
> > --header "X-OpenIDM-Password: Passw0rd" \
> > --header "Content-Type: application/json" \
> > --request PATCH \
> > --data '[
> >   {
> >      "operation": "remove",
> >      "field": "manager"
> >   }
> > ]' \
> > "http://localhost:8080/openidm/managed/user/aca0042c-9f4c-4ad5-8cf7-aca0adeb3470"
> > {
> >   "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
> >   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1545",
> >   "userName": "jdoe",
> >   "sn": "Doe",
> >   "givenName": "John",
> >   "mail": "jdoe@example.com",
> >   "telephoneNumber": "082082082",
> >   "preferences": {
> >     "updates": true,
> >     "marketing": false
> >   },
> >   "accountStatus": "active"
> > }
> > ```
>
> > **Collapse: Update a Specified User's Manager**
> >
> > ```
> > curl \
> > --header "X-OpenIDM-Username: bjensen" \
> > --header "X-OpenIDM-Password: Passw0rd" \
> > --header "Content-Type: application/json" \
> > --request PATCH \
> > --data '[
> >   {
> >     "operation": "replace",
> >     "field": "manager",
> >     "value": {"_ref" : "managed/user/aca0042c-9f4c-4ad5-8cf7-aca0adeb3470"}
> >   }
> > ]' \
> > "http://localhost:8080/openidm/managed/user/917bc052-ef39-4add-ae05-0a278e2de9c0"
> > {
> >   "_id": "917bc052-ef39-4add-ae05-0a278e2de9c0",
> >   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1565",
> >   "userName": "scarter",
> >   "sn": "Carter",
> >   "givenName": "Steven",
> >   "mail": "scarter@example.com",
> >   "telephoneNumber": "082082082",
> >   "preferences": {
> >     "updates": true,
> >     "marketing": false
> >   },
> >   "accountStatus": "active"
> > }
> > ```
>
> > **Collapse: Delete a Specified User**
> >
> > ```
> > curl \
> > --header "X-OpenIDM-Username: bjensen" \
> > --header "X-OpenIDM-Password: Passw0rd" \
> > --header "Content-Type: application/json" \
> > --request DELETE \
> > "http://localhost:8080/openidm/managed/user/9cae97b7-3bf3-4107-96d5-39ad153629db"
> > {
> >   "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
> >   "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
> >   "userName": "psmith",
> >   "sn": "Smith",
> >   "givenName": "Patricia",
> >   "mail": "psmith@example.com",
> >   "telephoneNumber": "082082082",
> >   "accountStatus": "active"
> > }
> > ```
>
> > **Collapse: Create a User**
> >
> > * Using POST:
> >
> >   ```
> >   curl \
> >   --header "Content-Type: application/json" \
> >   --header "X-OpenIDM-Username: bjensen" \
> >   --header "X-OpenIDM-Password: Passw0rd" \
> >   --request POST \
> >   --data '{
> >     "userName": "psmith",
> >     "sn": "Smith",
> >     "givenName": "Patricia",
> >     "mail": "psmith@example.com",
> >     "telephoneNumber": "082082082",
> >     "password": "Passw0rd"
> >   }' \
> >   "http://localhost:8080/openidm/managed/user"
> >   {
> >     "_id": "1a20930b-cf61-4b43-a730-9f73af9147cb",
> >     "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-571",
> >     "userName": "psmith",
> >     "sn": "Smith",
> >     "givenName": "Patricia",
> >     "mail": "psmith@example.com",
> >     "telephoneNumber": "082082082",
> >     "accountStatus": "active"
> >   }
> >   ```
> >
> > * Using PUT:
> >
> >   ```
> >   curl \
> >   --header "Content-Type: application/json" \
> >   --header "X-OpenIDM-Username: bjensen" \
> >   --header "X-OpenIDM-Password: Passw0rd" \
> >   --header "If-None-Match: *" \
> >   --request PUT \
> >   --data '{
> >     "userName": "psmith",
> >     "sn": "Smith",
> >     "givenName": "Patricia",
> >     "mail": "psmith@example.com",
> >     "telephoneNumber": "082082082",
> >     "password": "Passw0rd"
> >   }' \
> >   "http://localhost:8080/openidm/managed/user/psmith"
> >   {
> >     "_id": "psmith",
> >     "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-590",
> >     "userName": "psmith",
> >     "sn": "Smith",
> >     "givenName": "Patricia",
> >     "mail": "psmith@example.com",
> >     "telephoneNumber": "082082082",
> >     "accountStatus": "active"
> >   }
> >   ```
> >
> > |   |                                                                                                                                                                                                                          |
> > | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
> > |   | Delegated administration may not work as expected when using DS as your repository if `_id` is something *other* than a UUID. JDBC repositories may use other forms for `_id`, though using a UUID is still recommended. |
>
> |   |                                                                                                         |
> | - | ------------------------------------------------------------------------------------------------------- |
> |   | For more examples, including working with filters, refer to the [Postman collection](#da-postman-coll). |

|   |                                                                                                                                                                                    |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | All patches are done with a PATCH request. Delegated administrator operations do not currently support using POST actions for patch requests (POST `_action=patch` will not work). |

|   |                                                                                                             |
| - | ----------------------------------------------------------------------------------------------------------- |
|   | This process only applies to managed users. It will not work for internal users, as they cannot have roles. |

## Configure search UI for delegated administrators

|   |                                                                                                                           |
| - | ------------------------------------------------------------------------------------------------------------------------- |
|   | The end-user UI is not bundled with PingIDM. Learn more in [Install the end-user UI](../setup-guide/idm-enduser-ui.html). |

The IDM end-user UI support for delegated administration includes a search feature to filter a list of results. To keep search performant when working with large lists, you can configure the following constraints:

* [Set a minimum filter length](#da-min-filter-length).

* [Disable the ability to filter and sort](#da-disable-sort-filter-collections).

|   |                                                      |
| - | ---------------------------------------------------- |
|   | These settings only affect delegated administrators. |

### Minimum filter search length

You can set `minimumUIFilterLength` in `conf/ui-configuration.json` to define when results start filtering:

```json
"platformSettings" : {
    "managedObjectsSettings" : {
        "user" : {
            "minimumUIFilterLength" : 3
        }
    }
}
```

This setting prevents the UI from filtering until the user has typed at least three characters. `minimumUIFilterLength` can be used with any managed object, for example:

```json
"platformSettings" : {
    "managedObjectsSettings" : {
        "user" : {
            "minimumUIFilterLength" : 3
        },
        "role" : {
            "minimumUIFilterLength" : 2
        }
    }
}
```

### Disable sort and filter for resource collections

A *resource collection* is a set of objects that have a relationship with one or more other objects. For example:

* All users with a particular role assignment.

* All users who are members of an organization.

You can disable the ability to sort and filter resource collections using `"disableRelationshipSortAndSearch" : true` in `conf/ui-configuration.json`. This can be beneficial when working with *very* large lists. For example:

```json
"platformSettings" : {
    "managedObjectsSettings" : {
        "user" : {
            "disableRelationshipSortAndSearch" : true,
            "minimumUIFilterLength" : 3
        }
    }
}
```
