logo

Security Changes in Atoti V0.8

Hui Fang Yeo

Aligning and simplifying coding

In case you haven’t noticed, we have one less plugin with Atoti Python API v0.8 – the atoti-plus plugin. Plus features like security and the ability to build custom UI extensions have been merged into the core modules. With this change came simplifications such as:

  • Depending on our license, we can use the features that previously came with the atoti-plus plugin without having to install the plugin.
  • We can streamline our code as we no longer have to import modules like security separately.

In this article, we will explore how this change simplifies our security implementation. Note, this feature is not available in the Community Edition. Explore these features by requesting an evaluation license.

Module deprecation

In v0.7.x, the atoti_plus.UserServiceClient module is used to manage parts of the security config:


from atoti_plus import UserServiceClient
user_service_client = UserServiceClient.from_session(session)

user_service_client.basic.create_user(
      "atoti_admin", password="password", roles=["ROLE_ADMIN", “ROLE_SHARE”]
)
user_service_client.basic.create_user(
      "atoti_user", password="password", roles=["ROLE_SHARE"]
)

Below are the changes in v0.8.0:

  1. Instead of using user_service_client,  we will use session.security instead.
  2. Instead of using create_user, we will use credentials which is a mutable mapping.

session.security.basic.credentials.update({
    "atoti_admin": "password",
    "atoti_user": "password",
})

session.security.individual_roles.update({
    "atoti_admin": {"ROLE_ADMIN", “ROLE_SHARE”},
    "atoti_user": {"ROLE_SHARE"},
})

As we can see, instead of invoking the create_user function each time we create a username we can invoke the credential update function to create multiple users at the same time. Also, we can grant roles to multiple users in one go.  

Permission for sharing

Before v0.8.0, ROLE_SHARE was a system-defined role that could be assigned to users for the rights to share folders, dashboards, widgets and filters.  

Now, ROLE_SHARE is no longer available. Instead, all users with the role ROLE_USER will be granted sharing permissions. This permission is configured in the admin application using the canShare property. 

Admin application can be accessed from session.link(path="/admin"). Login with a user with ROLE_ADMIN assigned.

Controlling sharing permissions

We can remove the default sharing permissions for all users by removing the canShare properties or set it to false, using ctrl+s or cmd+s to save the change. 

To control who has permission to share, we can either grant canShare permissions to an individual user or by a role. For instance, under the user_roles folder, we can create a new folder for a role dedicated to sharing, e.g. ATOTI_SHARE. Under the role folder, create a file named permissions.  

Grant the user role the canShare permission by setting it to true. Anyone who is granted the role ATOTI_SHARE will be able to share now.

💡It is important to note that before v0.8.0, users were granted the role ROLE_USER by default when we created them with basic authentication. Starting with v0.8.0, remember to grant our users this role explicitly.  

Setting sharing permissions using requests

Other than updating sharing permissions using the admin web application, we can call the rest services to do so. But first, we should create a technical user to perform this backend action:

technical_user_name = "ATOTI_TECH_ADMIN"
technical_user_password = "password"

technical_user = session.security.basic.credentials[
    technical_user_name
] = technical_user_password
session.security.individual_roles[technical_user_name] = {"ROLE_USER", "ROLE_ADMIN"}

💡Regardless of the type of authentication provider the session is using, we can always create a technical user using the basic authentication function as shown above. 

Since we have activated security, our put request requires authentication to be passed in: 

response = requests.put(
f"https://localhost:{session.port}/activeviam/content/rest/v7/files?path=ui/user_roles/ROLE_SHARE/permissions",
    auth=(technical_user_name, technical_user_password),
    json={
        "content": '{"canShare": true}',
        "owners": ["atoti_admin"],
        "readers": ["ROLE_USER"],
        "overwrite": True,
        "recursive": True,
    },
)

Restricting Access

We used to create a role and apply restrictions on it by defining a tuple containing the table and column name, mapped to the value that the role has access to.


role_inspire = user_service_client.create_role(,
     "ATOTI_ROLE_INSPIRE",
    restrictions={("parent_co", "parent_company"): ["Inspire Brands"]},
)

Without having to explicitly create roles in Atoti, we can now use the name of the role mapped to the conditions of the restrictions. This syntax is now consistent with how other conditions are written across Atoti.  


session.security.restrictions.update(
    {
        "ATOTI_ROLE_INSPIRE": (base_tbl["parent_company"] == "Inspire Brands"),
        "ATOTI_ROLE_RESTAURANT": (
            base_tbl["parent_company"] == "Restaurant Brands International Inc."
        ),
    }
)

Login form in place of Basic Auth Prompt

Before Atoti v0.8.0, we leveraged the Basic Authentication prompt from the browser for login when we used either basic authentication or LDAP authentication:

However, such authentication prompts can be disruptive and may negatively impact the user experience. Therefore, we now have a login page in place of the login prompt!

Using Atoti Community Edition and want to try Atoti Python API? Request an evaluation license online!

Like this post ? Please share

Latest Articles

View All

Hierarchy Fundamentals in Atoti

Read More

Retail Banking Analytics with Atoti

Read More

Putting Python Code in Production

Read More

NEWSLETTER

Join our Community for the latest insights and information about Atoti