User

User profile create

Let’s explore an example of creating (post_user_list) and updating (put_user) user profiles via API:

A user profile is constructed from basic fields (firstName, lastName, email, roles, …) and your custom defined profile fields (user fields). In order to construct the required payload the definition of your custom profile fields (user fields) is required. The recommended process is to fetch all the user fields in advance to ensure the data is valid. The below example shows how you can fetch user fields:

>>> user_fields = requests.get('https://api.kaizenep.com/v2/user-fields', headers=headers).json()
[
    {
        "_id": "id1",
        "name": "Person College ID",
        "fieldType": "string",
        "isRequired": true
    },
    {
        "_id": "id2",
        "name": "Gender",
        "fieldType": "discrete",
        "isRequired": true,
        "categories": [
            {
                "_id": "opt1",
                "name": "Male"
            },
            {
                "_id": "opt2",
                "name": "Female"
            }
        ]
    }
]

In order to assign roles to a user a list of IDs has to be added to the payload. Role IDs can be obtained by using the roles endpoint (get_role_list). The below example shows how you can fetch the role IDs:

>>> roles = requests.get('https://api.kaizenep.com/v2/roles', headers=headers).json()
[
    {
        "_id": "roleid1",
        "name": "Trainee",
        ...
    },
    {
        "_id": "roleid2",
        "name": "Assessor",
        ...
    }
]

To enable the user to log in to risr/advance they must have credentials added to their account. There are two types of credentials:

  • Proxy type is used when authentication is done outside risr/advance such as when integrating with your SSO provider, and only the username is required to map the SSO user to the newly created risr/advance account. Username is in this case an agreed unique attribute provided by the authentication party (for example eduPersonPrincipalName - urn:oid:1.3.6.1.4.1.5923.1.1.1.6)

  • Local type is used when authentication is done within risr/advance and standard username and password is required.

By default a welcome email is sent to the newly created user. This behvaiour can be suppressed by adding a corresponding flag to the options.

Having the list of user fields and roles we can construct the payload for creating a user:

>>> payload = {
        "firstName": "John",
        "lastName": "Doe",
        "email": "john.doe@org.com",
        "roles": ["roleid1"],
        "userFields": [
            {"_id": "id1", "value": "Users value for field 1"},
            {"_id": "id2", "value": "opt2"}
        ],
        "credentials": [
            {"type": "proxy", "username": "sso_attribute_value"}
        ],
        "options": {
            "sendWelcomeEmail": false
        }
    }
>>> response = requests.post('https://api.kaizenep.com/v2/users', json=payload, headers=headers)
>>> response.json()
{"id": "new_profile_id", "rev": "revision number", "username": "new_kaizen_id"}

Retrieving users

Important

User ID vs Username

Each user is given unique ID we refer to as a “kaizen id” or a “username”. This account information is used as a user identifier in all parts of risr/advance. All user profile data are stored in a separate object with it’s own ID we refer to as a “profile id” or a “user id”

There are multiple ways how to retrieve a user profile.

  • Fetch by profile ID
    >>> response = requests.get('https://api.kaizenep.com/v2/users/new_profile_id', headers=headers)
    
  • Fetch by risr/advance ID
    >>> response = requests.get('https://api.kaizenep.com/v2/users/by_username/new_kaizen_id', headers=headers)
    
  • Fetch by a specific user field
    >>> response = requests.get('https://api.kaizenep.com/v2/users/by_field/id2/opt2', headers=headers)
    

The responses of these calls are identical and have the following structure.

>>> response.json()
{
    "id": "new_profile_id",
    "user": "new_kaizen_id",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@org.com",
    "roles": ["roleid1"],
    "userFields": [
        {
            "_id": "id1",
            "value": "Users value for field 1",
            "label": "Person College ID"
        },
        {
            "_id": "id2",
            "value": "opt2",
            "label": "Gender",
            "text_values": ["Female"]
        }
    ],
    "auditLog": [
        {
            "action": "user_created",
            "actor": "fry",
            "date": "2019-12-05T13:58:07.850768+00:00",
        }
    ]
}

The response contains all information about requested user profile. In some cases it is not required to fetch all the data. This can be controlled by an “includeParts” argument with following options:

  • all - Include all parts (excluding allRelations)

  • userFields - Include all user fields

  • auditlog - Include audit/changes log

  • roles - Include roles and whether user is an organisation admin

  • relations - Includes active relations and associated users

  • allRelations - Includes relations and associated users including past and future entries

includeParts argument is a list and can be passed as a comma-separated query string. For example

>>> response = requests.get('https://api.kaizenep.com/v2/users/by_username/new_kaizen_id?includeParts=roles,auditlog', headers=headers)
>>> response.json()
>>> response
{
    "id": "new_profile_id",
    "rev": "1-revision-number",
    "user": "new_kaizen_id",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@org.com",
    "roles": ["roleid1"],
    "auditLog": [
        {
            "action": "user_created",
            "actor": "fry",
            "date": "2019-12-05T13:58:07.850768+00:00",
        }
    ]
}

User profile update

Updating a profile is similar to creation. The main difference is that it is required to include profile id (user id) and a revision number. Revision number is important because it ensures that we are updating up to date version of the profile, this means that it has not been modified by someone else in the meantime. This implies that the profile to update has to be fetched from the server before we can construct the request payload.

All the fields in the payload are optional so that it is possible to update only part of the profile without affecting all other fields. An example of a payload is below:

>>> payload = {
        "_id": "profile_id",
        "_rev": "revision_number",
        "firstName": "John",
        "lastName": "Doe",
        "email": "john.doe@org.com",
        "roles": ["roleid1"],
        "userFields": [
            {"_id": "id1", "value": "Users value for field 1"},
            {"_id": "id2", "value": "opt2"}
        ]
    }
>>> response = requests.post('https://api.kaizenep.com/v2/users/profile_id', json=payload, headers=headers)
>>> response.json()
{"id": "profile_id", "rev": "new revision number", "username": "kaizen_id"}