1
0
Fork 0
mirror of https://github.com/varvet/pundit.git synced 2022-11-09 12:30:11 -05:00
varvet--pundit/spec/pundit_spec.rb
Ulysse Carion d766d9e792 Add #query, #record, and #policy properties to Pundit::NotAuthorizedError.
Exceptions raised by #authorize now provide the query (e.g. 'create?') and
record (e.g. an instance of 'Post') that caused the exception to be raised, as
well as the relevant policy (e.g. an instance of 'PostPolicy').

NotAuthorizedError is modified to continue to inherit from StandardError, but
now also has attr_accessor values for :query, :record, and :policy.
2014-03-05 00:12:44 -08:00

278 lines
8.3 KiB
Ruby

require "pundit"
require "pry"
require "active_support/core_ext"
require "active_model/naming"
class PostPolicy < Struct.new(:user, :post)
def update?
post.user == user
end
def destroy?
false
end
def show?
true
end
end
class PostPolicy::Scope < Struct.new(:user, :scope)
def resolve
scope.published
end
end
class Post < Struct.new(:user)
def self.published
:published
end
end
class CommentPolicy < Struct.new(:user, :comment); end
class CommentPolicy::Scope < Struct.new(:user, :scope)
def resolve
scope
end
end
class Comment; extend ActiveModel::Naming; end
class Article; end
class BlogPolicy < Struct.new(:user, :blog); end
class Blog; end
class ArtificialBlog < Blog
def self.policy_class
BlogPolicy
end
end
class ArticleTag
def self.policy_class
Struct.new(:user, :tag) do
def show?
true
end
def destroy?
false
end
end
end
end
describe Pundit do
let(:user) { double }
let(:post) { Post.new(user) }
let(:comment) { Comment.new }
let(:article) { Article.new }
let(:controller) { double(:current_user => user, :params => { :action => "update" }).tap { |c| c.extend(Pundit) } }
let(:artificial_blog) { ArtificialBlog.new }
let(:article_tag) { ArticleTag.new }
describe ".policy_scope" do
it "returns an instantiated policy scope given a plain model class" do
expect(Pundit.policy_scope(user, Post)).to eq :published
end
it "returns an instantiated policy scope given an active model class" do
expect(Pundit.policy_scope(user, Comment)).to eq Comment
end
it "returns nil if the given policy scope can't be found" do
expect(Pundit.policy_scope(user, Article)).to be_nil
end
end
describe ".policy_scope!" do
it "returns an instantiated policy scope given a plain model class" do
expect(Pundit.policy_scope!(user, Post)).to eq :published
end
it "returns an instantiated policy scope given an active model class" do
expect(Pundit.policy_scope!(user, Comment)).to eq Comment
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
end
describe ".policy" do
it "returns an instantiated policy given a plain model instance" do
policy = Pundit.policy(user, post)
expect(policy.user).to eq user
expect(policy.post).to eq post
end
it "returns an instantiated policy given an active model instance" do
policy = Pundit.policy(user, comment)
expect(policy.user).to eq user
expect(policy.comment).to eq comment
end
it "returns an instantiated policy given a plain model class" do
policy = Pundit.policy(user, Post)
expect(policy.user).to eq user
expect(policy.post).to eq Post
end
it "returns an instantiated policy given an active model class" do
policy = Pundit.policy(user, Comment)
expect(policy.user).to eq user
expect(policy.comment).to eq Comment
end
it "returns nil if the given policy can't be found" do
expect(Pundit.policy(user, article)).to be_nil
expect(Pundit.policy(user, Article)).to be_nil
end
describe "with .policy_class set on the model" do
it "returns an instantiated policy given a plain model instance" do
policy = Pundit.policy(user, artificial_blog)
expect(policy.user).to eq user
expect(policy.blog).to eq artificial_blog
end
it "returns an instantiated policy given a plain model class" do
policy = Pundit.policy(user, ArtificialBlog)
expect(policy.user).to eq user
expect(policy.blog).to eq ArtificialBlog
end
it "returns an instantiated policy given a plain model instance providing an anonymous class" do
policy = Pundit.policy(user, article_tag)
expect(policy.user).to eq user
expect(policy.tag).to eq article_tag
end
it "returns an instantiated policy given a plain model class providing an anonymous class" do
policy = Pundit.policy(user, ArticleTag)
expect(policy.user).to eq user
expect(policy.tag).to eq ArticleTag
end
end
end
describe ".policy!" do
it "returns an instantiated policy given a plain model instance" do
policy = Pundit.policy!(user, post)
expect(policy.user).to eq user
expect(policy.post).to eq post
end
it "returns an instantiated policy given an active model instance" do
policy = Pundit.policy!(user, comment)
expect(policy.user).to eq user
expect(policy.comment).to eq comment
end
it "returns an instantiated policy given a plain model class" do
policy = Pundit.policy!(user, Post)
expect(policy.user).to eq user
expect(policy.post).to eq Post
end
it "returns an instantiated policy given an active model class" do
policy = Pundit.policy!(user, Comment)
expect(policy.user).to eq user
expect(policy.comment).to eq Comment
end
it "throws an exception if the given policy can't be found" do
expect { Pundit.policy!(user, article) }.to raise_error(Pundit::NotDefinedError)
expect { Pundit.policy!(user, Article) }.to raise_error(Pundit::NotDefinedError)
end
end
describe "#verify_authorized" do
it "does nothing when authorized" do
controller.authorize(post)
controller.verify_authorized
end
it "raises an exception when not authorized" do
expect { controller.verify_authorized }.to raise_error(Pundit::NotAuthorizedError)
end
end
describe "#verify_policy_scoped" do
it "does nothing when policy_scope is used" do
controller.policy_scope(Post)
controller.verify_policy_scoped
end
it "raises an exception when policy_scope is not used" do
expect { controller.verify_policy_scoped }.to raise_error(Pundit::NotAuthorizedError)
end
end
describe "#authorize" do
it "infers the policy name and authorized based on it" do
expect(controller.authorize(post)).to be_truthy
end
it "can be given a different permission to check" do
expect(controller.authorize(post, :show?)).to be_truthy
expect { controller.authorize(post, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
end
it "works with anonymous class policies" do
expect(controller.authorize(article_tag, :show?)).to be_truthy
expect { controller.authorize(article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
end
it "raises an error when the permission check fails" do
expect { controller.authorize(Post.new) }.to raise_error(Pundit::NotAuthorizedError)
end
it "raises an error with a query and action" do
expect { controller.authorize(post, :destroy?) }.to raise_error do |error|
expect(error.query).to eq :destroy?
expect(error.record).to eq post
expect(error.policy).to eq controller.policy(post)
end
end
end
describe "#pundit_user" do
it 'returns the same thing as current_user' do
expect(controller.pundit_user).to eq controller.current_user
end
end
describe ".policy" do
it "returns an instantiated policy" do
policy = controller.policy(post)
expect(policy.user).to eq user
expect(policy.post).to eq post
end
it "throws an exception if the given policy can't be found" do
expect { controller.policy(article) }.to raise_error(Pundit::NotDefinedError)
end
it "allows policy to be injected" do
new_policy = OpenStruct.new
controller.policy = new_policy
expect(controller.policy(post)).to eq new_policy
end
end
describe ".policy_scope" do
it "returns an instantiated policy scope" do
expect(controller.policy_scope(Post)).to eq :published
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 "allows policy_scope to be injected" do
new_scope = OpenStruct.new
controller.policy_scope = new_scope
expect(controller.policy_scope(post)).to eq new_scope
end
end
end