Dynamic User Permissions

Each table has the option to set whether it allows updates, adds, deletes, or just read-only access.

I would like to manage these permissions dynamically.

Here are the tables I have:

  1. Users: This table manages users. Each user has a unique userID, their email used for logging in, and their user roles (EnumList + ref to the Roles table). A user can have multiple roles, such as Admin, Editor, User, etc.

  2. Table_Restrictions: This table defines which roles have which permissions for all the tables used in the AppSheet application. The Table_Restrictions table has columns for Adds, Updates, and Deletes. Each column uses an EnumList + ref to the Roles table to define the user roles that are allowed to perform the respective operations on the table. If all three columns are empty, the table is read-only for all roles.


Is it possible, in the table settings under the condition “Are updates allowed?”, to achieve the following:

  1. Verify the roles assigned to the user based on their email from the Users table.
  2. Check if the roles the user has are permitted to perform Adds, Updates, or Deletes. If they are, the table should be set accordingly for the user’s permissions. If not, it should be read-only.

I am trying to accomplish this but am slowly giving up.

Could someone guide me to the correct logic?

Thank you.

I’m done with similar craziness like this code…

SWITCH(
  CONTEXT("ViewType"),
  "Form", 
    IFS(
      IN(
        "SuperAdmin",
        SPLIT(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), ", ")
      ), 
      "ALL_CHANGES",
      NOT(ISBLANK(
        INTERSECT(
          SPLIT(
            LOOKUP(
              "Persons",
              "Custom_TablesRestrictions",
              "TableName",
              "AllowedAddsRoles"
            ),
            ", "
          ),
          SPLIT(
            LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"),
            ", "
          )
        )
      )),
      "ADDS_ONLY",
      TRUE, 
      "READ_ONLY"
    ),
  "Detail",
    IFS(
      IN(
        "SuperAdmin",
        SPLIT(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), ", ")
      ), 
      "ALL_CHANGES",
      NOT(ISBLANK(
        INTERSECT(
          SPLIT(
            LOOKUP(
              "Persons",
              "Custom_TablesRestrictions",
              "TableName",
              "AllowedUpdateRoles"
            ),
            ", "
          ),
          SPLIT(
            LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"),
            ", "
          )
        )
      )),
      "UPDATES_ONLY",
      TRUE, 
      "READ_ONLY"
    ),
  "Table",
    IFS(
      IN(
        "SuperAdmin",
        SPLIT(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), ", ")
      ), 
      "ALL_CHANGES",
      NOT(ISBLANK(
        INTERSECT(
          SPLIT(
            LOOKUP(
              "Persons",
              "Custom_TablesRestrictions",
              "TableName",
              "AllowedDeleteRoles"
            ),
            ", "
          ),
          SPLIT(
            LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"),
            ", "
          )
        )
      )),
      "DELETES_ONLY",
      TRUE, 
      "READ_ONLY"
    ),
  "READ_ONLY"
)

I want to achieve that by changing records in one table, I will change permissions to specific tables… I will simply add or remove a role for a specific table and specific Adds, Update, Delete permissions.

A functional solution. Mischief made commas (spaces) between EnumList values.
I still have to deal with that somehow.

Is this too crazy for appsheet? In testing it seems to work ok.

Otherwise, I’m sorry, I’m not a programmer, just an amateur.

SWITCH(
  TRUE,
  AND(
    NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedAddsRoles")), ",")))),
    NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedUpdateRoles")), ",")))),
    NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedDeleteRoles")), ","))))
  ), "ALL_CHANGES",
  
  AND(
    NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedAddsRoles")), ",")))),
    NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedUpdateRoles")), ","))))
  ), "ADDS_AND_UPDATES",
  
  AND(
    NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedAddsRoles")), ",")))),
    NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedDeleteRoles")), ","))))
  ), "ADDS_AND_DELETES",
  
  AND(
    NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedUpdateRoles")), ",")))),
    NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedDeleteRoles")), ","))))
  ), "UPDATES_AND_DELETES",
  
  NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedAddsRoles")), ",")))), "ADDS_ONLY",
  
  NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedUpdateRoles")), ",")))), "UPDATES_ONLY",
  
  NOT(ISBLANK(INTERSECT(SPLIT(TRIM(SUBSTITUTE(LOOKUP(USEREMAIL(), "Custom_Users", "Email", "AllUserRoles"), " , ", ",")), ","), SPLIT(TRIM(LOOKUP("Persons", "Custom_TablesRestrictions", "TableName", "AllowedDeleteRoles")), ",")))), "DELETES_ONLY",
  
  "READ_ONLY"
)
1 Like

I’m in the process of building this out myself as we speak.

I have a App Permissions table within my App (front-end) that I allow people to select “Functional Roles” that have the Modify Levels for each Table (“Database Tables” table).

I have more layers of complexity though, that says what type of data you are allowed to Modify (hence why there might be two entries for a Functional Role per table (e.g. below IT Help Tickets).

As a result you should be able to simplify yours more than mine to take out the Access Level and the additional Functional Roles to Roles layer.

CleanSheets_11-1720738438983.png

I wanted to make it as little amount of backend changes as possible, so people could add a table without having too much stuff to set up.

Each user is assigned a Role as part of their job:

Each role has multiple functional roles:

As a result, I built slices to help to find the highest level of Updates you are allowed for your role based on all your contribution roles with the role/s assigned to you.

You can ignore the Reddit slices as they are Read/edits for the Security Filters for that “Access Level” column from the first picture.

You have to create a hierarchy so that you allow the most access first and flow downwards from there.

This ALL_CHANGES slice is the first one to build:

(Side note these three are the other helper slices the show up):

App Permissions Table

and Many to Many - Roles to Functional Roles

and Many to Many - Staff to Roles

Then all the “Two Type” updates can flow on like this:

Then define a “One Type” slice:

Then all the “One Type” of permissions:

Once those slices are all set up, they won’t need to change.

Then the Table Config for Update Mode can reference the slices (unfortunately, you have to repeat the name of the table in several locations. As a result I have a field on the “Database Tables” table that means when you register the table within the app, it gives you this formula completed to add to the expression assistant):

Once that is set up, I can dynamically control the permission within the App itself, based on users → user’s roles → role’s functional roles → Table Permissions.

This means if a user changes roles, or if a security person changes the permissions sets for the roles or functional roles within a role, the user’s permissions may change.

Hope that helps shortcut some of the pain I had to go through to get what I was looking for.

Cheers :slightly_smiling_face:

1 Like

I managed to create a fully dynamic system of user roles.

Through the frontend, I can easily create any new role, assign it to any user (the user can have any number of roles) and I can easily set rights for each role and each table not only for Adds, Updates, Delete, Read-only, but also whether it has access to the table (Security filter).
I’m testing and it works great so far.

Tables only
User_Roles
Users
Table_Restrictions
I also filter the data according to CustomerID.

Thanks for the info.

2 Likes

Nice to know you two have got it working. Just to complete the post thread for any future reader, here iss a relevant tip .

Flexible user role management - Google Cloud Community

Hi @Witan ,

If that information helped you get to an outcome would you mind marking my post as a solution?

Thanks :slightly_smiling_face:

Hello,

I can make my contribution and I hope it will be useful at some point.

I control this permission using 2 tables.

  1. Permission: List app features
  2. Permission of each User/collaborator

I attach prints of how I do it and it works very well.

This I Have made in my app. and it is easy to control.

https://www.googlecloudcommunity.com/gc/AppSheet-Q-A/DYNAMIC-USER-CONTROLS-EDIT-NO-ACCESS-ETC/td-p/509096

Expression is too big and lengthy.