# Session Prop Auth, dictionaries and lists

**URL:** <https://forum.inductiveautomation.com/t/session-prop-auth-dictionaries-and-lists/93260>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [July 15, 2024, 10:11pm UTC](https://forum.inductiveautomation.com/t/session-prop-auth-dictionaries-and-lists/93260 "2024-07-15T22:11:41Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [July 15, 2024, 10:11pm UTC](https://forum.inductiveautomation.com/t/session-prop-auth-dictionaries-and-lists/93260/1 "2024-07-15T22:11:41Z")

</div>

For the `session.prop.auth` object:

We have a nested security level such as:

```python
Authenticated
Authenticated/Roles
Authenticated/Roles/Level1
etc...

```

And it looks like this:

```python
{"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:

```python
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!

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [July 15, 2024, 10:13pm UTC](https://forum.inductiveautomation.com/t/session-prop-auth-dictionaries-and-lists/93260/2 "2024-07-15T22:13:22Z")

</div>

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

> **[isAuthorized | Ignition User Manual](https://www.docs.inductiveautomation.com/docs/8.1/appendix/expression-functions/users/isAuthorized)**
>
> Returns a qualified value with a boolean value which is true if the user in the current Session is authorized, false otherwise.

---

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [July 15, 2024, 11:09pm UTC](https://forum.inductiveautomation.com/t/session-prop-auth-dictionaries-and-lists/93260/3 "2024-07-15T23:09:25Z")

</div>

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](https://forum.inductiveautomation.com/t/dynamically-selecting-pages-in-tab-container/93196/13)

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...

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 16, 2024, 6:39am UTC](https://forum.inductiveautomation.com/t/session-prop-auth-dictionaries-and-lists/93260/4 "2024-07-16T06:39:53Z")

</div>

> [@mdemaris](#):
>
> ```python
> 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.

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

```python
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:

```python
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):

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

```

---

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [July 16, 2024, 10:53pm UTC](https://forum.inductiveautomation.com/t/session-prop-auth-dictionaries-and-lists/93260/5 "2024-07-16T22:53:14Z")

</div>

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:

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

```

In testing this:

> [@pascal.fragnoud](#):
>
> `if 'something' in v['children'].values():`

an error is thrown:

```python
TypeError: list indices must be integers

```

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

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

```

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

```python
{'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:

```python
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.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [July 17, 2024, 5:24am UTC](https://forum.inductiveautomation.com/t/session-prop-auth-dictionaries-and-lists/93260/6 "2024-07-17T05:24:36Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 17, 2024, 7:28am UTC](https://forum.inductiveautomation.com/t/session-prop-auth-dictionaries-and-lists/93260/7 "2024-07-17T07:28:17Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [July 17, 2024, 5:02pm UTC](https://forum.inductiveautomation.com/t/session-prop-auth-dictionaries-and-lists/93260/8 "2024-07-17T17:02:54Z")

</div>

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.
