Appropriate use of Authority in rails app

109 Views Asked by At

I'm following the Michael Hartl RoR tutorial, but implementing Rollify and Authority along the way. I've never used Authority before and I am wondering if the following before_action is appropriate for Authority use

# app/controllers/users_controller.rb 
class UsersController < ApplicationController
  before_action :logged_in_user, only: [:edit, :update]
  .
  .
  .
  private

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

    # Before filters

    # Confirms a logged-in user.
    def logged_in_user
      unless logged_in?
        flash[:danger] = "Please log in."
        redirect_to login_url
      end
    end
end

would it be "good programming practice" to put the def logged_in_user inside of the ApplicationAuthorizer class for future use?

1

There are 1 best solutions below

0
On BEST ANSWER

Would it be "good programming practice" to put logged_in_user inside ApplicationAuthorizer

No.

There is a difference between Authentication and Authorization:

  • Authentication -- user logged in?
  • Authorization -- can user do this?

The difference is subtle but important - you'd expect authentication to happen before authorization, or at least independently.

A good analogy is authentication is when you get access to a secret party (password); authorization is which table you're able to sit at.

If you used one of the pre-rolled authentication systems (Devise or Sorcery), you'd have your authentication handled, providing you with such helpers as user_signed_in? etc.


To answer your question, your current pattern will suffice, considering you've rolled your own authentication.

If you were using Devise, you'd want to use the following:

#config/routes.rb
authenticate :user do
  resource :profile, controller: :users, only: [:show, :update] #-> url.com/profile
end

#app/controllers/users_controller.rb
class UsersController < ApplicationController
  def show
    @user = current_user
  end

  def update
    @user = current_user.update update_params
  end
end

--

What you're trying to do is evaluate the @user.id against current_user.id:

#app/models/user.rb
class User < ActiveRecord::Base
  include Authority::UserAbilities
  before_action :logged_in_user, only: [:edit, :update]

  def edit
     @user = User.find params[:id]
     redirect_to root_path, notice: "Can't edit this user" unless current_user.can_edit?(@user)
  end

  def update
    @user = User.find params[:id]
    if current_user.can_update?(@user)
       @user.update ...
    else
      # redirect
    end
  end

  private

  def logged_in_user
    redirect_to login_url, error: "Please log in." unless logged_in?
  end
end

# app/authorizers/user_authorizer.rb
class UserAuthorizer < ApplicationAuthorizer

  def self.editable_by?(user)
    user.id = self.id
  end

  def self.updatable_by?(user)
    user.id = self.id
  end
end