I have uplink instances running on multiple computers that access resources that are local to each computer. When a user on one of these computers visits my Anvil web app, the app should communicate with the uplink instance running on their machine. The user should not see or be aware of other uplinks/computers.
I found resources explaining how to handle multiple uplink instances with the same functions, by generating decorators with unique IDs (forum links at end of post).
What I am struggling to understand is how these unique IDs can get transferred to the web app, so that the running instance of the web app communicates with the correct uplink.
A few approaches that Iâve considered:
A âwhich computer are you on?â drop down. This does not meet the requirement that users should not be aware of other computers.
Make the unique ID based on public IP, which can be determined in the uplink code as well as the server code. However, it is possible for multiple computers to have the same public IP, so this wonât work.
Run anvil app server and runtime on each computer. This would work. But it less desirable than having a true web app with only a small python uplink running on the computer.
How do your users get the uplink script to run on their computer? Is there any way that you could have them set up a credentials file, or a setup âinstallerâ script that could set environmental variables?
You could then use the users service, and have them log in on the client side, with a matching login from the machine they are running.
If that is the case, then you could set the ID for the function decorator in the uplink when you give the uplink script for download and store the same ID on the Users table. At this point both uplink script and front end know each other.
Edit: @ianb Wow, same advice at the same time, but yes, yours arrived a second, maybe even two before mine, I do owe you a coke!
If I understand correctly, the question seems to be, âhow can the browser instance of the Client App reliably learn which machine itâs running on?â independent of anything that the User knows.
@ianb and @stefano.menci, thank you for the suggestions. I get what youâre saying and that is a route I will try out. My plan for distributing the uplink script was to use Pyinstaller to generate an executable and let the executable out into the wild for download on our support portal and (like it or not) getting sharing between people. So I would need to rethink that with what you are suggesting.
For some more detail, the local resource that the uplink script interacts with is a serial port or network interface card. And the web app is a tool for configuring a piece of hardware. The tool will be used by my coworkers (engineers, QA, support, installers) and probably some customers. I was not planning to implement users and logins. Its a case of âif you have the hardware connected, you have the right to configure itâ. There arenât security concerns of people accessing the web app who donât have the hardware, so I hesitate to make users create yet another login.
@p.colbert, yes, you are correct. That is the question I have. And if the answer is âthe client app cannot knowâ, then what other options do I have?
How about when the uplink script is run, it prints to the screen/terminal a code, which the user must enter on the web client. That code is the name of the local function that get registered via uplink.
Itâs not really an account, more like a single word One Time Password.
You could either have that as the permanent password, have it save somewhere. That way, once itâs been entered once it would remain until renewed (eg run with --force-renew-id). Or it could simply be different every time you run it.
If the user with the front end has access to the uplink, then I like @david.wylieâs idea.
I would add a little bit of automation: when the uplink start, it will generate a random ID, maybe a 4-character string easy to remember and type, print it so the user sees it, then call a function on the server saying this is my ID. At this point the server knows what uplink started last and from what IP, so it can do an educated guess about what ID to use. If there is only one ID generated on the correct time range and from the same IP address / the same geographical area, use it, otherwise show a list to pick from, maybe filtered by the geographical distance.
I have used the machines unique identifier UUID before, it should work on windows and linux. If I am storing it for later I would hash it, if you are using something like @david.wylie suggested, I would also hash it, but use a significantly shorter number of digits.
Something like the problem solved here:
You might even combine all three ideas (a dropdown, a login, and a unique identifier generated on installation / uplink script run-time) and create a system where no login is required, but if you created one you could âsaveâ your machine ID and be able to give it a nickname, and when storing more than one machine id have them available for selection in a user-specific dropdown.
This way users could choose to put in the code every time, or create a login and be able to access many machines though just one client page. The anvil users service is very simple to use, and supports zero password OTP via email only logins and you can configure how often a client would have to log in, etc.
What about a âGenerate uplink IDâ button on the app that says âPlease download this file and save it on the same folder with the uplinkâ. The button will generate a text file with an unique ID and offer to download it.
The user will save that file on the uplink folder. At this point the uplink will read the ID from that file. If the file is not there, it will ask the user to go to the app and generate one.
EDIT
Some message should be printed by both uplink and âGenerate uplink IDâ button to make it clear that the id file shouldnât be copied to another computer.
⌠but at the end of the day, this is very similar to @david.wylie solution where the uplink generates the ID and you need to copy it to the form.
Thank you everyone for the thoughtful suggestions. I am encouraged to continue using Anvil for future projects because of you all. This definitely points me towards a usable solution.
I think a short string that is displayed on the uplink script GUI that the user copies into the web client will work great. People are used to this sort of interaction, like registering apps on smart TVs and 2-factor identification.
On the PC side, I will store the string to a config file. On the web client side, I think I will experiment with Cookies so that the user does not have to enter the string every visit. In reality, once our products are configured they are unlikely to need this tool again, so 30 day cookies is more than sufficient.