Permissions on custom session properties

To give some context before my questions, I am moving a legacy codebase into Ignition Perspective. The codebase uses an SQL database to store permissions for users. The developer before me created a "globals" file where all permissions for the logged in user were retrieved from the database, and then stored in variables which are imported throughout the codebase.

I think the Session Custom properties feature could be useful for recreating this, since the properties can be different for each individual session, but are accessible throughout the project. I understand that you can set properties to "private", "protected", or "public", which is something I'd like to do. The problem I now have is that I have 100+ permission columns to go through and make protected, and a couple columns to make private.

I've created this structure to demonstrate my lengthy explanation.

  • If I set the object "testFolder" to private, is everything inside that object private as well?
  • If "testFolder" is private and "testPermission1" is protected, which one takes priority?
  • If the answer to the first question is no, is there an easier way to set 100+ properties to private without manually setting each one?

I did search for a while but couldn't find any documentation on how this works specific to custom session properties. Also tried accessing the properties in the browser dev console but couldn't find the object there despite using the search tool.

Turns out that you have to assign the property a value before it will show up in the browser dev console. You can't just leave it as the literal string "value". I should've realized that sooner.

After making a private object with a private string inside it, I can still see it in the dev console using this JavaScript code. Is this intended behavior? I would prefer to keep the permission properties out of view from the user, but now knowing this, not sure I can get around this.

__client.page.sessionCustom.root.value

See testObject object and values below it - all set to private yet still appearing in the dev console.

This could be out of context as it doesn’t relate to the issue you’re explicitly facing. However, what exactly are you trying to do with the sessions here? Are these perspective views meant to function sort of like a webapp, with custom RBAC built in on top of ignitions default provider? Which adds another question what is the structure of the RBAC you’re trying to implement?

I just need a globally accessible variable to store a permission from a SQL database. This was the best way I could find at the time of me initially posting, so maybe there is a better option. I just don't want to be querying the permissions table in every view locked behind permissions.

Are these perspective views meant to function sort of like a webapp, with custom RBAC built in on top of ignitions default provider?

Correct.

Which adds another question what is the structure of the RBAC you’re trying to implement?

Per user, 1 row from the database, with multiple columns. I made a table below with a demonstration of the database structure. I want to collect all of the permissions for the logged in user, store them in a custom session property, and then use them elsewhere in the project. I'd want to have one property per permission.

Username Permission1 Permission2 Permission3
user1 Yes No Yes
user2 No No Yes

After more tinkering, I have this script which seems to do what I want. The username comes from a text input box, but to simplify it I've just hardcoded it. Only problem now is figuring out how to keep these properties away from the user.

from util.auth import get_login_row
from util.const import LOGIN_COLUMNS # a list of column names from the db as strings

username = "testuser"
data = get_login_row(username) # pulls the row (all columns) from the database

user_globals = self.session.custom.userGlobals
	
for column in LOGIN_COLUMNS:
	user_globals[column] = data[column]

Example:

If possible I’d look in to refactoring that RBAC now that you’re migrating. Generally speaking assigning permissions to a user via columns is an anti-pattern. An example of the proper architecture would look something like this.

usersTable {
    id INT PRIMARY KEY NOT NULL IDENTITY(1,1) -- MSSQL Autoincrement pk 
    username VARCHAR(255) NOT NULL UNIQUE,
    -- Other user associated data
}

permissionsTable {
    id INT PRIMARY KEY NOT NULL IDENTITY(1,1) -- MSSQL Autoincrement pk
    name VARCHAR(255) NOT NULL UNIQUE,
    slug VARCHAR(255) NOT NULL UNIQUE,
}

userPermissionsTable {
    id INT PRIMARY KEY NOT NULL IDENTITY(1,1) -- MSSQL Autoincrement pk,
    userId INT PRIMARY KEY NOT NULL IDENTITY(1,1),
    permissionId INT PRIMARY KEY NOT NULL IDENTITY(1,1),
}

-- Maybe add a unique constraint on (userId, permissionId) to userPermissions table to make sure there isn't an overlap of permissions.
  • Why do we have a name, and then something called slug?
    • Names are for user inference, slug is for system inference.
  • Why is this better?
    • Because adding a new permission does not require a new column and checking permissions isn’t looping over the actual user object
def check_permissions(user, required_permission):
    if required_permission in user.permissions:
        return True
    return False

I agree, and I appreciate your insight. When I say "legacy", I mean at least 10-20 years. I know that's not much for some people but it is for me.

I'll look into whether I can redesign the existing database. The existing codebase isn't the most straightforward which is the reason for me porting it to Ignition.

I guess all that I need is just a way to make these properties not visible or writable to an end user. After changing them to private I can still see them in the dev console.