Files
fizzy/app/models/user/email_address_changeable.rb
T
2025-11-17 09:12:41 -05:00

55 lines
1.6 KiB
Ruby

module User::EmailAddressChangeable
EMAIL_CHANGE_TOKEN_PURPOSE = "change_email_address"
EMAIL_CHANGE_TOKEN_EXPIRATION = 30.minutes
extend ActiveSupport::Concern
def change_email_address_using_token(token)
parsed_token = SignedGlobalID.parse(token, for: EMAIL_CHANGE_TOKEN_PURPOSE)
if parsed_token.nil?
raise ArgumentError, "The token is invalid"
elsif parsed_token.find != self
raise ArgumentError, "The token was generated for a different user"
elsif identity.email_address != parsed_token.params.fetch("old_email_address")
raise ArgumentError, "The token was generated for a different email address"
else
new_email_address = parsed_token.params.fetch("new_email_address")
change_email_address(new_email_address)
end
end
def send_email_address_change_confirmation(new_email_address)
token = generate_email_address_change_token(
to: new_email_address,
expires_in: EMAIL_CHANGE_TOKEN_EXPIRATION
)
IdentityMailer.email_change_confirmation(
email_address: new_email_address,
token: token,
user: self
).deliver_later
end
def change_email_address(new_email_address)
transaction do
new_identity = Identity.find_or_create_by!(email_address: new_email_address)
update!(identity: new_identity)
end
self
end
private
def generate_email_address_change_token(from: identity.email_address, to:, **options)
options = options.reverse_merge(
for: EMAIL_CHANGE_TOKEN_PURPOSE,
old_email_address: from,
new_email_address: to,
)
to_sgid(**options).to_s
end
end