Here at Drawbotics, we use the Pundit gem for anything authorization-related.
Our platform has a client-side and an admin-side, both sharing the same database, models, and policies, which led to the following situation :
def new?
user.role == ClientUser::Owner || user.role == AdminUser::Supervisor
end
Some refactoring was needed. We needed a way to :
After some testing and diving into the Pundit codebase, we found a way to cover our 2 needs.
I implemented all the models with the following method :
def self.policy_class
Default::ModelPolicy
end
Everytime i call the authorize
method on a Model
object, Pundit will call model.policy_class
in order to find the policy class to use. That first change allowed us to easily categorize our policy classes in namespaces.
One problem remained : specifying the policy to use for a shared object.
In order to also have that feature, I added to every shared model an attr_writer
also called policy_class
and changed the policy_class
method :
def policy_class(klass = Default::ModelPolicy)
@policy_class ||= klass
end
With that change, I know have two choices when using Pundit :
authorize(model)
(Pundit usual behavior)authorize model
This code will use the Default::ModelPolicy
located in policies/default
model.policy_class = Admin::ModelPolicy
authorize model
This code will use the Admin::ModelPolicy
located in policies/admin. That way I can specify the policy to use for shared models.
With that solution, i've been able to clearly organize all policies before making all my changes.