# Workaround to access Perspective user source from Gateway

**URL:** <https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900>\
**Category:** Ignition\
**Tags:** ignition81, perspective\
**Created:** [January 29, 2024, 3:21pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900 "2024-01-29T15:21:41Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![ian.sebryk](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ian.sebryk/32/49319_2.png) [@ian.sebryk](https://forum.inductiveautomation.com/u/ian.sebryk)\
**Post date:** [January 29, 2024, 3:21pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/1 "2024-01-29T15:21:41Z")

</div>

i need a workaround to be able to access the Perspective project's user source from the Gateway scope. i'm tasked with building a granular alarm roster and i'm boned because _none_ of the Perspective project stuff is available from the Gateway scope (as i understand from support). so i can't help but wonder if someone has come up with a clever workaround for this problem. not having the depth of Ignition knowledge i'd like yet, i'm not familiar with what can and can't be accessed from the Gateway scope that the Perspective project can write to. my thinking is the project can write to some Gateway-accessible maguffin so when i build my alarm roster, i can get that user source name and data.

---

<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:** [January 29, 2024, 3:50pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/2 "2024-01-29T15:50:50Z")

</div>

Can you expand upon what you mean a bit more?  
The gateway and perspective are both running on the same JVM, meaning the same memory, etc - sharing information is "easy" between the two. From some arbitrary gateway context you can't _directly_ run (most) Perspective scripting, because your script doesn't have the implicit contextual info to know what Perspective "thing" to talk to. You can still pass that Perspective info manually using kwargs on the functions, though, and they'll still work.

---

<div class="post-metadata">

**Author:** ![ian.sebryk](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ian.sebryk/32/49319_2.png) [@ian.sebryk](https://forum.inductiveautomation.com/u/ian.sebryk)\
**Post date:** [January 29, 2024, 4:07pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/3 "2024-01-29T16:07:55Z")

</div>

if i run `system.tag.readBlocking('[System]Client/System/UserSource')[0].value` in a project, i get the name of the user source: `SpankytownRacers`. if i run the same thing building a custom alarm roster, i get `None`. according to tech support this only works in Vision because Gateway doesn't have access to the Perspective project's session objects.

---

<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:** [January 29, 2024, 4:14pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/4 "2024-01-29T16:14:27Z")

</div>

That's a pretty poor explanation of what's going on here.

I would explain it as "all of the tags in the Client folder, under the System tag provider, are provided _by the Vision module_, and only exist in its scope".

But I'm still confused. You mention alarm rosters (Gateway scoped, user sources) and then Perspective session objects (Gateway/Perspective scoped, identity providers) - I don't see how you're trying to tie the two together. You don't even use user sources (directly) in Perspective, so anything you're doing is going to ultimately be fragile (what if you change your project to a non-Ignition IdP?)

If you're actually asking "given a particular project's name, how can I retrieve the user source assigned in it's general properties" - that's a fair question, and answerable. I _think_ that's what you're asking, but all the Perspective stuff is throwing me off.

---

<div class="post-metadata">

**Author:** ![ian.sebryk](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ian.sebryk/32/49319_2.png) [@ian.sebryk](https://forum.inductiveautomation.com/u/ian.sebryk)\
**Post date:** [January 29, 2024, 4:31pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/5 "2024-01-29T16:31:37Z")

</div>

okay. more detail:

we have a very granular, per-asset permission system. it included notification settings for each asset in a project so some people are notified only for their assigned assets. to that end, we need to build a custom roster for asset alarms that are assigned. in other words, a project handles data for 6 assets. 2 of those assets are assigned to one guy, 3 to another, and all 6 to yet a third. when an alarm pipeline is triggered, an alarm notification needs to go ONLY to the assigned guy. and as you can see, there's some overlap.

so. i built a script that generates that email roster based on the granular permissions of each asset. works perfectly in a Perspective view. when i translocate it to the Pipeline Block Editor's Notification block, the script generates an empty list because the code that points to the user source doesn't return the name of the project's user source, it returns `None`. so nothing gets sent out; an empty list means no emails/SMS messages. and since this is on a Master project, i am unable to hardcode the user source because each leaf (?) needs to define it's own user source.

from my conversation with tech support, the reason i get `None` is because the Gateway apparently cannot access the project's Perspective attributes. basically the same reason the Script Console is functionally useless for Perspective testing.

so, okay, software limitation. time for a workaround, because this is critical for our clients. which brings us to the question i posted.

does that clarify better? 🤞

EDIT: a (better) screenshot to help visualize what i'm talking about ↓ and this is _ **per user** _:

 ![Screenshot 2024-01-29 093744](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/2/c2486262ae173483ff7b98138250ccf8383e64e5.png)

---

<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:** [January 29, 2024, 4:41pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/6 "2024-01-29T16:41:00Z")

</div>

Sort of? I understand the problem you're describing, but still not quite _why_ it's a problem.

What are you retrieving/doing/whatevering in this script that actually requires Perspective? Just the user source piece? Could you elevate this generated list to a tag somewhere, so you can easily read/bind to it in Perspective _and_ alarm pipelines?

From the outside looking in, with no knowledge of actual operational complexities (my preferred place to be 😄) it really sounds like this data should either be calculated once and _stored_ somewhere (a database, or failing that, in the tag system in Ignition) **or** if it has to be calculated repeatedly, there should be a single project library script that relies on no implicit context and is "pure" - it should take user source, asset identifier, etc as inputs, and return your list of users (or whatever) as the sole output.

Basically, my stumbling block is these two sentences:

> i built a script that generates that email roster based on the granular permissions of each asset. works perfectly in a Perspective view.

Because I don't see how calculating the "granular permissions of each asset" should have any reliance on anything provided by Perspective at all.

---

<div class="post-metadata">

**Author:** ![ian.sebryk](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ian.sebryk/32/49319_2.png) [@ian.sebryk](https://forum.inductiveautomation.com/u/ian.sebryk)\
**Post date:** [January 29, 2024, 5:41pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/7 "2024-01-29T17:41:04Z")

</div>

i'm still digesting... and please know i've had basically 2wks of ramp on Ignition before just being thrown into the mix, so i fully admit to being functionally stupid a lot of times as to things Ignition. but i do have a fair amount of developer experience. so forgive me if my terms are not from the Ignition lexicon. 😜 i promise i'm not trying to be obtuse! 🙂

so. it feels like i'm missing something important, and it's niggling in the back of my brain... but until it pops, let me explain a bit more.

because our end-user is bascially on par with a box of rocks in terms of computer literacy, we have to make everything (every. damn. thing) retard-proof. to that end, we have, from what i understand, 2 user data 'sources': 1 is Ignition, which provides authentication and _overarching_ roles (basically a global permission). then each project also has a set of datasets in the user source that provide the granular permissions _per asset_ **and** _per user_. see hopefully useful image ↓  
 ![Screenshot 2024-01-29 103347](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/6/e6b331b5238268bfe66c5f36930bae9ba029afc1.png)

so. from the Alarm pipeline's Custom Roster, which as i understand is Gateway scoped, i need to access that Project's User Source to _then_ pull the data from the dataset for determining who gets the notification. which apparently is NOT doable because, so i was told, the Gateway cannot see those datasets because they are in a scope it can't access. if this is not the correct way, i'm all ears, believe me. with my limited knowledge and going by what i've inherited, this seemed the best way to go.

any clearer? 🤞 🤞 🙏

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [January 29, 2024, 6:13pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/8 "2024-01-29T18:13:38Z")

</div>

> [@ian.sebryk](#):
>
> the Gateway cannot see those datasets because they are in a scope it can't access.

Tags are Gateway Global.

They can be reached from anywhere. The exception are tags located in the Vision Client Tags, which are only available in Vision Client Scope.

What you have indicated as a "User Source" is not a User Source, it is a Tag Provider. Tag Providers are found on the Gateway Webpage at Config \> Tags \> Realtime Tag Providers

User Sources would be found under Config \> Security \> UserSources

---

<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:** [January 29, 2024, 6:32pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/9 "2024-01-29T18:32:16Z")

</div>

You should also be able to 'back into' a tag provider from an alarm by examining the path.

---

<div class="post-metadata">

**Author:** ![ian.sebryk](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ian.sebryk/32/49319_2.png) [@ian.sebryk](https://forum.inductiveautomation.com/u/ian.sebryk)\
**Post date:** [January 29, 2024, 6:50pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/10 "2024-01-29T18:50:01Z")

</div>

oh! okay. so the guys here are using the wrong terms. great. 💩 but that **does** help explain why my question was confusing. i will amend moving forward as well as browbeat the dudes here.

_... interval with tech support's callback ..._

okay. turns out i'm just looking for love in all the wrong places. using the `event.source`, i can parse the resultant string and get the `prov:` from that. solved my problem. which i believe is what you, @paul-griffith, were saying about 'backing into a tag provider'.

please accept my apologies for bad term use, which resulted in a lot of unnecessary confusion. and i offer my thanks for your incredible patience. you're all champs, and i appreciate all your help. 💯

EDIT: `event.source` yields a lovely mess: `prov:Whitewater:/tag:Alarms/debugAlarmTrip:/alm:Alarm`. no spaces. random colons. so fun to parse. 🍴

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [January 29, 2024, 7:11pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/11 "2024-01-29T19:11:14Z")

</div>

> [@ian.sebryk](#):
>
> i can parse the resultant string and get the `prov:`

I'm not sure what type you're getting back, but there may be a "better" way to get the provider than by string parsing.

---

<div class="post-metadata">

**Author:** ![ian.sebryk](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ian.sebryk/32/49319_2.png) [@ian.sebryk](https://forum.inductiveautomation.com/u/ian.sebryk)\
**Post date:** [January 29, 2024, 7:14pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/12 "2024-01-29T19:14:06Z")

</div>

> [@lrose](#):
>
> but there may be a "better" way

i just edited my last post. yeah. i _wish_ there was a better way, but it doesn't look like it. 😵‍💫

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [January 29, 2024, 7:15pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/13 "2024-01-29T19:15:46Z")

</div>

This is in an alarm pipeline? Where is this script being called from? Trying to figure out what `event.source` is.

---

<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:** [January 29, 2024, 7:28pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/14 "2024-01-29T19:28:53Z")

</div>

> [@ian.sebryk](#):
>
> so fun to parse.

It's a `QualifiedPath`, which there's helpfully a static method to parse:

> **[QualifiedPath](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.36/com/inductiveautomation/ignition/common/QualifiedPath.html#parse(java.lang.String))**
>
> declaration: package: com.inductiveautomation.ignition.common, class: QualifiedPath

But to @lrose' point, may still not be necessary.

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [January 29, 2024, 7:38pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/16 "2024-01-29T19:38:12Z")

</div>

Okay, looks like the object is a QualifiedPath.

So you can just use:

```auto
event.source.firstPathComponent

```

Which will return the first component of the path, in this case the provider.

For instance this code:

```auto
from com.inductiveautomation.ignition.common import QualifiedPath

path = QualifiedPath.parse('prov:Whitewater:/tag:Alarms/debugAlarmTrip:/alm:Alarm')

print path.firstPathComponent

```

returns `Whitewater`

If you would like it to be more explicit then you could use:

```auto
event.source.getPathComponent('prov')

```

The first will be more performant though.

To go one step further you could then use it to build a tagPath for your call to get the dataset:

```auto
from com.inductiveautomation.ignition.common import QualifiedPath
from com.inductiveautomation.ignition.common.tags.paths import BasicTagPath

path = QualifiedPath.parse('prov:Whitewater:/tag:Alarms/debugAlarmTrip:/alm:Alarm')

tagPath = BasicTagPath(path.firstPathComponent,['Users','allassets'])

print tagPath.toStringFull()

```

Output:

```auto
>>> 
[Whitewater]Users/allassets
>>>

```

---

<div class="post-metadata">

**Author:** ![ian.sebryk](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ian.sebryk/32/49319_2.png) [@ian.sebryk](https://forum.inductiveautomation.com/u/ian.sebryk)\
**Post date:** [January 29, 2024, 7:44pm UTC](https://forum.inductiveautomation.com/t/workaround-to-access-perspective-user-source-from-gateway/84900/17 "2024-01-29T19:44:24Z")

</div>

okay. that's friggin' awesome. 💯 🥳 that's **exactly** what i needed. cannot express how awesome this is.

dammit. imma have to learn Kotlin...
