Session Prop Auth, dictionaries and lists

For the session.prop.auth object:

We have a nested security level such as:

Authenticated
Authenticated/Roles
Authenticated/Roles/Level1
etc...

And it looks like this:

{"children":[
	{"children":[
		  {"children":[],"name":"Level1"},
		  {"children":[],"name":"Level2"}
	],"name":"Roles"}
],"name":"Authenticated"}

I am trying to determine if the user is:

  • Authenticated (I think I got this one)
  • Or has Level1 clearance
    I have not been successful at getting into the list of roles yet.

I have this so far, but I get lost on looping through and checking values in the list:

for i in dict1.keys():
	for x in dict1[i]:
		print(x)

This results in printing out the whole list of roles, then the word Authenticated printed one letter per line afterwards.

Thanks in advance!

Don't attempt to script this - use the built in expression function:

Well, I am looking for a solution for a dynamic tabbed container, or tabbed header of sorts, drawing the menu options from a query, referencing a post here: Dynamically Selecting Pages in Tab Container - #13 by mdemaris

I know how to use this function elsewhere, but how would I get authentication on a dynamic menu, if I don't have another source that I can use?

My idea is either I have a table with the Roles and Menu Items with a flag indicating which menu a role can access, OR build a script that pulls the info from session.prop.auth and check if their role is listed. If I use isAuthorized coded to each tab, or button, the menus will change based on what work area the user is in and which roles they have.

UNLESS, (thinking out loud) I create a button for every menu item and hide it based on authentication, which is a lot of buttons, but it might make things easier for programming views and, as you indicated, using isAuthorized.

Bottom line, trying to replicate a Vision tab strip and do away with some funky DB stuff on the OG setup. Such as storing the path and user names in tables, one table for each menu item...

This smells like something that needs clarifying.
You can write the exact same thing like this, which should make things easier to understand:

for value in dict1.values():
    for item in value:
        print item

Note how in the outer loop we're calling the values() method, and in the inner one we're not ?
The print statement will print each item in whatever value is. If it's a dict or a list, or any iterable, it will print its elements.
If its a string... the elements are characters.

When you're dealing with nested structures like this, the usual solution is to use recursion, so that each level can be handled like the one before.
Unless you have a strict structure with a known maximum depth level that's only 1 or 2, in which case you can get away with dealing with each level, ie:

for k, v in full_dict.items():
    if k == 'roles':
        if 'something' in v['children'].values():
            do_something()
    elif isinstance(v, list):
        do_something_else()

The recursive version would look like this (pseudo code):

function walk(node)
    for each item in node children:
        if item has children:
            walk(item)
        else:
            handle_leaf()

Ok, some thoughts here.
k does not equal roles, it equals children, specifically the first instance; then it equals name, specifically the last instance. So, we are moving through the first layer OK.

I changed the names a little because it might get confusing which children I was getting, like this:

{"children1":[
	{"children2":[
		  {"children3":[],"name3":"Level1"},
		  {"children4":[],"name4":"Level2"}
	],"name2":"Roles"}
],"name1":"Authenticated"}

In testing this:

an error is thrown:

TypeError: list indices must be integers

changing index to v[0] results in this error:

AttributeError: 'str' object has no attribute 'values'

If I remove the .values() from v[0], and print v[0], I get this:

{'children2': [{'children3': [], 'name': 'Level1'}, {'children4': [], 'name': 'Level2'}], 'name': 'Roles'}

Next, how do I get into v[0]? For each children, there is a list within that dictionary.

This is getting me closer:

for k, v in dict1.items():
	print(k,v)
	if 'name2' in v[0]:
		print(v[0])
		print(v[0].keys())
		print(v[0].values())
		for j, m in v[0].items():
			print(j)
			print(m)

If I go another level into m, that should get me the key:value pairs I am looking for.

What about the similar scripting function:
system.perspective.isAuthorized(isAllOf=True, securityLevels=['Authenticated/Roles/Level1'])

1 Like

I was only doing "conceptual code", but if you want I can make you something directly usable.
Though it seems to me there should be a better way.

Also, note that if the data structure seems too hard to use, or too convoluted... Maybe it can be reworked.

The goal was to create two dynamic Tab Containers, using the main query for the first container, and based on the tab index or name, grab the appropriate sub-tabs. I thought I could search/navigate the security roles somehow that would be more modular or dynamic and allow for Tabs to have different security levels (based on who and where, of course).

What is has turned into is really understanding the levels of dictionaries, lists and tuples and how to successfully navigate them if needed. I decided to drop the Tab Containers, and create dual-level button header, and code the security level based on the display order from left to right. That way, if a user has access to one of the main menu options, and only access to one of the sub-menu options, I can allow for that.

I think I'm going to close this thread, pretty sure I can figure out the rest of the list/tuple if I really need to go that far. I do feel a solid understanding is good to have and you all have helped me discover more on the dictionary and list functions, some which are not mentioned in the docs, but are included in Python language natively.