MODUSERSKC-4 Document process of user creation

MODUSERSKC-4 - Getting issue details... STATUS


In this guide, we will learn how to create a user, search for capabilities/capability-sets according to the relevant folio permissions, and create roles with the necessary capabilities and assign them to the user.  Please note that these operations will eventually all be possible via the Folio UI.

Please note that these operations will eventually all be possible via the Folio UI.

Preparations

This guide uses the command line, cURL utility, and jq (a lightweight and flexible command-line JSON processor).

For convenience, save the base URL of your environment as a variable. For instance, if you're working with a local environment, you'll use:

baseUrl="http://gateway"
adminUsername="folio"
adminPassword="folio"
tenant="diku"

Disclaimer: Please replace variables with your actual data. The data you use should be according to your current environment setup.

Getting Access Token

curl -c - -L -X POST "${baseUrl}/authn/login-with-expiry" \
-H "x-okapi-tenant: ${tenant}" \
-H 'Content-Type: application/json' \
-d '{
  "username": "'"${adminUsername}"'",
  "password": "'"${adminPassword}"'"
}' | grep folioAccessToken

Once you've got your access token, save it as a variable.

token="access_token_from_cookies_here"

Remember, all the operations hence should employ this variable with token.

Creating a User

To create call perform the following request:

curl -L -X POST "${baseUrl}/users-keycloak/users" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}" \
-H 'Content-Type: application/json' \
-d '{
  "username": "johndoe",
  "type": "staff",
  "personal": {
    "firstName": "John",
    "lastName": "Doe",
    "email": "johndoe@foo.bar"
  }
}' | jq .

Save user ID.

Create user password

Once you have created a user, you can assign a password to it using the username. Here's a command example on how you can do this:

curl -L -X POST "${baseUrl}/authn/credentials" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}" \
-H 'Content-Type: application/json' \
-d '{
  "username": "johndoe",
  "password": "secret_password"
}'

Note: Make sure to store your username and password, as they will be used for the user to log in to the system.

Capabilities

Understanding Capabilities

Before we proceed with searching and assigning capabilities, it's important to understand what capabilities are.

There are two concepts: capability and capability-set. A capability is like an atomic permission. It is the smallest indivisible unit of power that can be assigned.

On the other hand, a capability-set is a collection of multiple capabilities, which simplifies the management of capabilities. Capabilities and capability-sets can be assigned to a role and then assigned to a user. They can also be assigned directly to a user. It's also crucial to understand that these capabilities and capability-sets are created and managed by the system itself.

Unlike permission-sets in Folio, a capability-set cannot contain other capability-sets. It can only contain capabilities.

Searching capabilities/capability-sets

To search for capability-sets, use the following request:

curl -X GET "${baseUrl}/capability-sets" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}"  | jq .

Let's say we want to find all capability-sets related to Inventory. We can achieve it using this request:

curl -X GET "${baseUrl}/capability-sets?query=resource==Inventory" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}"  | jq .

 Capability-sets response under the spoiler:

 capability-sets response...
{
  "capabilitySets": [
    {
      "id": "e54e1b37-6f11-422e-b7ed-70339f3d4dff",
      "name": "inventory.manage",
      "description": "Entire set of permissions needed to use the inventory",
      "resource": "Inventory",
      "action": "manage",
      "applicationId": "app-platform-complete-0.0.2",
      "type": "data",
      "capabilities": [
        "cc6e7b55-21e6-4884-bfb2-a4a197f0178b",
        "b3cc7e08-3f71-4b69-9a85-292d69231e32",
        "1cdf6b65-e387-4437-ba42-1c77ac17d2b7",
        "040cd85f-cde3-402e-a9d6-b1ebbedbda25",
        "f9e0a12f-82c0-4126-bdd1-08cbae086a2a",
        "7b124969-ccf9-480c-ab59-57c8279211db",
        "f11b171f-f877-4c57-90fa-c629e57c6237",
        "d835f21c-7424-4cb9-b4e9-12935673e763",
        "36812269-32b2-4bb9-9a5b-4937edcf3aae",
        "cf29fafc-7f3e-4fd9-8387-6ce53ba7c3fc",
        "18e85b91-8687-42a7-ade6-468d37f7fe42",
        "fa28c961-d662-42ae-93fc-82bd1bf38fd4",
        "623af1be-f8fc-4911-aa44-bfc85c68db41",
        "b4c884b7-376f-49f9-b129-58b9b947d5d5",
        "baa027a0-40b5-4a17-99bc-8cb6dad12f25",
        "a47a5f46-f95a-451c-9a90-7f3e5eeeb645",
        "5934251e-c4c5-4008-9bd2-7ac3a9a87fbe",
        "e357318d-c907-4cf2-9f22-3ca7744ec928",
        "f5437ca8-4187-459b-85ea-187c7e1ca350",
        "fb131797-a879-4caa-8d9c-0a6a753b4515",
        "843de70c-8eda-49f6-8c31-abf6c894fa81",
        "e7972762-5c37-4143-a937-42bfb9952b08"
      ],
      "metadata": {
        "createdDate": "2023-11-30T09:46:45.065+00:00"
      }
    }
  ],
  "totalRecords": 1
}

