# Changing a user's email address: the new one takes effect only once a
# link mailed to it is followed, and the old one hears about it.
module EmailChangesController do
implements Controller
alias Auth
alias Mailers.EmailChangesMailer
def new(ctx) do
skip_authorization
email_address = Auth.signed_in_user(&ctx)?.email_address.clone()
render email_address: email_address, title: "Change your email address"
end
# Says the same whether or not the address is taken, so the page doesn't
# reveal who has an account; a taken address never gets the link.
def create(ctx) do
skip_authorization
user = Auth.signed_in_user(&ctx)?.clone()
new_email = User.normalize_email(¶ms[:email_address])
if User.find_by(email_address: &new_email)!.is_none() do
user.unconfirmed_email = Some(new_email.clone())
user.save()!
link = url_for(email_change_path(&user.email_change_token()))?
EmailChangesMailer.confirm(&new_email, &link).deliver_now()!
end
redirect "/", notice: "Check #{new_email} for a link to confirm it."
end
# The link from the mail: it needn't be followed signed in.
def show do
case User.find_by_email_change_token(¶ms[:token])! do
Some(found) ->
user = found
old_email = user.email_address.clone()
if user.confirm_email_change()! do
EmailChangesMailer.changed(&old_email, &user.email_address).deliver_now()!
redirect "/", notice: "Your email address is now #{user.email_address}."
else
redirect "/", alert: "That address is taken now."
end
nil -> redirect "/", alert: "That link is invalid or has expired."
end
end
end