how to run two method in before_filter?

316 Views Asked by At

My code for post controller is as follows. What I'm trying to do is user should be able to delete his own posts, and admin_user can delete any posts. The following code make admin_user can delete posts, but for normal user, when trying to delete his own post, it redirect to root_path

It seems do_authentication doesn't work properly, a normal user is trying to be authenticated as an admin instead of "correct_user"

What could be wrong?

Thanks!

class PostsController < ApplicationController
  before_filter :signed_in_user, only: [:index, :create, :destroy]
  before_filter :do_authentication,  only: :destroy
  .
  .
  .
def destroy
  @post.destroy
  flash[:success] = "Post deleted!"
  redirect_back_or user_path(current_user)
end

private
  def do_authentication
    correct_user || admin_user
  end

  def correct_user
    @post = current_user.posts.find_by_id(params[:id])
    redirect_to user_path(current_user) if @post.nil?
  end

  def admin_user
    @post = Post.find_by_id(params[:id])
    redirect_to(root_path) unless current_user.admin?
  end
2

There are 2 best solutions below

1
On BEST ANSWER

First of all I would suggest using cancan for authorization. I think your problem is the return value of correct_user. You don't control that. If that method returns something that evaluates to false the do_authentication method will also call admin_user. Also looking at your code it seems that the admin authorization won't work also ...

try this:

def do_authentication
  @post = Post.find_by_id(params[:id])
  redirect_to redirect_location unless current_user.admin? or @post.user == current_user
end

def redirect_location
  return "redirect_location_for_admin" if current_user.admin?
  return "redirect_location_for_non_admins"
end
0
On

The methods correct_user,admin_user will be executed for all the users regardless of their role because you have not checked any condition while calling the methods.The code need to be improved to solve your problem.

def do_authentication
  if current_user.admin?
    @post = Post.find_by_id(params[:id])
  else
    @post = current_user.posts.find_by_id(params[:id])
    redirect_to user_path(current_user), :notice => "Access denied" unless @post
  end
end