Note: The example above illustrates how you can utilize the query  parameter in the request for searching records, a prevalent approach in Folio. Refine your search by adjusting the query parameter to match your specific needs.

To search capabilities, use the following request:

curl -X GET "${baseUrl}/capabilities?query=permission==accounts.cancel.post" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}"  | jq .

Response example under the spoiler:


 capabilities response...
{
  "capabilities": [
    {
      "id": "db3d9947-f28e-4e0d-b090-63f9725734ef",
      "name": "accounts_cancel.execute",
      "description": "Cancels an account",
      "resource": "Accounts Cancel",
      "action": "execute",
      "applicationId": "app-platform-complete-0.0.2",
      "permission": "accounts.cancel.post",
      "endpoints": [
        {
          "path": "/accounts/{id}/cancel",
          "method": "POST"
        },
        {
          "path": "/accounts-bulk/cancel",
          "method": "POST"
        }
      ],
      "type": "procedural",
      "metadata": {
        "createdDate": "2023-11-30T09:46:43.819+00:00"
      }
    }
  ],
  "totalRecords": 1
}

Note: A capability has a permissions field that corresponds to the permissionName  in Folio permissions. This information can be helpful when searching for the required permissions.


Example of Searching for a Capability Corresponding to a Permission

In Folio, the description parameter is consistent across permissions and capabilities. For instance, if you're searching for a capability-set corresponding to a Folio UI permission, you can utilize the description  parameter in your search criteria. This can provide a clearer navigation and management of permissions and their associated capabilities.

Let's imagine we have a UI permission with the displayName  'Inventory: All permissions'. We first find this permission in mod-permissions  and then link it to a capability-set using the description  parameter. To find permission by using the displayName, you can do the following search:

curl -X GET "${baseUrl}/perms/permissions?query=displayName=Inventory: All permissions" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}"  | jq .
 permissions response...
{
  "permissions": [
    {
      "permissionName": "ui-inventory.all-permissions.TEMPORARY",
      "displayName": "Inventory: All permissions",
      "id": "e1111ac0-e139-4a79-9cb0-b0d8e0e9c1e3",
      "description": "Some subperms to support enabling/using the Inventory app",
      "tags": [],
      "subPermissions": [
        "ui-plugin-create-inventory-records.create",
        "ui-inventory.instance.view",
        "ui-inventory.instance.create",
        "ui-inventory.holdings.create",
        "ui-inventory.item.create",
        "ui-inventory.instance.edit",
        "ui-inventory.item.edit",
        "ui-inventory.holdings.edit",
        "ui-inventory.item.markasmissing",
        "ui-inventory.item.delete",
        "ui-inventory.holdings.delete",
        "ui-inventory.instance.view-staff-suppressed-records",
        "browse.contributors.instances.collection.get",
        "inventory-storage.bound-with-parts.collection.get"
      ],
      "childOf": [],
      "grantedTo": [
        "17a68d38-f795-47ca-a11e-cd7a80351f8b",
        "26878f64-ab88-4f62-8cc7-172714453329",
        "1b9644ff-0686-42e6-9191-52267038c841",
        "bf7f4a66-da8e-43bd-be50-5bbdd2fcbaea",
        "1acb804c-ff45-44d1-bdc2-8b10ec82b69f",
        "bed68e93-c746-4598-ace5-19dc2dbd30b4"
      ],
      "mutable": false,
      "visible": true,
      "dummy": false,
      "deprecated": true,
      "moduleName": "folio_inventory",
      "moduleVersion": "9.4.5"
    }
  ],
  "totalRecords": 1
}

