Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Policies custom parameters #48

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 8 additions & 8 deletions lib/pundit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ class NotDefinedError < StandardError; end
extend ActiveSupport::Concern

class << self
def policy_scope(user, scope)
def policy_scope(user, scope, resolve_by = :resolve, *args)
policy = PolicyFinder.new(scope).scope
policy.new(user, scope).resolve if policy
policy.new(user, scope).public_send(resolve_by, *args) if policy
end

def policy_scope!(user, scope)
PolicyFinder.new(scope).scope!.new(user, scope).resolve
def policy_scope!(user, scope, resolve_by = :resolve, *args)
PolicyFinder.new(scope).scope!.new(user, scope).public_send(resolve_by, *args)
end

def policy(user, record)
Expand Down Expand Up @@ -52,18 +52,18 @@ def verify_policy_scoped
raise NotAuthorizedError unless @_policy_scoped
end

def authorize(record, query=nil)
def authorize(record, query=nil, *args)
query ||= params[:action].to_s + "?"
@_policy_authorized = true
unless policy(record).public_send(query)
unless policy(record).public_send(query, *args)
raise NotAuthorizedError, "not allowed to #{query} this #{record}"
end
true
end

def policy_scope(scope)
def policy_scope(scope, resolve_by = :resolve, *args)
@_policy_scoped = true
Pundit.policy_scope!(pundit_user, scope)
Pundit.policy_scope!(pundit_user, scope, resolve_by, *args)
end

def policy(record)
Expand Down
64 changes: 64 additions & 0 deletions spec/pundit_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,38 @@ def destroy?
def show?
true
end
def compare(a, b)
a == b
end
end
class PostPolicy::Scope < Struct.new(:user, :scope)
def resolve
scope.published
end
def custom
scope.unpublished
end
def do_math(a, b)
a + b
end
end
class Post < Struct.new(:user)
def self.published
:published
end
def self.unpublished
:unpublished
end
end

class CommentPolicy < Struct.new(:user, :comment); end
class CommentPolicy::Scope < Struct.new(:user, :scope)
def resolve
scope
end
def custom
scope.name.pluralize
end
end
class Comment; extend ActiveModel::Naming; end

Expand Down Expand Up @@ -69,31 +84,63 @@ def destroy?
Pundit.policy_scope(user, Post).should == :published
end

it "returns an instantiated custom policy scope given a plain model class" do
Pundit.policy_scope(user, Post, :custom).should == :unpublished
end

it "returns an instantiated custom policy scope with parameters given a plain model class" do
Pundit.policy_scope(user, Post, :do_math, 2, 3).should == 5
end

it "returns an instantiated policy scope given an active model class" do
Pundit.policy_scope(user, Comment).should == Comment
end

it "returns an instantiated custom policy scope given an active model class" do
Pundit.policy_scope(user, Comment, :custom).should == 'Comments'
end

it "returns nil if the given policy scope can't be found" do
Pundit.policy_scope(user, Article).should be_nil
end

it "throws an exception if the given custom scope can't be found" do
expect{ Pundit.policy_scope(user, Comment, :wrong_name) }.to raise_error(NoMethodError)
end
end

describe ".policy_scope!" do
it "returns an instantiated policy scope given a plain model class" do
Pundit.policy_scope!(user, Post).should == :published
end

it "returns an instantiated custom policy scope given a plain model class" do
Pundit.policy_scope!(user, Post, :custom).should == :unpublished
end

it "returns an instantiated custom policy scope with parameters given a plain model class" do
Pundit.policy_scope!(user, Post, :do_math, 2, 3).should == 5
end

it "returns an instantiated policy scope given an active model class" do
Pundit.policy_scope!(user, Comment).should == Comment
end

it "returns an instantiated custom policy scope given an active model class" do
Pundit.policy_scope!(user, Comment, :custom).should == 'Comments'
end

it "throws an exception if the given policy scope can't be found" do
expect { Pundit.policy_scope!(user, Article) }.to raise_error(Pundit::NotDefinedError)
end

it "throws an exception if the given policy scope can't be found" do
expect { Pundit.policy_scope!(user, ArticleTag) }.to raise_error(Pundit::NotDefinedError)
end

it "throws an exception if the given custom scope can't be found" do
expect{ Pundit.policy_scope!(user, Comment, :wrong_name) }.to raise_error(NoMethodError)
end
end

describe ".policy" do
Expand Down Expand Up @@ -216,6 +263,11 @@ def destroy?
expect { controller.authorize(post, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
end

it "can be given permission to check and parameters" do
controller.authorize(post, :compare, 1, 1).should be_true
expect { controller.authorize(post, :compare, 2, 1) }.to raise_error(Pundit::NotAuthorizedError)
end

it "works with anonymous class policies" do
controller.authorize(article_tag, :show?).should be_true
expect { controller.authorize(article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
Expand Down Expand Up @@ -249,8 +301,20 @@ def destroy?
controller.policy_scope(Post).should == :published
end

it "returns an instantiated custom policy scope" do
controller.policy_scope(Post, :custom).should == :unpublished
end

it "returns an instantiated custom policy scope with parameters" do
controller.policy_scope(Post, :do_math, 2, 3).should == 5
end

it "throws an exception if the given policy can't be found" do
expect { controller.policy_scope(Article) }.to raise_error(Pundit::NotDefinedError)
end

it "throws an exception if the given custom scope can't be found" do
expect{ controller.policy_scope(Post, :wrong_name) }.to raise_error(NoMethodError)
end
end
end