Implementing User Roles in Experiences

Most applications have user roles. For example, in some applications, certain pages and functionality are available to everyone, and others only available to an admin user. You can implement your own custom user roles with a Losant Experience.

This tip is adapted from How to Securely Upload Files with Losant Experiences , by Brandon Cannaday

Let’s look at an example. Here is an example of an Experience View:

For this application, the maintenance interval data (stored in a Losant Data Table), should be available to everyone. But, we only want administrators (a new role type) to upload new maintenance interval data to the underlying Losant Application. This use case requires us to show/hide the upload form you see above based on the user’s “role.”

There are two main ways to “group” Experience Users:

Experience Groups - An Experience Group is a mechanism for associating your application’s devices with your Experience Users. Experience Groups are there to help you manage the relationship between your groups of customers and their devices.

Experience User Tags - Tags allow for the storing of arbitrary data against any Experience User, like user roles (ex. admin or not). Tags can be used to group Experience Users in the most flexible way possible.

We recommend Experience User Tags for user roles. Since user roles don’t usually impact any relationships to devices, but they do impact the UI, we don’t need to create Experience Groups for user roles.

In the image of the Experience you see above, here is the code to hide/show the upload form based on the user’s role (experience.user.userTags.role) and using the #eq helper:


{{! Only show the upload form if the user is an admin and a member of the Kanarra Technologies group }}
{{#eq experience.user.experienceGroups.[0].name 'Kanarra Technologies'}}
{{#eq experience.user.userTags.role 'admin'}}
  <form action="/maintenance-intervals" method="POST" enctype="multipart/form-data">
    <div style="font-size: 16px; text-align:center;margin-bottom:15px;">
      Upload new maintenance intervals
    </div>
    <div>
      <div style="text-align:center;">
        <input type="file" name="maintenanceIntervals" id="maintenanceIntervals" accept=".csv">
      </div>
      <div style="text-align:center;margin-top:10px;">
        <button class="button">Upload</button>
      </div>
    </div>
  </form>
{{/eq}}
{{/eq}}

Using techniques in this tip, you can start to build out user roles in your Experiences today. We’ll be back with a tip next week! :slight_smile:

1 Like

Hi Taron, thank you for a good example. I am currently implementing a better user management in our instance and a few things are not clear to me, for example:

  1. Where to find a reference doc for Syntax of Losant Helpers available in custom pages. I mean #eq and #if etc

  2. What if I want to give an access to users who are part of a certain group, but there are a few groups they are members of? It results in 0-N array records on experience.user.experienceGroups.[index]. In other words, what if I don’t know the exact index of the group. Should I browser through all available groups?

  3. Could you correct my expression for the example described in 2), please?

    {{#eq experience.user.experienceGroups.[0].name ‘My Target Group’ || #eq experience.user.experienceGroups.[1].name ‘My Target Group’ #eq experience.user.experienceGroups.[2].name ‘My Target Group’ #eq experience.user.experienceGroups.[3].name ‘Target Group’ }}
    {{/eq}}

@Alexander_Kondrov,

  1. Yes, they are hard to find. It’s currently on our list for doc improvements. I’ll bump that up for you.
  1. & 3.

I don’t actually think you can nest helpers in a conditional like that. ( I’ll have to double-check the best way to do that. ). But, my best recommendation would be to move that logic into a workflow and pass it in as page data. You can do the logic in a Workflow and pass userShouldSeeSomething ( or something of the like) to your page. Then, you can reduce down to a simple #if:

{{#if userShouldSeeSomething}} Aweomse IoT Things {{/if}}

I recommend keeping the logic in your views super simple.

Taron,

Thank you for the advice to pass view rights stuff from the workflow. I haven’t think about it before receiving your hint. I will try to check it out.

1 Like

Taron,

In addition, I have a feedback on the syntax of your and Brandon’s example.
‘Kanarra Technologies’ - didn’t work for me
"Kanarra Technologies" - worked for me

1 Like

@anaptfox

Hi, I’m currently working on a similar topic but we face the challenge that we want to have users in different groups different roles. Is there any recommendation on your side how to implement such a thing?

Many thanks

@Jonas_Helmstetter I would still use one of the two methods described at the top of the post:

  1. Store a role tag on each Experience User and set it to, for example, “admin”, “editor”, “viewer”, etc. This is what I recommend even for your use case.
  2. If you want to maintain them in groups, you can build experience groups that exist outside of your multitenant hierarchy and add users to those groups. An experience user may be in multiple groups, so an administrative user could be in a top-level group calles “Administrators” as well as in an experience group called “Company X” - which could then be a descendent of other groups if desired.

Hi @Dylan_Schuster Many thanks for your fast reply. So in order to have a User A in Group A and B but with different roles (Group A: Admin, Group B: Viewer) you would suggest Method 2 to have an experience group hierachy like this:

  • Group A:
    • Group: Admins
      • Members: User A
    • Group: Viewers
  • Group B:
    • Group Admins:
    • Group Viewers:
      • Members: User A

That could work, if that fits your model. More what I was thinking was that your administrators existed outside of your hierarchy altogether, but that may not be appropriate for your solution. Something like:

  • Admins
    • (Members: User A)
  • My Root Group
    • Client A
      • SubGroup A.1
        • (Members: User A)
      • SubGroup A.2
    • Client B
      • SubGroup B.1
      • SubGroup B.2

I see the advantages of your shown model. But this would mean the “admin role” would not be specific for one group but it would be valid for all groups. Would it be possible to store all experience user ids in an experience group tag named admins? As far as I know, arrays in a tag are not supported or am I wrong? Many thanks for your help. I really appreciate the great support you and your team offer for the platform.

Would it be possible to store all experience user ids in an experience group tag named admins? As far as I know, arrays in a tag are not supported or am I wrong?

Possible? Yes - you could store it as a stringified array and then parse it when needed. But I wouldn’t recommend it. A syntax error would break the whole solution, and tag values have a maximum length of 255 characters, meaning that you could fit a maximum of 9 admins into a tag.

If the admins still need to be scoped to specific groups in your hierarchy, you could try something like this for a structure …

  • Top-level Group A
    • Administrators A
      • (admin user is a member)
    • Sub-group A.1
      • (admin user is a member)
    • Sub-group A.2
  • Top-level Group B
    • Administrators B
    • Sub-group B.1
    • Sub-group B.2

For what it’s worth, I still think identifying administrators is best done as a tag on the experience user and not through separate experience groups, but Losant is flexible enough to support either of those implementations.

Many thanks. I just want to make sure that I understood it correctly. Your recommendation is to create the role as experience user tag. So that means if I have a user in multiple groups with different roles I would need to create an experience user tag for each group the user is in with a specifc role. The key could be for example the experience group id.

OK, your use case is a little clearer to me now. If a user should be an admin in Group A but not have admin privileges in Group B, then perhaps maintaining the admins as sub-groups in each top-level group would be the way to go. But you could still accomplish it with tags on the experience user - for example, a tag with a key of isAdmin-EXPERIENCE_GROUP_ID and a value of true.