Hi there,
I am currently using the custom sign-up flow as a dependency for a login device for my app. However, something seems to be off with the email confirmation. When registering, the email gets send to the address properly, but when clicking on the link, it does not set the confirmed_email variable to True and also does not login the user. It simply shows the login page.
I tried this in debug mode and publication mode, both do not work.
Code Sample:
this is the login button click
def button_1_click(self, **event_args):
custom_signup.login_flow.login_with_form()
self.update_login_status()
user = anvil.users.get_user()
if user is None:
alert("Login failed. Please try again.")
return # Exit the function if no user is logged in
Globals.user_email = user["email"]
this is the confirmation link to be sent out. I tried with {anvil.server.get_app_origin(‘published’)}#?email={url_encode(user[‘email’])}&confirm={url_encode(user[‘link_key’])} in published mode and {anvil.server.get_app_origin()}#?email={url_encode(user[‘email’])}&confirm={url_encode(user[‘link_key’])} in debug mode. both fails.
@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()
anvil.email.send(to=user['email'], subject="Confirm your email address", text=f"""
Hi,
Thanks for signing up for our service. To complete your sign-up, click here to confirm your email address:
{anvil.server.get_app_origin('published')}#?email={url_encode(user['email'])}&confirm={url_encode(user['link_key'])}
Thanks!
""")
return True
This is the function that should identify the hashed content:
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:
if not anvil.server.call('_is_password_key_correct', h['email'], h['pwreset']):
alert("This is not a valid password reset link")
return
while True:
pwr = PasswordResetDialog()
if not alert(pwr, title="Reset Your Password", buttons=[("Reset password", True, 'primary'), ("Cancel", False)]):
return
if pwr.pw_box.text != pwr.pw_repeat_box.text:
alert("Passwords did not match. Try again.")
else:
break
if anvil.server.call('_perform_password_reset', h['email'], h['pwreset'], pwr.pw_box.text):
alert("Your password has been reset. You are now logged in.")
else:
alert("This is not a valid password reset link")
elif 'confirm' in h:
if anvil.server.call('_confirm_email_address', h['email'], h['confirm']):
alert("Thanks for confirming your email address. You are now logged in.")
else:
alert("This confirmation link is not valid. Perhaps you have already confirmed your address?\n\nTry logging in normally.")
This is the server function that should be called once the hased content had been validated:
@anvil.server.callable
def _confirm_email_address(email, confirm_key):
"""Confirm a user's email address if the key matches; return True if it did."""
user = get_user_if_key_correct(email, confirm_key)
if user is not None:
user['confirmed_email'] = True
user['link_key'] = None
anvil.users.force_login(user)
return True
This is the link that got sent in the debug mode (I inserted a fake email-address for the Q&A here):
“https://my_app.anvil.app/debug/UHWIYGG2JYGP5H2OR62VFXI3A7VIRJAM%3DCA6OOJX4STN5V4DHZGIODP7K#?email=my_email%40gmail.com&confirm=IX5VAyvDiYACJ2”
This is the email link in publication mode (I inserted a fake email-address and app name for the Q&A here):
“https://my_app.anvil.app?email=my_email%40gmail.com&confirm=VBFMbrzvTgscj8”
Would be great, if anyone had an idea on how to fix this.