Reputation: 1413
I've been trying to wrap my head around the concept of a policy, which seems straightforward enough--a policy is a set of rules by which access to system privileges and resources is determined.
Simple enough.
So, in order for a user within a system to access a list of, say, every other user within that system, they'd require the necessary credentials (e.g., maybe being an administrator or simply being logged in as a registered user). What I'm struggling to understand at even the most basic level is how to actually USE Pundit to accomplish this. As is the case with the documentation for lots of open-source software I've attempted to learn, the Pundit documentation seems to at best allude to how the tool should work but does not provide a full and concrete example of so much as a basic use case. All I'm looking for here is a "hello world" example so I don't spend three or four days piecing together a confused and half-working implementation myself for something so small as this. Furthermore, what examples Pundit does provide only serve to confuse matters worse.
I've basically created a test application that attempts to use Devise (which I seem to understand and be able to use well enough) and Pundit in combination. So far:
Now, what I'd like to do--which is something very basic and probably shouldn't have my furrowing by brow so soon--is to restrict the user's access to the users index page based on whether they are logged into the system, and it's here that I'm completely stuck.
What have I tried so far?
I've generated a User policy, which looks like this:
class UserPolicy < ApplicationPolicy
class Scope < Scope
puts "Inside UserPolicy scope."
attr_reader :user
def initialize(user)
@user = user
end
def index
puts "You've hit the index."
end
def resolve
scope
end
end
end
class UsersController < ApplicationController
before_filter :authenticate_user!
after_action :verify_authorized
def index
@users = User.all
authorize current_user
end
end
At this point, I'm completely lost as to how to associate the two--the UserPolicy class and UsersController.
I seem to at least be able to print to my console the message "Inside UserPolicy scope." but otherwise just see the following error message in THE browser:
"not allowed to index? this #"
What am I missing and, if nothing else, where is the gap in my own knowledge that's making this and other Rails-related tools so difficult to learn? I'm a professional software engineer (historically, I've been a front-end engineer and have within the last couple of years been working to become a full-stack engineer), but I find myself getting stuck far too often with open-source tools like this one.
Upvotes: 1
Views: 1442
Reputation: 3870
Your implementation has a few issues:
index?
) goes into the parent UserPolicy
class, not the internal Scope
class.true
or false
. Your index?
call returns puts "You've hit the index."
, which evaluates to nil
Upvotes: 2
Reputation: 6075
Pundit is really just plain ruby objects set in a rails like structure.
I think your confusion is trying to authorize the user, think of it more from a resource perspective. You are limiting users access to a certain object via a certain restful action. Scopes limit what they can see, for instance, admin could probably do scope.all, a single user would probably not be allowed or just be able to scope themselves on the users controller.
In my application policy i define helpers to group certain types of users. Here is an example.
class TicketPolicy < ApplicationPolicy
class Scope < Struct.new(:user, :scope)
def resolve
#Allows government to see their organization
# only allows citizens to see nothing
if user.government?
scope.where(:organization_id => user.organization_id)
else
scope.where(:id => 0)
end
end
end
def index?
is_government
end
def show?
is_government && is_inside_organization(@record)
end
def create?
is_government && is_inside_organization(@record)
end
def new?
is_government && is_inside_organization(@record)
end
def update?
is_government && is_inside_organization(@record)
end
def edit?
if user.employee?
return is_mine(@record) && is_inside_organization(@record)
end
is_government && is_inside_organization(@record)
end
def destroy?
false
end
end
This limits the access to the groups/roles and then in my controller i just call
authorize @thing
Then pundit will take care of the access based on the policy.
Upvotes: 1