The flexible way to adopt UX/UI in Angular app according to user’s permissions.

Daniel Ostrovsky
5 min readFeb 8, 2019

--

In many projects, there are authentication processes (more or less). A lot of “best practices” were written in all known technologies and so on, and so forth.

But what happens after the user made the login? After all, he by far cannot do everything. How to define what he can see and what not. What buttons he has the rights to click on, what to change, create and delete.

In this article, I want to consider the approach used for solving these problems in a web application.

To begin with, the present/effective authorization can take place only on the server. On front-end, we are able just to improve UI and UX. We can hide the buttons on which the user has no rights to click, or prevent him from reaching the pages, or to show the message that he does not have the rights to do a certain action.

And here arises the question, how to make it as correctly as possible? Let’s start by defining the problem.

We created a Todo App and it has different types of users:

USER — can see and update all the tasks (check/uncheck), but cannot delete, create and see statistics page.

ADMIN — can see all the tasks and create new ones, but cannot see statistics.

SUPER_ADMIN — can see all the tasks, create new ones and delete them, and also can see statistics.

In this a situation, we can use the “roles”. However, the situation can change a lot. Imagine ADMIN user with permissions to delete tasks. Or USER with access to see statistics. A simple solution is to create new roles.

But on large applications, with massive user role system, we will quickly get lost in a huge amount of roles…

And here we recall the “user rights” permissions. For easier management, we can create groups of several permissions and attach them to the user. It is always possible to add specific permission to a specific user.

This kind of solutions can be found in many large services: AWS, Google Cloud, SalesForce and so on. Also, similar solutions have already been implemented in many frameworks, for example, Django (Python).

I want to give an example of implementation for Angular applications. (On the example of the same ToDo App).

First, let’s define all possible permissions.

  1. Divide into features.
    We have tasks and statistics.
  2. We define possible actions with each of them.
    Task: create, read, update, delete.
    Statistics: read (in our example only viewing).
  3. Create a MAP of roles and permissions.

In my opinion, this is the best option, but in most cases, the server will return something like this:

Less readable, but also not bad at all.

This is how our application looks when the user is already authenticated but UI/UX is not yet adopted according to user’s permissions:

Let’s look at the USER’s permissions:

Navigation:

USER cannot see the statistics, it means he basically cannot navigate to this page.

For such situations in Angular, there are Guards, which are used at the Routes level (documentation).

Pay attention to the object in data.permissions = ‘stats’, these are exactly the permissions that the user needs to have, in order to have access to this page.

Based on the required data.permissions and USER’s permissions PermissionsGuardService will decide whether or not to allow access on page ‘/stats’.

getPermissions(); a helper function that returns an object with user's permissions.
checkPermissions(); checks if required permission is part of user’s permissions.

Hiding Elemnts

Now, our USER cannot navigate to the statistics page. However, he still can create tasks and delete them.

To make USER unable to delete tasks, it will be enough to remove the red (X) from the task line.

For this purpose, we will create a custom Structural Directive.

Now USER does not see the DELETE button but can still add new tasks.

Adopt element state:

If we remove the input field, the whole look of our application will ruin. The correct solution in this situation would be to disable the input field.

Let’s try pipe for this.

And now the USER can only see the tasks and change them (check/uncheck). However, we still have Clear completed button fully functional and available for USER.

Decorators:

Suppose that we have the following requirements from our Product Manager:

1. The ‘Clear Completed’ button should be visible to everyone and always.

2. It should also be clickable.

3. In case USER without corresponding permissions presses the button, an error message should appear.

Constructional directive will not help us, nor does pipes.

It is also not very convenient to register the check for permissions into component functions. All we need is to check permissions between the click and the execution of the bound function.

In my opinion here it is worth to use the decorators.

And our final result:

Conclusion

Maybe it’s not the best solutions. But this approach allows us to easily and dynamically adapt our UX in accordance with the permissions that the user has.

Repo Link

P.S. This is my first article… I hope it’s not a full failure.

--

--

Daniel Ostrovsky

Web development expert and teams manager with over twenty years experience in the industry.