Now, having the permission's description, we can find the corresponding capability-set: 

curl -X GET "${baseUrl}/capability-sets?query=description==*Some subperms to support enabling*" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}"  | jq .
 capability-sets response...
{
  "capabilitySets": [
    {
      "id": "dcd42a7f-4a22-4bb9-8d4a-75541e71a9da",
      "name": "ui-inventory_all-permissions_temprorary.manage",
      "description": "Some subperms to support enabling/using the Inventory app",
      "resource": "UI-Inventory All-Permissions Temprorary",
      "action": "manage",
      "applicationId": "app-platform-complete-0.0.2",
      "type": "data",
      "capabilities": [
        "fe5c3f2d-c9eb-4e41-a19c-609626acbf10",
        "9bb373c6-b187-4a43-8d41-b717346fe4a9",
        "7fe19a97-2c90-4cba-8a58-103282d0bf76",
        "3a3836c0-8cf1-4a80-9dbf-4090d69d555b",
        "41f0688b-0cc3-49c6-8ab4-88cb824c9969",
        "ef631049-a3a4-4ac8-9a70-aab6ea8f20e7",
        "1e6b7593-6266-4da3-9c7b-967ddf833a63",
        "2219a2c3-db13-48d4-b809-4023f53053dd",
        "cc6e7b55-21e6-4884-bfb2-a4a197f0178b",
        "b3cc7e08-3f71-4b69-9a85-292d69231e32",
        "1cdf6b65-e387-4437-ba42-1c77ac17d2b7",
        "7b124969-ccf9-480c-ab59-57c8279211db",
        "d835f21c-7424-4cb9-b4e9-12935673e763",
        "36812269-32b2-4bb9-9a5b-4937edcf3aae",
        "cf29fafc-7f3e-4fd9-8387-6ce53ba7c3fc",
        "fa28c961-d662-42ae-93fc-82bd1bf38fd4",
        "b4c884b7-376f-49f9-b129-58b9b947d5d5",
        "baa027a0-40b5-4a17-99bc-8cb6dad12f25",
        "a47a5f46-f95a-451c-9a90-7f3e5eeeb645",
        "5934251e-c4c5-4008-9bd2-7ac3a9a87fbe",
        "fb131797-a879-4caa-8d9c-0a6a753b4515",
        "c8702859-424d-450a-a1ea-17a45d9461f8",
        "2b46ed8b-e96d-4ad3-8676-5cba06b627f3",
        "79181f59-505e-48c0-84e2-44cab5051828",
        "bc7c2661-02fb-469b-bc34-18a6442d5486",
        "76e99f8f-d25b-43d1-8499-16e3679f3833",
        "2baa01c6-4663-42db-8af4-b340b1b6d954",
        "a5ba97be-4935-4965-a0d8-729d3bd7d25d",
        "a38772aa-9502-41ab-95e2-a625fe69966c",
        "29d2ab21-19fc-4a02-bb70-ec7b9c91689f",
        "9102ab8f-1950-4aca-9287-94e256859831",
        "8499a75b-fd41-4f97-84eb-667077ce5c33",
        "ee9bd541-b158-4548-b391-fc0bfec34e51",
        "129547a9-500c-4252-bcb9-050aaaa29d34",
        "09814e04-6594-488a-a0b0-66b06d867984",
        "0c5564e0-0476-4816-a9ae-ba60d2af86d7",
        "0ac23679-3a16-4a82-bc2f-1d130bd6ca25",
        "eba8a028-a74d-421b-9794-c50c5dbfd60c",
        "62c64b3d-f0d0-4c3d-822d-32db1e71459a",
        "e2e4015a-4216-4faf-8c0d-9f574603cb0e",
        "2eace724-906a-4e8e-9db4-2843af198bf3",
        "0601f5b9-3c87-4ee4-b32b-b82c95d1b886",
        "4ad0a88d-4f01-4bc0-a420-614bd446ac68",
        "b35dfb72-3d3c-4cfa-9c12-08713325e3f6",
        "ef2862b0-5a44-4c64-96ab-a4dd870692a8",
        "9b01dc7a-9a0f-4e65-9808-1763a74150f8",
        "5dda45eb-d420-4390-92e3-11507cd3d3ba",
        "27b9a0c5-71a6-45a1-87b0-2e32b7e99f43",
        "9021499d-e224-4004-bf59-bd02a5c5c0c2",
        "286853aa-6511-4f39-9f1c-4c9908fd6d29",
        "0a5fd467-153d-4b6d-9821-d4b8701d29cc",
        "99d2d256-0612-4974-92af-dd39e48a6c7b",
        "3d3a9e19-d32e-4b87-a5b7-86ce079ae400",
        "db23dc4d-daa8-4efa-adc7-3f2640460fce",
        "dbdf0a1b-093d-4bee-8159-18b0095515b5",
        "94160ae5-6491-48a8-9a5f-0332c4f9d288",
        "12db1dc4-03cd-4d14-ab76-905658806c75",
        "910f2baa-d7e6-4861-ba31-372f666832b6",
        "78027f69-a9d4-4933-91a5-3d40ee3c7a27",
        "5d0e2855-2800-4b30-91df-ae93125561c8",
        "7460294f-bb1a-4714-bc3c-8f7306966fa9",
        "1776e952-c7b4-47be-abf1-ee5d22c5a13c",
        "0e7dee67-cb0c-4534-97e0-92182dde4126",
        "de3e79f4-7c8f-4008-8737-022c68b99ec0",
        "efd4e8fb-87aa-44e3-98be-bc95a015de01",
        "8d3b0dce-d3e0-48ec-9ffc-8f75e9f6eb58",
        "b9024705-6df9-476b-974b-1c07c8b1a394",
        "12a6ecb6-a9fc-4638-8622-fd5a40d140bc",
        "cb67008a-a7d1-4de8-a858-20805b209631",
        "3869a0cb-7530-4038-a608-65b10917518f",
        "a178c286-4ffc-47db-84e7-21ee20d891cb",
        "dac0887a-164a-493f-9acd-ff8c328b47b1",
        "22c846be-a5da-4948-b52b-e4724adbf2a7",
        "5dcfc2c6-32c7-4f89-9ef3-50665cba6ed0",
        "7f8b57b8-4a25-4c78-8faa-2d874cb4176e",
        "368027e9-80e4-4afd-8be6-c592dabe15a1",
        "fd4406d2-d8d4-4be0-a874-812f022b8b7a",
        "63d9adda-8bce-436c-855f-7c853481a26d",
        "044df6d6-90b2-4a31-b894-cab8a85185dd",
        "e77ed147-e9ad-4f44-830a-9e642d5ba8d6",
        "4fb19638-f00f-4cf2-90d4-88d216f97dd9",
        "c38244d1-d41c-407a-a14c-1a7a8099b765",
        "e0741392-45eb-4d3d-89fe-d00cccbdb960",
        "402c2c02-d70b-4b13-808b-3a7d57f10501",
        "c40cba83-e495-4145-8c45-71933cfc24c8",
        "da2c7b09-2e6b-429b-ae9d-7550e2e4a8d7",
        "f65d5782-e2f3-42b2-b544-6203e2b585a1",
        "2d998f85-46a6-4eec-ab5e-8e3487742d1c",
        "49a12c85-703b-4588-9bf0-6acf6f2c0d3f",
        "edc99f2d-ebae-4504-a4dc-5ffb4de7651e",
        "dafaf505-93ae-47d8-a9ba-1976b0456d05",
        "74d876cb-254f-4688-a6ff-054215ef6219",
        "f35c6223-c4ed-4a69-bf88-6a481a504f5d"
      ],
      "metadata": {
        "createdDate": "2023-11-30T09:46:53.736+00:00"
      }
    }
  ],
  "totalRecords": 1
}

