fix: correct user activation and password reset logic

- Change `user.send(:activate)` to `user.activate` for clarity.
- Fix typo in email parameter from `emial` to `email` in password reset.
- Update render calls to include status codes for better error handling.
- Modify password reset email method to accept a user parameter.
- Update tests to reflect changes in password reset functionality.

These changes improve the clarity of the user activation process and
ensure that the password reset functionality works correctly with
proper error handling and user feedback.
This commit is contained in:
songtianlun 2025-01-08 10:14:36 +08:00
parent 43d39c3010
commit 8bb7615cb1
10 changed files with 55 additions and 30 deletions

View File

@ -3,7 +3,7 @@ class AccountActivationsController < ApplicationController
def edit def edit
user = User.find_by(email: params[:email]) user = User.find_by(email: params[:email])
if user && !user.activated? && user.authenticated?(:activation, params[:id]) if user && !user.activated? && user.authenticated?(:activation, params[:id])
user.send(:activate) user.activate
log_in user log_in user
flash[:success] = "Account activated!" flash[:success] = "Account activated!"
redirect_to user redirect_to user

View File

@ -3,7 +3,7 @@ class PasswordResetsController < ApplicationController
end end
def create def create
@user = User.find_by(emial: params[:password_reset][:email].downcase) @user = User.find_by(email: params[:password_reset][:email].downcase)
if @user if @user
@user.create_reset_digest @user.create_reset_digest
@user.send_password_reset_email @user.send_password_reset_email
@ -11,7 +11,7 @@ class PasswordResetsController < ApplicationController
redirect_to root_url redirect_to root_url
else else
flash.now[:danger] = "Email not found" flash.now[:danger] = "Email not found"
render 'new' render 'new', status: :unprocessable_entity
end end
end end

View File

@ -28,11 +28,11 @@ class UsersController < ApplicationController
# flash[:success] = "Welcome to the Sample App!" # flash[:success] = "Welcome to the Sample App!"
# redirect_to @user # redirect_to @user
# redirect_to user_url(@user) # redirect_to user_url(@user)
@user.send(:send_activation_email) @user.send_activation_email
flash[:info] = "Please check your email to activate your account." flash[:info] = "Please check your email to activate your account."
redirect_to root_url redirect_to root_url
else else
render "new" render "new", status: :unprocessable_entity
end end
end end

View File

@ -14,9 +14,8 @@ class UserMailer < ApplicationMailer
# #
# en.user_mailer.password_reset.subject # en.user_mailer.password_reset.subject
# #
def password_reset def password_reset(user)
@greeting = "Hi" @user = user
mail to: user.email, subject: "Password reset"
mail to: "to@example.org"
end end
end end

View File

@ -1,5 +1,5 @@
class User < ApplicationRecord class User < ApplicationRecord
attr_accessor :remember_token, :activation_token attr_accessor :remember_token, :activation_token, :reset_token
# before_save { self.email = email.downcase } # before_save { self.email = email.downcase }
# before_save { email.downcase! } # before_save { email.downcase! }
before_save :downcase_email before_save :downcase_email
@ -57,6 +57,26 @@ class User < ApplicationRecord
update_attribute(:remember_digest, nil) update_attribute(:remember_digest, nil)
end end
def activate
# update_attribute(:activated, true)
# update_attribute(:activated_at, Time.zone.now)
update_columns(activated: true, activated_at: Time.zone.now)
end
def send_activation_email
UserMailer.account_activation(self).deliver_now
end
def create_reset_digest
self.reset_token = User.new_token
update_attribute(:reset_digest, User.digest(reset_token))
update_attribute(:reset_sent_at, Time.zone.now)
end
def send_password_reset_email
UserMailer.password_reset(self).deliver_now
end
private private
def downcase_email def downcase_email
@ -68,14 +88,4 @@ class User < ApplicationRecord
self.activation_token = User.new_token self.activation_token = User.new_token
self.activation_digest = User.digest(activation_token) self.activation_digest = User.digest(activation_token)
end end
def activate
# update_attribute(:activated, true)
# update_attribute(:activated_at, Time.zone.now)
update_columns(activated: true, activated_at: Time.zone.now)
end
def send_activation_email
UserMailer.account_activation(self).deliver_now
end
end end

View File

@ -3,7 +3,7 @@
<div class="row"> <div class="row">
<div class="vol-md-6 col-md-offset-3"> <div class="vol-md-6 col-md-offset-3">
<%= form_with(url: password_resets_path, scope: password_reset, <%= form_with(url: password_resets_path, scope: :password_reset,
local: true) do |f| %> local: true) do |f| %>
<%= f.label :email %> <%= f.label :email %>
<%= f.email_field :email, class: "form-control" %> <%= f.email_field :email, class: "form-control" %>

View File

@ -1,5 +1,12 @@
<h1>User#password_reset</h1> <h1>Password reset</h1>
<p>To reset your password click the link below:</p>
<%= link_to "Reset password", edit_password_reset_url(@user.reset_token,
email: @user.email) %>
<p>This link will expire in two hours.</p>
<p> <p>
<%= @greeting %>, find me in app/views/user_mailer/password_reset.html.erb If you did not request your password to be reset, please ignore this email and your password will stay as it is.
</p> </p>

View File

@ -1,3 +1,7 @@
User#password_reset To reset your password click the link below:
<%= @greeting %>, find me in app/views/user_mailer/password_reset.text.erb <%= edit_password_reset_url(@user.reset_token, email: @user.email) %>
This link will expire in two hours.
If you did not request your password to be reset, please ignore this email and your password will stay as it is.

View File

@ -9,6 +9,8 @@ class UserMailerPreview < ActionMailer::Preview
# Preview this email at http://localhost:3000/rails/mailers/user_mailer/password_reset # Preview this email at http://localhost:3000/rails/mailers/user_mailer/password_reset
def password_reset def password_reset
UserMailer.password_reset user = User.first
user.reset_token = User.new_token
UserMailer.password_reset(user)
end end
end end

View File

@ -14,10 +14,13 @@ class UserMailerTest < ActionMailer::TestCase
end end
test "password_reset" do test "password_reset" do
mail = UserMailer.password_reset user = users(:michael)
user.reset_token = User.new_token
mail = UserMailer.password_reset(user)
assert_equal "Password reset", mail.subject assert_equal "Password reset", mail.subject
assert_equal [ "to@example.org" ], mail.to assert_equal [ user.email ], mail.to
assert_equal [ "noreply@mail.frytea.com" ], mail.from assert_equal [ "noreply@mail.frytea.com" ], mail.from
assert_match "Hi", mail.body.encoded assert_match user.reset_token, mail.body.encoded
assert_match CGI.escape(user.email), mail.body.encoded
end end
end end