user5715347
user5715347

Reputation:

Rails how to require the current password to allow user update

I am having a rather difficult problem i want to update the user profile only if they submit the current password.I am not using devise.And another post here at stack overflow didn't really help me. This is my User controller code:

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def show
    @user = User.find(params[:id])
    @user_posts = @user.posts if @user
    if @user
      if @user_posts
        render 'show.html'
      else
        render 'show.html'
      end
    else
      render file: 'public/404.html', status: 404, formats: [:html]
    end
  end

  def create
    @user = User.new(user_params)
    if @user.save
      session[:user_id] = @user.id
      redirect_to root_path
      flash[:notice] = "Successfully Signed up :-)"
    else
      redirect_to signup_path
      flash[:notice] = "You didn't sign up successfully :-("
    end
  end

  def edit
    @user = User.find(params[:id])
    if current_user.id = @user.id
      render 'edit'
    else
      redirect_to @user
    end
  end

  def update
    @user = User.find(params[:id])
    if @user.update_attributes(user_params)
      flash[:notice] = "Profile updated"
      redirect_to @user
    else
      render 'edit'
    end
  end

  :password == :password_confirmation

  private

  def user_params
    params.require(:user).permit(:user_name, :email, :password, :password_confirmation)
  end
end

And this is my user.rb:

class User
  has_secure_password
  has_many :posts
  has_many :comments

  def admin?
    self.role == 'admin'
  end

  def moderator?
    self.role == 'moderator'
  end    
end

Please help because I have been working with this for a long time now. And the other solution about this topic here at stack overflow didn't work.

Upvotes: 1

Views: 1231

Answers (2)

mtkcs
mtkcs

Reputation: 1716

One way is to use virtual attributes

1. The User model

class User < ActiveRecord::Base
  attr_accessor :current_password
end

2. The form

add the current_password attribute to the form as a text_field input

3. The UsersController

def update
  @user = User.find params[:id]
  if @user.authenticate(update_params[:current_password])
    # update the user
    # maybe check if the data are valid
    @user.update(update_params)  
  else
    flash[:warning] = "Please provide your password"
    @user.errors.add :current_password, "invalid"
    render :edit
  end
end

def update_params
  params.require(:user).permit(:current_password, :email)
end

Upvotes: 1

Kristj&#225;n
Kristj&#225;n

Reputation: 18803

First, you have a problem in your edit action:

current_user.id = @user.id

That assigns @user.id to current_user.id - you wanted == to test that it's the correct User. You should put a similar check on update, and probably extract it into a before_action so you can easily apply it anywhere you want to.

To check that the password is present, add it to your form like any other field and then get it out of params to verify it. That would look something like this:

class UsersController < ApplicationController
  def update
    encrypted = encrypt(params[:password]) # Using whatever your mechanism is
    if encrypted == @user.encrypted_password
      # Update the user
    else
      flash[:notice] = 'Password is required to update user information.'
      redirect_to edit_user(path(@user))
    end
  end
end

Upvotes: 0

Related Questions