I would like to write mobile apps that use my Anvil app’s users and data.
What I’ve tried and what’s not working:
I’ve set up an Anvil app with a domain, enabled user management, and added an account (email, but google and facebook are enabled; I could forego them if they are problematic). I have the app set up so that all it does is require authentication on the main form.
I know I could use client uplink to access the data, however I’m just not sure that that’s what it was designed for. Can someone clarify if I’m to distribute one client uplink key with my app, or would it be better to use API endpoints? If I use API endpoints, should I just use the basic auth on them? Is it possible for each client to have its own uplink key?
This is all assuming that I can also implement authentication from the app against Anvil, but I’m saving that for another day, and I think I understand that challenge a little better.
You can absolutely create a mobile app that shares data back and forth from the app and uplink. You do not need to have a per user uplink key only a per app uplink key. If you want to distinguish data between users, you can just check which user is accessing the uplink function. Here we are receiving data from a user from server or client side using something like: anvil.server.call("receive_user_data", new_data)
This will call the registered server function, be it on the server or uplink, and providing the new_data as the argument.
require_user=True will enforce that this function can only be called by an authenticated user.
# running in your external uplink
import anvil.server
import anvil.users
from anvil.tables import app_tables
@anvil.server.callable(require_user=True)
def receive_user_data(data):
# check which user is sending data
from_user = anvil.users.get_user()
# Do your processing on the data... Maybe some validations
# Maybe we just store the data to a table
app_tables.user_data_table.add(user=from_user, data=data)
If you have more details on what you are trying to accomplish, there are lots of really smart and helpful people around here.
Thanks, @racersmith ! I am building apps with BeeWare, which is great for GUIs, but lacking in integrations for common things an app is going to need, like user management. I was familiar with Anvil already but hadn’t tried to use it outside of the regular app environment before.
I’d really love to be able to use Anvil for webapps and BeeWare for mobile and desktop apps; that’d give me Python in both places. The more closely I can integrate them the better and more slick it will be. It feels like a perfect marriage.
So an example would be having the mobile app interface with Anvil for user signup and authentication. I think this is probably going to work using a WebView to show and interact with the login form. From there, I will want to retrieve information about that the site that is public, as well as information specific to that user.
Let me get uplink set up in an app and at least get public information coming through via the uplink package and then I will report back.
BeeWare, interesting… Something to note is that Anvils apps can be installed as a Progressive Web App to give a native feel without the need to deploy android and iOS apps.
Or they can be made in a TWA app that can be published on Android and App stores using https://www.pwabuilder.com/
If you want to access native APIs too, you can make an Anvil app communicate with a mobile app framework using webviews - Native Android/IOS apps with Anvil
So I kinda got this to work in a janky way. I’m open to feedback. Here is a breakdown.
For simplicity, my Anvil app requires that all visitors log in. So right now, you visit the domain, get a login form, and after authenticating there is just a placeholder image shown.
The BeeWare app, for simplicity, also opens immediately to authentication. To accomplish this, the anvil-uplink module is used to make some calls to the Anvil app’s server modules and uses a WebView widget.
I make use of a tokens table that has the columns token, client_token, last_used, and email.
With that stage set, here is the process.
BeeWare app opens
BeeWare app makes a call to one of the Anvil app’s public server module functions using anvil-uplink. The server module function is initiate_login.
This initiate_login Anvil app function uses secrets.token_urlsafe(20) to make a “client token”, writes that into the tokens table, and returns the “client token” to the BeeWare app.
The BeeWare app makes a WebView widget and opens the site address with #?token={client_token} appended to it. The login form appears in the WebView widget. An async event handler on_webview_load starts executing.
The Anvil app’s main form that was just loaded looks for the client token in the query string. If there is one, a call to a server module function set_tokens is made, which has require_user=True set on its decorator.
The set_tokens function uses secrets.token_urlsafe(20) to make another token, and writes that token, datetime.date.today(), and the user['email'] from user = anvil.users.get_user().
The BeeWare app has been async polling another Anvil app server module function, find_token, passing its client token.
The find_token server module function looks in the tokens table to see if the given client token row has its other values populated, indicating the user successfully logged in. If so, it returns (row['token'], row['email']) and updates row['last_used'].
In the BeeWare app, the find_token call eventually returns the token and the user’s email.
The BeeWare app now has a “private token” and a “client token” and the user’s email, and is now ready to make other calls to the Anvil app, passing them to indicate the user authenticated.
This won’t work with Google or Facebook logins because the BeeWare WebView widget doesn’t pop out a browser window for those login methods. If there was some way to get directly at the Google login page that might work, but login_with_google only shows an Anvil login screen with the “log in with Google” button.
Anyway, I don’t know that I would use this for anything important, but if I make a little Anvil+BeeWare app that I need to quickly set up user management and data tables for, I now have the option!