Creating Roles and Assigning Capabilities

After the user is created, and the required capability-set and capability have been found, we can proceed to the creation of a role and assignment to the user.

Note: Capabilities can be assigned both directly to a user and through a role.

Create a role:

curl -X POST "${baseUrl}/roles" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}" \
-H 'Content-Type: application/json' \
-d '{
  "name": "role-name",
  "description": "role description"
}' | jq .

To associate role with capability-sets, use the following command:

curl -X POST "${baseUrl}/roles/capability-sets" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}" \
-H 'Content-Type: application/json' \
-d '{
  "roleId": "f4351668-8216-43de-b82d-c0aca05153b0",
  "capabilitySetIds": [
    "e54e1b37-6f11-422e-b7ed-70339f3d4dff"
  ]
}' | jq .


 assoticating roles with capabilities...

Roles can also be directly linked with capabilities:

curl -X POST "${baseUrl}/roles/capabilities" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}" \
-H 'Content-Type: application/json' \
-d '{
  "roleId": "03db8142-c79f-4f38-8662-ee0f7ca05a36",
  "capabilityIds": [
    "c11e07f4-8bb0-45d1-a396-aaa72ae3121b",
    "d928eab1-1d3a-4d67-949e-a0305ced5b6a"
  ]
}' | jq .

