ruby-on-railsrolifyauthority

Appropriate use of Authority in rails app


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?


Solution

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

    No.

    There is a difference between Authentication and Authorization:

    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