0
votes

Hello, I'm new to ruby on rails, and currently working on an exercise where I have 3 types of users ( Admin, moderator and member). I'm using the Pundit gem with the Devise Gem. I was asked to define Pundit scope classes to make Posts accessible according to the role of the user.

Admin and moderator can see all posts. Signed in user can see his posts only. A guest can't see the posts.

Here's the PostsController:

class PostsController < ApplicationController
          def index
            @posts = policy_scope(Post.all)
            authorize @posts
          end

          def show
            @post = Post.find(params[:id])
          end

          def new
            @post = Post.new
            authorize @post
          end

          def create 
            @post = current_user.posts.build(params.require(:post).permit(:title, :body))
            authorize @post
            if @post.save
              flash[:notice] = "Post was saved"
              redirect_to @post
            else
              flash[:error] = "There was an error saving the post. Please try again"
              render :new
            end
          end

          def edit
            @post = Post.find(params[:id])
            authorize @post
          end
          def update 
            @post = Post.find(params[:id])
            authorize @post
            if @post.update_attributes(params.require(:post).permit(:title, :body))
              flash[:notice] = "Post was updated."
              redirect_to @post
            else
              flash[:error] = "There was an error saving the post.Please try again."
              render :edit
            end
          end
        end

Here's my application policy:

    class ApplicationPolicy
      attr_reader :user, :record

      def initialize(user, record)
        @user = user
        @record = record
      end

      def index?
        false
      end

      def show?
        scope.where(:id => record.id).exists?
      end

      def create?
        user.present?
      end

      def new?
        create?
      end

      def update?
        user.present? && (record.user == user || user.admin?)
      end

      def edit?
        update?
      end

      def destroy?
        update?
      end

      def scope
        record.class
      end

      class Scope
        attr_reader :user, :scope

        def initialize(user, scope)
          @user = user
          @scope = scope
        end

        def resolve
          scope
        end
      end
    end

And my post policy:

class PostPolicy < ApplicationPolicy 


  class Scope < Scope 
    def resolve 
      if user.admin? || user.moderator? 
      scope.all

      else
      scope.where(:id => user.id).exists?
      end
    end
  end 


  def index?
    user.admin? || user.id?
  end

end

Also, is there anywhere I can read or learn more about scope policies with Pundit and authorization on rails?

2
You didn't really tell what seems to be the problem? you can figure out how to do the exercise or you are stuck at it? You can read more about Pundit thereKarim Tarek

2 Answers

0
votes

Make sure to always write the methods to declare the admin and the moderator in your User model if you want to work with Pundit policies.

def admin?
  role == 'admin'
end

def moderator?
  role == 'moderator'
end
0
votes

There is a better way to define admins, moderators and members. First do:

rails g migration AddRoleToUsers role:integer

Then in your users model make an enum

enum role: [:member, :moderator, :admin] # add whatever roles you want 

The enum will automatically create for each role a

.member? # checks if role is member
.member! # turns the user into a member so like current_user.member!
 # and the same for all other roles.

Not sure if this really helps but hope you find it useful!