To assign the newly created role to the user, use the following command:

curl  -X POST "${baseUrl}/roles/users" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}" \
-H 'Content-Type: application/json' \
-d '{
  "userId": "13480b8b-dba5-4980-86d7-5314996a418b",
  "roleIds": [
    "f4351668-8216-43de-b82d-c0aca05153b0"
  ]
}' | jq .

Assigning Roles to a User

Once the role has been created and associated with the required capability-set (or just capability), we can proceed to assign this role to the user.

To assign the newly created role to the user, use the following command:

curl -X POST "${baseUrl}/roles/users" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}" \
-H 'Content-Type: application/json' \
-d '{
  "userId": "13480b8b-dba5-4980-86d7-5314996a418b",
  "roleIds": [
    "f4351668-8216-43de-b82d-c0aca05153b0"
  ]
}' | jq .

Note: Ensure to use the appropriate IDs for the user, role, and capabilities that correspond to your specific environment when executing these commands. Correct IDs are crucial for the proper assignment of permissions.

Assigning Capabilities Directly to User

It's possible to assign capability-sets or capabilities directly to a user, bypassing the role. Here is the corresponding request for this operation.

Associate user with capabilities:

curl -X POST "${baseUrl}/users/capabilities" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}" \
-H 'Content-Type: application/json' \
-d '{
  "userId": "61893f40-4739-49fc-bf07-daeff3021f90",
  "capabilityIds": [
    "8d2da27c-1d56-48b6-958d-2bfae6d79dc8",
    "d5221b22-386f-4c7f-b3b6-5897f94044a0"
  ]
}' | jq .

Associate user with capability-sets:

curl -X POST "${baseUrl}/users/capability-sets" \
-H "x-okapi-tenant: ${tenant}" \
-H "x-okapi-token: ${token}" \
-H 'Content-Type: application/json' \
-d '{
  "userId": "9b663ae9-9483-4fab-966b-58955bc31893",
  "capabilitySetIds": [
    "c11e07f4-8bb0-45d1-a396-aaa72ae3121b",
    "d928eab1-1d3a-4d67-949e-a0305ced5b6a"
  ]
}' | jq .

Useful Links and Additional Information

  • There is an API endpoint available for creating multiple roles at once: POST /roles/batch .

  • How to create a Shadow User in a member tenant can be found here