-
I'm needing to programmatically create an account for a user, and then send them an email to set their password. My thought was I could just create the account, create a reset password key, and then send them a Welcome email with the reset password link in it. I'm not sure if this is the best way to do it, but I'm having trouble figuring out how to generate the reset password key. I know that the Rodauth Alternatively I could use the |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
You can access Rodauth instance methods through the internal request instance that you can initialize with So, I'd recommend going the internal request route. When calling Vanilla Rodauth examplerequire "roda"
require "sequel"
DB = Sequel.sqlite
DB.create_table :accounts do
primary_key :id, type: :Bignum
String :email, null: false
Integer :status_id, null: false, default: 1
String :password_hash
end
DB.create_table :account_verification_keys do
foreign_key :id, :accounts, primary_key: true, type: :Bignum
String :key, null: false
DateTime :requested_at, null: false, default: Sequel::CURRENT_TIMESTAMP
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
end
DB.create_table :account_password_reset_keys do
foreign_key :id, :accounts, primary_key: true, type: :Bignum
String :key, null: false
DateTime :deadline, null: false
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
end
DB.create_table :account_email_auth_keys do
foreign_key :id, :accounts, primary_key: true, type: :Bignum
String :key, null: false
DateTime :deadline, null: false
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
end
class RodauthApp < Roda
plugin :rodauth do
enable :create_account, :verify_account, :reset_password, :internal_request
set_deadline_values? true
hmac_secret SecureRandom.hex
account_password_hash_column :password_hash
base_url "https://example.com"
internal_request_configuration do
create_account_set_password? false
verify_account_set_password? false
send_verify_account_email { nil } # skip sending email
send_reset_password_email { nil } # skip sending email
end
end
end
class RodauthMailer
def welcome(account_id, reset_password_key)
@reset_password_link = rodauth.reset_password_url(key: email_token(account_id, reset_password_key))
p @reset_password_link
end
private
def email_token(account_id, key)
"#{account_id}_#{rodauth.compute_hmac(key)}"
end
def rodauth
RodauthApp.rodauth.allocate
end
end
RodauthApp.rodauth.create_account(login: "user@example.com")
RodauthApp.rodauth.verify_account(account_login: "user@example.com")
RodauthApp.rodauth.reset_password_request(login: "user@example.com")
account_id = DB[:accounts]
.where(email: "user@example.com")
.get(:id)
reset_password_key = DB[:account_password_reset_keys]
.where(id: account_id)
.get(:key)
RodauthMailer.new.welcome(account_id, reset_password_key) In Rails, you'd probably have something like this: class RodauthMain < Rodauth::Rails::Auth
configure do
enable :create_account, :verify_account, :reset_password, :internal_request
internal_request_configuration do
create_account_set_password? false
verify_account_set_password? false
send_verify_account_email { nil } # skip sending email
send_reset_password_email { nil } # skip sending email
end
end
end RodauthApp.rodauth.create_account(login: "user@example.com")
RodauthApp.rodauth.verify_account(account_login: "user@example.com")
RodauthApp.rodauth.reset_password_request(login: "user@example.com")
account = Account.find_by!(email: "user@example.com")
reset_password_key = account.password_reset_key.key
RodauthMailer.welcome(account.id, reset_password_key) An alternative solution that doesn't require using password reset could be to send an account verification link, where the user would be asked to set the password on verification. The configuration for that could look like this: class RodauthMain < Rodauth::Rails::Auth
configure do
enable :create_account, :verify_account, :internal_request
create_account_set_password? true # assuming this is what you want by default
verify_account_set_password? { !has_password? }
internal_request_configuration do
create_account_set_password? false
send_verify_account_email { nil } # skip sending email
end
end
end RodauthApp.rodauth.create_account(login: "user@example.com")
account = Account.find_by!(email: "user@example.com")
account_verification_key = account.verification_key.key
RodauthMailer.welcome(account.id, account_verification_key) class RodauthMailer < ApplicationMailer
def welcome(account_id, account_verification_key)
@account_verification_link = rodauth.verify_account_url(key: email_token(account_id, account_verification_key))
# ...
end
# ...
end |
Beta Was this translation helpful? Give feedback.
You can access Rodauth instance methods through the internal request instance that you can initialize with
Rodauth::Rails.rodauth
. However, in many cases, these methods are relying on certain state being set. In this case,#create_reset_password_key
relies on@reset_password_key_value
, which is set by calling#generate_reset_password_key_value
, which is a private method.So, I'd recommend going the internal request route. When calling
reset_password_request
, you could disable sending the email in internal request configuration, and send the welcome email instead. Here is a self-contained example showing this:Vanilla Rodauth example