Hi! I’m building out an Anvil project that has users submit some information in an ‘unsecure’ form, at then at some point requires them to set up an actual user before moving into the ‘secure’ part of my app.
My app Startup Form is currently set up as the first step in this overall workflow (so unsecured).
I would like a user’s email confirmation link to direct the user directly to the ‘secure’ part of the app, since they’ve already completed that part of the workflow.
I can’t figure out the best way to do this. I had thought some logic in the init of my initial form might do it: If the user came from a routing with “/_/email-confirm/” I could redirect them. But, I can’t figure out how to even get the inbound request URLs, and I’m not sure if this is the right approach in the first place!
Any ideas? Thank you!
Hi @danbolinson and welcome to the forum.
The custom login flow dependency does this with a url_hash
rather than an http end point…
here’s some code snippets from the custom login flow module that might give you some ideas:
from anvil.http import url_encode
@anvil.server.callable
def _send_email_confirm_link(email):
"""Send an email confirmation link if the specified user's email is not yet confirmed"""
user = app_tables.users.get(email=email)
if user is not None and not user['confirmed_email']:
if user['link_key'] is None:
user['link_key'] = mk_token()
google.mail.send(to=user['email'], subject="Confirm your email address", text="""
Hi,
Thanks for signing up for our service. To complete your sign-up, click here to confirm your email address:
%s#?email=%s&confirm=%s
Thanks!
""" % (anvil.server.get_app_origin('published'), url_encode(user['email']), url_encode(user['link_key'])))
return True
def do_email_confirm_or_reset():
"""Check whether the user has arrived from an email-confirmation link or a password reset, and pop up any necessary dialogs.
Call this function from the 'show' event on your startup form.
"""
h = anvil.get_url_hash()
if isinstance(h, dict) and 'email' in h:
if 'pwreset' in h:
...
elif 'confirm' in h:
if anvil.server.call('_confirm_email_address', h['email'], h['confirm']):
anvil.alert("Thanks for confirming your email address. You are now logged in.")
else:
anvil.alert("This confirmation link is not valid. Perhaps you have already confirmed your address?\n\nTry logging in normally.")
Docs and Clone link can be found here:
Anvil Docs | Custom user authentication
2 Likes
Great, thanks for linking to this, this is helpful!
I had been trying the get_url_hash method but it kept coming up empty. On closer inspection I guess that’s because the anvil standard email confirmation emails are structured like:
https://APPNAME.anvil.works/_/email-confirm/ENCODEDEMAIL/TOKEN
In other words - no hash!
I’d been hoping to avoid going the route of custom authentication however. I wonder if this is a suitable feature request? It would be helpful to ‘catch’ inbound emails from the standard anvil registration work-flow and it seems like the get_url_hash is perfectly suited here?
I have used a blank landing page that checks to see if the user has ever visited the page before to route traffic (based on a cookie) to direct traffic and that’s working.
Thanks again!
1 Like