Authorizing an array of ID's with the Pundit gem
Asked Answered
G

2

8

I have a multiple select box for a has_many association. The params come in as:

foo_ids: ["1", "2", "3"]

Using strong parameters, I do not permit this attribute because I would like to authorize it myself so people cannot just put whatever they want in it.

def update
  bar.foos = authorized_foos
  bar.update(baz_params)
  respond_with bar
end

private

  def authorized_foos
    foos = Foo.find(params[:baz][:foo_ids])
    foos.each do |foo|
      authorize foo, :manage?
    end
  end

This approach is going to force me to find all of the foos, loop through them, and authorize each one individually. Is there an easier way to manage has_many authorization, preferably with the Pundit gem?

Goraud answered 20/8, 2013 at 15:14 Comment(2)
Hi Logan, I'm one of the maintainers of Pundit and would like to learn about your use case. Is it simply authorizing all records in the collection, or are additional checks involved somehow? Your input could get your question solved nicely in a future release and also help others. I'd be happy if you could leave a comment here. Thanks in advance!Juliettejulina
To save everybody from reading through the whole issue thread on Github. This issue there is closed, basically saying it can be handled by extending Pundit or changing the way you go about this.Unshackle
M
2

The simplest way to do this is looping. Iterate through each user from the users' array and authorize each and every user. For example,

users_id_array = [1,2,3,4,5,6]

private

  def authorized_users
  users = User.find(params[:group][:user_ids])
  users.each { |u| authorize u, :manage? }
  ...
end

So this is the very basic and simplest answer.

Morganstein answered 27/1, 2015 at 17:29 Comment(0)
S
1

I do something similar to this. Because of how little info you've provided I'm going to make a swath of assumptions.

  1. You have a many to many association of foos to users. By this I mean a foo can have many users and a user can be a member of many foos.

  2. You understand how to set-up the models to attain (1). If you don't just comment and I'll edit this response.

So what we will need to have working for this to work is the following:

  1. @foo.users returns a collection of users
  2. @user.foos returns a collection of foos

With the models set up to support the actions above this is much easier than you are making it out to be.

class FooPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      user.foos
    end
  end
end

I think you're missing the point of pundit. Pundit allows you to do authorization on a user by user basis. So the above code scopes a user to only the groups (foos in this case) that they are a part of.

Seldom answered 12/5, 2017 at 17:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.