Rails 4 - Pundit with Rolify - allows a group of roles

I am trying to create an application with Rails 4.

I have defined a series of roles with the Rolify stone.

Now I want to use pundit so that users can play a role. If more than one type of role can do something, I have defined a role group.

In my application_policy, I have defined private methods that define the role groups that I want to use in pundit permissions.

My application policy creates a user instance and record. Then I define the record as the name of the corresponding model (the same name as the policy for this model).

I have:

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? false end def new? create? end def update? false end def edit? update? end def destroy? false end def scope Pundit.policy_scope!(user, record.class) end class Scope attr_reader :user, :scope def initialize(user, scope) @user = user @scope = scope end def resolve scope end end private def cf_legal [ :Admin, :CF_Legal, :CF_Policy_Manager ] end def cf_content [ :Admin, :CF_Author, :CF_Editor ] end end 

Then in my content policy I want to say:

 def record content end def create user.has_role? :cf_content end 

When I save this and try to do it, I do not see what I should see (as a user with the author role.

Can anyone see how to do this?

+6
source share
3 answers

tl; dr: Use request methods in your Policy class.

First, the model must have its own policy class, which (optionally) extends the ApplicationPolicy class. Let's say your model is called Post . Then you can do something like:

 class PostPolicy < ApplicationPolicy attr_reader :user, :post def initialize(user,post) @user = user @post = post end def create? cf_content.all? { |role| user.has_role?(role) } end private def cf_content [ :Admin, :Author, :Editor ] end end class PostsController def create @post = Post.new(params[:post]) authorize @post, :create? # @post.save and redirect, etc. end end 

And the authorization call will call the create? request method create? and check if the user has roles in cf_content.

Perhaps you don't even need to add a second create? argument create? as the pdait documentation says:

The authorization method automatically reports that the message will have a corresponding PostPolicy class, and creates an instance of this class, passing the current user and this record. Then it appears from the action name so that it causes an update? on this policy example.

Or in your case create? instead of update? .

+2
source

You can check multiple roles as follows:

user.admin? or user.author?

If you want to test a role from an array, you can also check with: cf_content.include? (user.role) OR cf_content.include? (user.role.title), which is suitable for the script.

You can also check related roles related to → user.applied_roles and see if the returned roles will include your expected role.

+1
source

I think you need to use

 has_any_role? 

Which takes two or more arguments as characters. But your cf_content method returns an array. If the user needs 3 roles that you defined in cf_create , you need to do something more like

 def create cf_content.all? { |role| user.has_role?(role) } end 

UPDATE:

If you need only one role than a simple change:

 def create cf_content.any? { |role| user.has_role?(role) } end 

Also, I'm not sure what they represent, but if they are the names of your roles, I would suggest using lowercase letters. Therefore, instead of

 [ :Admin, :CF_Author, :CF_Editor ] 

You can use:

[: admin ,: cf_author ,: cf_editor]

UPDATE 2:

Originally? will not accept an array. So if you want to check has_role? on an array do you need to iterate has_role? over each element of the array. Since the: cf_content method returns an array of roles, change from:

 def create user.has_role? :cf_content end 

To:

 def create :cf_content.any? { |role| user.has_role?(role) } end 

But you did not explain where you are trying to put your "content policy".

0
source

All Articles