Skip to content

Users

Users

Laputa has its own user base to manage accesses. This user base is stored in the mongo database. There are four ways to "create" a user:

  • Users created manually, in the admin interface
  • Users created automatically via the SSO (more info on that in the other chapters of this page)
  • Users generated for public embeds (but they are not saved in DB)

Note a bearer token can contain a user that does not have to exist in DB (that's how the latter 2 work).

Code structure

Most of the code handling the user logic is in the folder laputa.common.user. This code is mostly tested, split into small functions, and uses the UserModel or the UserMongoOrm. It should not use the database_manager, so beware :) We tried to have small files handling different functionalities around the user. For example, user_password.py handles all logic around the user password.

However, there is the special file user_legacy.py, which contains legacy code that uses database_manager. Please, don't enrich is file with more code, and take the time to split this file into small functions, in dedicated files.

Also, there is some legacy code left in api.resources.user that mostly handles user creation and reset password logic. And there is some other legacy code in database_manager handling user update and validation. All this code should be moved to laputa.common.user in the next refactorings.

Lifecycle: Creation, deletion, expiration and reset password

More info about this in the official documentation.

The user can be created or deleted by the admin via POST /users. This route can either create or delete one or many users. To create or delete one user it is a "standard" http call with a JSON payload. To create or delete users in blulk, it uses a CSV file upload. This CSV file is then converted to a dataframe and parsed in user_df.py.

When users are created via POST /users, the admin can either specify a password or choose to send a password generation email. In the second case, the user will receive a link which is the same as the "reset password" one.

The admin can specify an expiration date for the user. When his date is expired, the user cannot login anymore, but the user object still exists in database, and is still viewable in users admin section of the studio.

When a user is deleted, it also still exists in database, but is marked with the flag deleted, so it is not listed anymore in the users admin section.

The user can reset its own password (via a "forgot password" link in the UI). In that case (and in the case when the user chose "send a password generation email"), a temporary token is generated. This token is sent to the user in a link via email, and can only be used for the user to change his password.

Roles and privileges

Users have roles and privileges. A role gives default privileges, but it can be overridden. Users can belong to groups and groups can have privileges: more info about it in the next section.

Warning

Even thought privileges are a field of the UserModel, they (most of the time) should not be retrieved directly from the model but from the common.user.user_privileges.get_user_privileges function instead. The reason is groups can also have roles affected to them, and the users being part of these groups will inherit the privileges. This function computes the actual privileges of the user.

Available roles are:

  • SUPER_ADMIN: usually someone from Toucan Toco; it has all privileges, including the permission to add or remove all admins
  • ADMIN: has the permission to add and remove users and admins, but not super admins. He also has the permission to do other administrative stuff such as edit instance settings, or edit instance email notifications. He has the contributor permission on all small apps.
  • USER: has not the permission to do any administrative stuff, and, by default, he does not have access to any small app. The admin gives privileges to the user per small app when creating the user (or configuring the SSO).

Available privileges per small app are:

  • Own : is the owner of the app, same privileges as an admin but only for the small app
  • Contributor: can view and edit all config in the small app, in staging and in production
  • Data contributor : same as contributor but only for the data part of configs
  • Design contributor : same as contribubor but only for the design part of configs
  • Self contribute : can contribute to its personal embed
  • Validator: can view (not edit) the staging and the production
  • Viewer: can only view the production

Groups, permissions and privileges

More info about this in the official documentation.

User groups are created separately from the user creation. Users can be added to groups directly on creation or later (a user can be part of multiple groups). They are stored in a separate collection with their the group name being unique (it is not changeable for now). Groups can also contain privileges, they will override their users respective privileges, they have:

  • A privileges dict field stored in a similar way to the user's one.
  • A boolean field use_group_privileges, if set to True, the privileges of the group will be applied to its users instead of their user privileges.

Warning

If a user is part of two group that have conflicts happen between their privileges, the maximum privilege will be taken.

They are also used for permissions, see the "permission" page of this doc for more info.

User attributes

The auth provider (SSO) can add extra fields in the user (nested under its attributes field): these are called user attributes. These attributes are mostly used for permissions as well.

User secrets

Like user's attributes, The auth provider (SSO) can add extra fields in the user (nested under its secrets field): these are called user secrets and can contain tokens or some secrets informations.

Model

The pydantic user model is in laputa.models.user; it has many properties, and is a bit cahotic. We already have done the effort to have a fixed model in DB via mongoengine, we will think about splitting this model later on.

This model is used in most part of the code and allows to validate the user object. However, in legacy parts of the code, there is validation done manually: in database_manager mostly.