Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
226 lines (184 sloc) 6.51 KB
require 'spec_helper'
describe AccessGranted::Policy do
let(:klass) { Class.new { include AccessGranted::Policy } }
subject(:policy) { klass.new(nil) }
describe "#configure" do
before :each do
@member = FakeUser.new(1, false, false, false)
@mod = FakeUser.new(2, true, false, false)
@admin = FakeUser.new(3, false, true, false)
@banned = FakeUser.new(4, false, true, true)
end
it "passes user object to permission block" do
post_owner = double(id: 123)
other_user = double(id: 5)
post = FakePost.new(1, post_owner.id)
klass = Class.new do
include AccessGranted::Policy
def configure
role :member do
can :destroy, FakePost do |post, user|
post.user_id == user.id
end
end
end
end
expect(klass.new(post_owner).can?(:destroy, post)).to eq(true)
expect(klass.new(other_user).can?(:destroy, post)).to eq(false)
end
it "selects permission based on role priority" do
klass = Class.new do
include AccessGranted::Policy
def configure
role :administrator, { is_admin: true } do
can :destroy, String
end
role :moderator, { is_moderator: true } do
can :update, String
end
role :member do
can :read, String
end
end
end
expect(klass.new(@admin).can?(:destroy, String)).to eq(true)
expect(klass.new(@admin).can?(:read, String)).to eq(true)
expect(klass.new(@member).cannot?(:destroy, String)).to eq(true)
expect(klass.new(@member).can?(:read, String)).to eq(true)
expect(klass.new(@mod).can?(:read, String)).to eq(true)
expect(klass.new(@mod).cannot?(:destroy, String)).to eq(true)
end
context "when multiple roles define the same permission" do
it "checks all roles until conditions are met" do
user_post = FakePost.new(1, @member.id)
other_post = FakePost.new(2, 66)
klass = Class.new do
include AccessGranted::Policy
def configure
role :administrator, { is_admin: true } do
can :destroy, FakePost
end
role :member do
can :destroy, FakePost do |post, user|
post.user_id == user.id
end
end
end
end
expect(klass.new(@admin).can?(:destroy, user_post)).to eq(true)
expect(klass.new(@admin).can?(:destroy, other_post)).to eq(true)
expect(klass.new(@member).can?(:destroy, user_post)).to eq(true)
expect(klass.new(@member).cannot?(:destroy, other_post)).to eq(true)
end
end
it "resolves permissions without subject" do
klass = Class.new do
include AccessGranted::Policy
def configure
role :member do
can :vague_action
end
end
end
expect(klass.new(@member).can?(:vague_action)).to eq(true)
end
describe "#cannot" do
it "forbids action when used in superior role" do
klass = Class.new do
include AccessGranted::Policy
def configure
role :banned, { is_banned: true } do
cannot :create, String
end
role :member do
can :create, String
end
end
end
expect(klass.new(@member).can?(:create, String)).to eq(true)
expect(klass.new(@banned).can?(:create, String)).to eq(false)
end
end
describe "#authorize!" do
let(:klass) do
Class.new do
include AccessGranted::Policy
def configure
role(:member) { can :create, String }
end
end
end
it "raises AccessDenied if action is not allowed" do
expect { klass.new(@member).authorize!(:create, Integer) }.to raise_error do |err|
expect(err).to be_a(AccessGranted::AccessDenied)
expect(err.action).to eq(:create)
expect(err.subject).to eq(Integer)
end
end
it "raises AccessDenied with supplied message if action is not allowed" do
message = 'You are not allowed to create Integer'
expect { klass.new(@member).authorize!(:create, Integer, message) }.to raise_error do |err|
expect(err).to be_a(AccessGranted::AccessDenied)
expect(err.action).to eq(:create)
expect(err.subject).to eq(Integer)
expect(err.message).to eq(message)
end
end
it "returns the subject if allowed" do
expect(klass.new(@member).authorize!(:create, String)).to equal String
end
end
end
describe "#role" do
it "allows passing role class" do
klass_role = Class.new AccessGranted::Role do
def configure
can :read, String
end
end
subject.role(:member, klass_role)
expect(policy.roles.first.class).to eq(klass_role)
end
it "returns roles in the order of priority" do
policy.role(:admin)
policy.role(:moderator)
policy.role(:user)
policy.role(:guest)
expect(policy.roles.map(&:name)).to eq([:admin, :moderator, :user, :guest])
end
it "allows defining a default role" do
policy.role(:member)
expect(policy.roles.map(&:name)).to include(:member)
end
it "does not allow duplicate role names" do
policy.role(:member)
expect { policy.role(:member) }.to raise_error AccessGranted::DuplicateRole
end
it "allows nesting `can` calls inside a block" do
role = policy.role(:member) do
can :read, String
end
expect(role.find_permission(:read, String).granted).to eq(true)
end
end
describe "#applicable_roles" do
let(:user) { double("User", is_moderator: true, is_admin: true) }
subject(:policy) { klass.new(user) }
before do
policy.role(:administrator, { is_admin: true })
policy.role(:moderator, { is_moderator: true })
policy.role(:member)
end
context "user matches all roles" do
it "returns all matching roles in the order of priority" do
expect(policy.applicable_roles.map(&:name)).to eq([:administrator, :moderator, :member])
end
end
context "user is just an admin" do
let(:user) { double("User", is_moderator: false, is_admin: true) }
it 'returns array with admin and member roles' do
expect(policy.applicable_roles.map(&:name)).to eq([:administrator, :member])
end
end
end
end