feat: add password reset functionality

- Implement PasswordResetsController with new and create actions
- Add views for new and edit password reset forms
- Update routes to include password reset paths
- Create migration to add reset_digest and reset_send_at to users

This commit introduces a complete password reset feature, allowing
users to request a password reset via email. It includes the
necessary controller actions, views, and database schema updates.
The user experience is enhanced with a link to the password reset
form on the login page.
This commit is contained in:
songtianlun 2025-01-07 18:09:44 +08:00
parent 8ba219c4c0
commit 43d39c3010
8 changed files with 51 additions and 1 deletions

View File

@ -0,0 +1,20 @@
class PasswordResetsController < ApplicationController
def new
end
def create
@user = User.find_by(emial: params[:password_reset][:email].downcase)
if @user
@user.create_reset_digest
@user.send_password_reset_email
flash[:info] = "Email send with password reset instructions"
redirect_to root_url
else
flash.now[:danger] = "Email not found"
render 'new'
end
end
def edit
end
end

View File

@ -0,0 +1,2 @@
module PasswordResetsHelper
end

View File

@ -0,0 +1,2 @@
<h1>PasswordResets#edit</h1>
<p>Find me in app/views/password_resets/edit.html.erb</p>

View File

@ -0,0 +1,14 @@
<% provide(:title, "Forget password") %>
<h1>Forget password</h1>
<div class="row">
<div class="vol-md-6 col-md-offset-3">
<%= form_with(url: password_resets_path, scope: password_reset,
local: true) do |f| %>
<%= f.label :email %>
<%= f.email_field :email, class: "form-control" %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>

View File

@ -8,6 +8,7 @@
<%= f.email_field :email, class: 'form-control' %> <%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %> <%= f.label :password %>
<%= link_to "(forgot password)", new_password_reset_path %>
<%= f.password_field :password, class: 'form-control' %> <%= f.password_field :password, class: 'form-control' %>
<%= f.label :remember_me, class: "checkbox inline" do %> <%= f.label :remember_me, class: "checkbox inline" do %>

View File

@ -1,4 +1,6 @@
Rails.application.routes.draw do Rails.application.routes.draw do
get "password_resets/new"
get "password_resets/edit"
# get "sessions/new" # get "sessions/new"
# get "users/new" # get "users/new"
# get "static_pages/home" # get "static_pages/home"
@ -19,6 +21,7 @@ Rails.application.routes.draw do
resources :users resources :users
resources :account_activations, only: [ :edit ] resources :account_activations, only: [ :edit ]
resources :password_resets, only: [ :new, :create, :edit, :update ]
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

View File

@ -0,0 +1,6 @@
class AddResetToUsers < ActiveRecord::Migration[8.0]
def change
add_column :users, :reset_digest, :string
add_column :users, :reset_send_at, :datetime
end
end

4
db/schema.rb generated
View File

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_01_06_091017) do ActiveRecord::Schema[8.0].define(version: 2025_01_07_093124) do
create_table "users", force: :cascade do |t| create_table "users", force: :cascade do |t|
t.string "name" t.string "name"
t.string "email" t.string "email"
@ -22,6 +22,8 @@ ActiveRecord::Schema[8.0].define(version: 2025_01_06_091017) do
t.string "activation_digest" t.string "activation_digest"
t.boolean "activated", default: false t.boolean "activated", default: false
t.datetime "activated_at" t.datetime "activated_at"
t.string "reset_digest"
t.datetime "reset_send_at"
t.index ["email"], name: "index_users_on_email", unique: true t.index ["email"], name: "index_users_on_email", unique: true
end end
end end