0
I am working on a project and I need to do a password reset system. I’m not using g and I don’t want to use.
I found that the can_change filter runs and I am redirected to the user page, which makes no sense to me, since the can_change filter is in the Userscontroller, and not in the Passwordresetscontroller
The email is sent without errors. I click on the link and go to /password_resets/edit?token=fewgfeggrf, but when I click edit password, it doesn’t work. How to resolve?
mailers/password_reset.Rb
class PasswordReset < ActionMailer::Base
default from: '[email protected]'
def send_password_reset(user)
    @user = user
    @reset_link = edit_password_resets_url({
        token: @user.password_reset_token
    })
    mail({
        :to => user.email, 
        :bcc => ['reset password <[email protected]'],
        :subject => I18n.t('password_reset.send_password_reset.subject')
    }) 
end
end
views/password_reset/send_password_reset.html.erb
<h2><%= t '.greetings', full_name: @user.full_name %></h2>
 <p><%= t '.body_html', link: link_to(t('.click_here'), @reset_link) %></p>
controllers/password_resets_controller.Rb
class PasswordResetsController < ApplicationController
before_action :require_no_authentication, only: [:new, :create, :edit, :update]
def new
end
def create
    user = User.find_by(email: params[:email])
    if user.present?
        user.generate_password_reset
        PasswordReset.send_password_reset(user).deliver
        redirect_to root_url, notice: t('flash.notice.check_email_reset')
    else 
        flash[:alert] = t('flash.alert.cannot_find_email_reset')
        render :new
    end
end
def edit
    @user = User.find_by(password_reset_token: params[:token])
end
def update
    @user = User.find_by!(password_reset_token: params[:token])
    if @user.password_reset_sent_at < 2.hours.ago
        redirect_to new_password_reset_path, alert: t('flash.alert.time_expired')
    end
    if @user.update(password_reset_user_params)
        @user.password_reseted!
        redirect_to new_user_sessions_path, notice: t('flash.notice.password_reseted_complete')
    else
        render :edit
    end
end
private
def password_reset_user_params
    params.require(:user).permit(:password, :password_confirmation)
end
end
models/user.Rb
class User < ActiveRecord::Base
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
VALID_BIRTHDAY_REGEX = /[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}/
validates_presence_of :full_name, :email, :birthday, :about
validates_length_of :about, minimum: 10, maximum: 100
validates_format_of :email, with: VALID_EMAIL_REGEX
validates_uniqueness_of :email
validates_format_of :birthday, with: VALID_BIRTHDAY_REGEX 
has_secure_password
scope :confirmed, -> { where.not(created_at: nil) }
before_create do |user|
    user.confirmation_token = SecureRandom.urlsafe_base64
end
def confirm!
    return if confirmed?
    self.confirmed_at = Time.current
    self.confirmation_token = ''
    save!
end 
def confirmed?
    confirmed_at.present?
end
def self.authenticate(email, password)
    user = confirmed.find_by(email: email)
    if user.present?
        user.authenticate(password)
    end
end
def generate_password_reset
    self.password_reset_token = SecureRandom.urlsafe_base64
    self.password_reset_sent_at = Time.zone.now
    save!
end
def password_reseted?
    password_reset_token.present?
end
def password_reseted!
    return if password_reseted?
    self.password_reset_token = ''
    self.password_reseted_at = Time.current
    save!
end
def password_reseted_expired?
    password_reset_sent_at < 1.hours.ago
end
end
views/password_resets/new.html.erb
<%= form_tag password_resets_path, :method => :post do %>
<div>
    <%= label_tag :email %>
    <%= text_field_tag :email, params[:email] %>
</div>
<div><%= submit_tag %></div>
views/password_resets/Edit.html.erb
<%= form_for @user do |f| %>
<p>
    <%= f.label :password %><br>
    <%= f.password_field :password %>
    <%= error_field(@user, :password) %>
</p>
<p>
    <%= f.label :password_confirmation %><br>
    <%= f.password_field :password_confirmation %>
    <%= error_field(@user, :password_confirmation) %>
</p>
<p>
    <%= f.submit %>
</p>
controllers/users_controller.Rb
class UsersController < ApplicationController
before_action :can_change, only: [:edit, :update]
before_action :require_no_authentication, only: [:new, :create]
def show
    @user = User.find(params[:id])
end
def new
    @user = User.new
end
def create
    @user = User.new(user_params)
    if @user.save
        Signup.confirm_email(@user).deliver
        redirect_to new_user_sessions_path, notice: t('flash.notice.user_created') 
    else
        render action: :new
    end
end
def edit
    @user = User.find(params[:id])
end
def update
    @user = User.find(params[:id])
    if @user.update(user_params)
        flash[:notice] = t('flash.notice.user_updated')
        redirect_to @user
    else
        render action: :edit
    end
end
private
def user_params
    params.require(:user).permit(:full_name, :email, :birthday, :password, :password_confirmation, :about)
end
def can_change
    unless user_signed_in? && current_user == user
        redirect_to user_path(params[:id])
    end
end
def user
    @user ||= User.find(params[:id])
end
end
config/Routes
resource :password_resets