Devise Forgot Password for logged in user

后端 未结 3 720
天命终不由人
天命终不由人 2020-12-29 10:25

I\'m wondering if there is a manner of calling the \'forgot password\' procedure without forcing my user to log out

The case I\'m running into is: 1. a user logs in

3条回答
  •  别那么骄傲
    2020-12-29 11:06

    My complete solution here, because I then also learned that the user would have to log out after clicking the link in the email, was to add an some additional UserController actions for actually editing the password as well as saving it. This is not an ideal solution and cold probably be done in a better manner but it works for me.

    users controller; added methods to do the reset

        before_filter :authenticate_user!, :except => [:do_reset_password, :reset_password_edit]
    
        def reset_password
            id = params[:id]
            if id.nil?
              id = current_user.id
            end    
            if (!user_signed_in? || current_user.id.to_s != id.to_s)
            flash[:alert] = "You don't have that right." 
              redirect_to '/home'
              return
            end
    
            @user = User.find(id)
            @user.send_reset_password_instructions
    
            respond_to do |format|
                format.html { redirect_to '/users/edit', notice: 'You will receive an email with instructions about how to reset your password in a few minutes.' }
            end
         end
    
    
        def do_reset_password
            id = params[:id]
            if id.nil? && !current_user.nil?
              id = current_user.id
            end
    
            if id.nil?
                @user = User.where(:reset_password_token => params[:user][:reset_password_token]).first
            else
                @user = User.find(id)
            end
            if  @user.nil? || @user.reset_password_token.to_s != params[:user][:reset_password_token]
              flash[:alert] = "Url to reset was incorrect, please resend reset email." 
              redirect_to '/home'
              return
            end
    
            # there may be a better way of doing this, devise should be able to give us these messages
            if params[:user][:password] != params[:user][:password_confirmation]
                flash[:alert] = "Passwords must match." 
                  redirect_to :back
                  return
            end
            if @user.reset_password!(params[:user][:password],params[:user][:password_confirmation])
                @user.hasSetPassword = true
                @user.save
                respond_to do |format|
                    format.html { redirect_to '/home', notice: 'Your password has been changed.' }
                end
            else
                flash[:alert] = "Invalid password, must be at least 6 charactors." 
                  redirect_to :back 
            end
        end
    
        def reset_password_edit
            @user = User.where(:reset_password_token => params[:reset_password_token]).first
            if  @user.nil? || !@user.reset_password_period_valid?
                flash[:alert] = "Password reset period expired, please resend reset email" 
                redirect_to "/home"
                return
            end
        end
    

    views/devise/registrations/edit; changed the view to not let the user edit fields that require a password

        <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
          <%= devise_error_messages! %>
    
          <% if !resource.hasSetPassword %>                                           
              <%= f.label :name %>

    <%= @user.name %>

    <%= f.label :email %>

    <%= @user.email %>

    you cannot change any settings because you have not set a password
    yet, you can do so by following the
    <%= link_to "Forgot your password", "/users/reset_password" %> procedure

    <% else %>

    <%= f.label :name %>
    <%= f.text_field :name %>

    <%= f.label :email %>
    <%= f.email_field :email %>
    <%= f.label :password %>
    <%= f.password_field :password %>(leave blank if you don't want to change it)
    <%= f.label :password_confirmation %>
    <%= f.password_field :password_confirmation %>
    <%= f.label :current_password %>
    <%= f.password_field :current_password %> (we need your current password to confirm your changes)
    <%= f.submit "Update" %>
    <% end %> <% end %>

    views/devise/mailer/reset_password_instructions; had to change it to point to the right URL in our new case

        

    Hello <%= @resource.email %>!

    Someone has requested a link to change your password, and you can do this through the link below.

    <% if !@resource.hasSetPassword %>

    <%= link_to 'Change my password', 'http://streetsbehind.me/users/reset_password_edit?reset_password_token='+@resource.reset_password_token %>

    <% else %>

    <%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %>

    <% end %>

    If you didn't request this, please ignore this email.

    Your password won't change until you access the link above and create a new one.

    views/users/reset_password_edit.erb

    <%= form_for(@user, :url => url_for(:action => :do_reset_password) , :html => { :method => :post }) do |f| %>
    
      <%= f.hidden_field :reset_password_token %>
    
      
    <%= f.label :password, "New password" %>
    <%= f.password_field :password %>
    <%= f.label :password_confirmation, "Confirm new password" %>
    <%= f.password_field :password_confirmation %>
    <%= f.submit "Change my password" %>
    <% end %>

    config/routes.rb

    get "users/reset_password"
    get "users/reset_password_edit"
    
    resource :users do
      post 'do_reset_password'
    end
    

提交回复
热议问题