/test/dsl_base_test.rb
Ruby | 756 lines | 624 code | 131 blank | 1 comment | 9 complexity | 667ece31888fde54ea62ccc964897ea2 MD5 | raw file
- require 'ostruct'
- require 'test_helper'
- require File.join(File.dirname(__FILE__), '..', 'lib', 'acl9', 'controller_extensions', 'dsl_base')
- class FakeUser
- def initialize
- @roles = {}
- end
- def has_role?(role, object = nil)
- @roles.include?([role.to_s, object])
- end
- def <<(role)
- role = [role] unless role.is_a? Array
- role << nil if role.size == 1
- raise unless role[0]
- role[0] = role[0].to_s
- @roles[role] = true
- end
- end
- class DslTester < Acl9::Dsl::Base
- def initialize
- super
- @_subject = nil
- @_objects = {}
- @_current_action = nil
- end
-
- def permit(user, *args)
- check_allowance(user, *args).should == true
- self
- end
-
- def forbid(user, *args)
- check_allowance(user, *args).should == false
- self
- end
-
- def show_code
- puts "\n", allowance_expression
- self
- end
- protected
- def check_allowance(subject, *args)
- @_subject = subject
- @_current_action = (args[0] || 'index').to_s
- @_objects = args.last.is_a?(Hash) ? args.last : {}
- @_callable = @_objects.delete(:call)
- instance_eval(allowance_expression)
- end
- def _subject_ref
- "@_subject"
- end
- def _object_ref(object)
- "@_objects[:#{object}]"
- end
- def _action_ref
- "@_current_action"
- end
- def _method_ref(method)
- "@_callable.send(:#{method})"
- end
- end
- #describe Acl9::Dsl::Base do
- class DslBaseTest < Test::Unit::TestCase
- class ThatFoo; end
- class ThatBar; end
- def arg_err(&block)
- lambda do
- acl(&block)
- end.should raise_error(ArgumentError)
- end
- def acl(&block)
- tester = DslTester.new
- tester.acl_block!(&block)
-
- tester
- end
- def permit_some(tester, user, actions, vars = {})
- actions.each { |act| tester.permit(user, act, vars) }
- (@all_actions - actions).each { |act| tester.forbid(user, act, vars) }
- end
-
- before do
- @user = FakeUser.new
- @user2 = FakeUser.new
- @user3 = FakeUser.new
- @foo = ThatFoo.new
- @foo2 = ThatFoo.new
- @foo3 = ThatFoo.new
- end
- describe "default" do
- it "should set default action to deny if none specified" do
- acl do end.default_action.should == :deny
- end
-
- it "should set default action to allow" do
- acl do
- default :allow
- end.default_action.should == :allow
- end
-
- it "should set default action to deny" do
- acl do
- default :deny
- end.default_action.should == :deny
- end
-
- it "should raise ArgumentError with unknown default_action" do
- arg_err do
- default 123
- end
- end
-
- it "should raise ArgumentError when default is called more than once" do
- arg_err do
- default :deny
- default :deny
- end
- end
- end
- describe "empty blocks" do
- it "should deny everyone with default deny" do
- acl do
- end.forbid(nil).forbid(@user)
- end
-
- it "should allow everyone with default allow" do
- acl do
- default :allow
- end.permit(nil).permit(@user)
- end
- end
- describe "empty" do
- it "allow should raise an ArgumentError" do
- arg_err { allow }
- end
-
- it "deny should raise an ArgumentError" do
- arg_err { deny }
- end
- end
- describe "anonymous" do
- it "'allow nil' should allow anonymous, but not logged in" do
- acl do
- allow nil
- end.permit(nil).forbid(@user)
- end
-
- it "'allow anonymous' should allow anonymous, but not logged in" do
- acl do
- allow anonymous
- end.permit(nil).forbid(@user)
- end
-
- it "'deny nil' should deny anonymous, but not logged in" do
- acl do
- default :allow
- deny nil
- end.forbid(nil).permit(@user)
- end
-
- it "'deny anonymous' should deny anonymous, but not logged in" do
- acl do
- default :allow
- deny anonymous
- end.forbid(nil).permit(@user)
- end
- end
- describe "all" do
- it "'allow all' should allow all" do
- acl do
- allow all
- end.permit(nil).permit(@user)
- end
-
- it "'deny all' should deny all" do
- acl do
- default :allow
- deny all
- end.forbid(nil).forbid(@user)
- end
- end
- describe "default :allow" do
- it "should allow when neither allow nor deny conditions are matched" do
- acl do
- default :allow
- allow :blah
- deny :bzz
- end.permit(nil).permit(@user)
- end
-
- it "should deny when deny is matched, but allow is not" do
- acl do
- default :allow
- deny all
- allow :blah
- end.forbid(nil).forbid(@user)
- end
-
- it "should allow when allow is matched, but deny is not" do
- @user << :cool
- acl do
- default :allow
- deny nil
- allow :cool
- end.permit(@user)
- end
-
- it "should allow both allow and deny conditions are matched" do
- @user << :cool
- acl do
- default :allow
- deny :cool
- allow :cool
- end.permit(@user)
-
- acl do
- default :allow
- deny all
- allow all
- end.permit(@user).permit(nil).permit(@user2)
- end
- end
-
- describe "logged_in" do
- it "'allow logged_in' should allow logged in, but not anonymous" do
- acl do
- allow logged_in
- end.forbid(nil).permit(@user)
- end
-
- it "'allow logged_in' should deny logged in, but not anonymous" do
- acl do
- default :allow
- deny logged_in
- end.permit(nil).forbid(@user)
- end
- end
- describe "default :deny" do
- it "should deny when neither allow nor deny conditions are matched" do
- acl do
- default :deny
- allow :blah
- deny :bzz
- end.forbid(nil).forbid(@user)
- end
-
- it "should deny when deny is matched, but allow is not" do
- acl do
- default :deny
- deny all
- allow :blah
- end.forbid(nil).forbid(@user)
- end
-
- it "should allow when allow is matched, but deny is not" do
- @user << :cool
- acl do
- default :deny
- deny nil
- allow :cool
- end.permit(@user)
- end
-
- it "should deny both allow and deny conditions are matched" do
- @user << :cool
- acl do
- default :deny
- deny :cool
- allow :cool
- end.forbid(@user)
-
- acl do
- default :deny
- deny all
- allow all
- end.forbid(@user).forbid(nil).forbid(@user2)
- end
- end
- describe "global roles" do
- it "#allow with role" do
- @user << :admin
- acl { allow :admin }.permit(@user).forbid(nil).forbid(@user2)
- end
-
- it "#allow with plural role name" do
- @user << :mouse
- acl do
- allow :mice
- end.permit(@user).forbid(nil).forbid(@user2)
- end
- it "#allow with several roles" do
- @user << :admin
- @user << :cool
- @user2 << :cool
- @user3 << :super
- acl do
- allow :admin
- allow :cool
- end.permit(@user).permit(@user2).forbid(nil).forbid(@user3)
- end
-
- it "#deny with role" do
- @user << :foo
- acl { default :allow; deny :foo }.forbid(@user).permit(nil).permit(@user2)
- end
-
- it "#deny with plural role name" do
- @user << :mouse
- acl do
- default :allow
- deny :mice
- end.forbid(@user).permit(nil).permit(@user2)
- end
- it "#deny with several roles" do
- @user << :admin
- @user << :cool
- @user2 << :cool
- @user3 << :super
- acl do
- default :allow
- deny :admin
- deny :cool
- end.forbid(@user).forbid(@user2).permit(nil).permit(@user3)
- end
- end
- describe "prepositions" do
- [:of, :for, :in, :on, :at, :by].each do |prep|
- it "#allow with object role (:#{prep}) should check controller's ivar" do
- @user << [:manager, @foo]
- acl do
- allow :manager, prep => :foo
- end.
- permit(@user, :foo => @foo).
- forbid(@user, :foo => @foo2).
- forbid(@user, :foo => ThatFoo).
- forbid(nil, :foo => @foo).
- forbid(@user2, :foo => @foo)
- end
- it "#allow with invalid value for preposition :#{prep} should raise an ArgumentError" do
- arg_err do
- allow :hom, :by => 1
- end
- end
- end
- it "#allow with a class role should verify this role against a class" do
- @user << [:owner, ThatFoo]
- acl do
- allow :owner, :of => ThatFoo
- end.permit(@user).forbid(nil).forbid(@user2)
- end
-
- [:of, :for, :in, :on, :at, :by].each do |prep|
- it "#deny with object role (:#{prep}) should check controller's ivar" do
- @user << [:bastard, @foo]
- acl do
- default :allow
- deny :bastard, prep => :foo
- end.
- forbid(@user, :foo => @foo).
- permit(@user, :foo => @foo2).
- permit(@user, :foo => ThatFoo).
- permit(nil, :foo => @foo).
- permit(@user2, :foo => @foo)
- end
-
- it "#deny with invalid value for preposition :#{prep} should raise an ArgumentError" do
- arg_err do
- deny :her, :for => "him"
- end
- end
- end
- it "#deny with a class role should verify this role against a class" do
- @user << [:ignorant, ThatFoo]
- acl do
- default :allow
- deny :ignorant, :of => ThatFoo
- end.forbid(@user).permit(nil).permit(@user2)
- end
- it "#allow with several prepositions should raise an ArgumentError" do
- arg_err do
- allow :some, :by => :one, :for => :another
- end
- end
- it "#deny with several prepositions should raise an ArgumentError" do
- arg_err do
- deny :some, :in => :here, :on => :today
- end
- end
- end
- describe ":to and :except" do
- it "should raise an ArgumentError when both :to and :except are specified" do
- arg_err do
- allow all, :to => :index, :except => ['show', 'edit']
- end
- end
- describe "" do
- after do
- %w(index show).each { |act| @list.permit(nil, act) }
- %w(edit update delete destroy).each { |act| @list.forbid(nil, act) }
-
- %w(index show edit update).each { |act| @list.permit(@user, act) }
- %w(delete destroy).each { |act| @list.forbid(@user, act) }
- %w(index show edit update delete destroy).each { |act| @list.permit(@user2, act) }
- end
- it ":to should limit rule scope to specified actions" do
- @user << :manager
- @user2 << :trusted
- @list = acl do
- allow all, :to => [:index, :show]
- allow 'manager', :to => :edit
- allow 'manager', :to => 'update'
- allow 'trusted', :to => %w(edit update delete destroy)
- end
- end
-
- it ":except should limit rule scope to all actions except specified" do
- @user << :manager
- @user2 << :trusted
- @list = acl do
- allow all, :except => %w(edit update delete destroy)
- allow 'manager', :except => %w(delete destroy)
- allow 'trusted'
- end
- end
- end
- end
- describe "conditions" do
- [:if, :unless].each do |cond|
- it "should raise ArgumentError when #{cond} is not a Symbol" do
- arg_err do
- allow nil, cond => 123
- end
- end
- end
- it "allow ... :if" do
- acl do
- allow nil, :if => :meth
- end.
- permit(nil, :call => OpenStruct.new(:meth => true)).
- forbid(nil, :call => OpenStruct.new(:meth => false))
- end
-
- it "allow ... :unless" do
- acl do
- allow nil, :unless => :meth
- end.
- permit(nil, :call => OpenStruct.new(:meth => false)).
- forbid(nil, :call => OpenStruct.new(:meth => true))
- end
-
- it "deny ... :if" do
- acl do
- default :allow
- deny nil, :if => :meth
- end.
- permit(nil, :call => OpenStruct.new(:meth => false)).
- forbid(nil, :call => OpenStruct.new(:meth => true))
- end
- it "deny ... :unless" do
- acl do
- default :allow
- deny nil, :unless => :meth
- end.
- permit(nil, :call => OpenStruct.new(:meth => true)).
- forbid(nil, :call => OpenStruct.new(:meth => false))
- end
- end
- describe "several roles as arguments" do
- it "#allow should be able to receive a role list (global roles)" do
- @user << :bzz
- @user2 << :whoa
- acl do
- allow :bzz, :whoa
- end.permit(@user).permit(@user2).forbid(nil).forbid(@user3)
- end
-
- it "#allow should be able to receive a role list (object roles)" do
- @user << [:maker, @foo]
- @user2 << [:faker, @foo2]
- acl do
- allow :maker, :faker, :of => :foo
- end.
- permit(@user, :foo => @foo).
- forbid(@user, :foo => @foo2).
- permit(@user2, :foo => @foo2).
- forbid(@user2, :foo => @foo).
- forbid(@user3, :foo => @foo).
- forbid(@user3, :foo => @foo2).
- forbid(nil)
- end
-
- it "#allow should be able to receive a role list (class roles)" do
- @user << [:frooble, ThatFoo]
- @user2 << [:oombigle, ThatFoo]
- @user3 << :frooble
- acl do
- allow :frooble, :oombigle, :by => ThatFoo
- end.
- permit(@user).
- permit(@user2).
- forbid(@user3).
- forbid(nil)
- end
-
- it "#deny should be able to receive a role list (global roles)" do
- @user << :bzz
- @user2 << :whoa
- acl do
- default :allow
- deny :bzz, :whoa
- end.forbid(@user).forbid(@user2).permit(nil).permit(@user3)
- end
-
- it "#deny should be able to receive a role list (object roles)" do
- @user << [:maker, @foo]
- @user2 << [:faker, @foo2]
- @user3 = FakeUser.new
- acl do
- default :allow
- deny :maker, :faker, :of => :foo
- end.
- forbid(@user, :foo => @foo).
- permit(@user, :foo => @foo2).
- forbid(@user2, :foo => @foo2).
- permit(@user2, :foo => @foo).
- permit(@user3, :foo => @foo).
- permit(@user3, :foo => @foo2).
- permit(nil)
- end
-
- it "#deny should be able to receive a role list (class roles)" do
- @user << [:frooble, ThatFoo]
- @user2 << [:oombigle, ThatFoo]
- @user3 << :frooble
- acl do
- default :allow
- deny :frooble, :oombigle, :by => ThatFoo
- end.
- forbid(@user).
- forbid(@user2).
- permit(@user3).
- permit(nil)
- end
- it "should also respect :to and :except" do
- class Moo; end
- @user << :foo
- @user2 << [:joo, @foo]
- @user3 << [:qoo, Moo]
- acl do
- allow :foo, :boo, :to => [:index, :show]
- allow :zoo, :joo, :by => :foo, :to => [:edit, :update]
- allow :qoo, :woo, :of => Moo
- deny :qoo, :woo, :of => Moo, :except => [:delete, :destroy]
- end.
- permit(@user, 'index').
- permit(@user, 'show').
- forbid(@user, 'edit').
- permit(@user2, 'edit', :foo => @foo).
- permit(@user2, 'update', :foo => @foo).
- forbid(@user2, 'show', :foo => @foo).
- forbid(@user2, 'show').
- permit(@user3, 'delete').
- permit(@user3, 'destroy').
- forbid(@user3, 'edit').
- forbid(@user3, 'show')
- end
- end
- describe "actions block" do
- it "should raise an ArgumentError when actions has no block" do
- arg_err do
- actions :foo, :bar
- end
- end
-
- it "should raise an ArgumentError when actions has no arguments" do
- arg_err do
- actions do end
- end
- end
-
- it "should raise an ArgumentError when actions is called inside actions block" do
- arg_err do
- actions :foo, :bar do
- actions :foo, :bar do
- end
- end
- end
- end
-
- it "should raise an ArgumentError when default is called inside actions block" do
- arg_err do
- actions :foo, :bar do
- default :allow
- end
- end
- end
- [:to, :except].each do |opt|
- it "should raise an ArgumentError when allow is called with #{opt} option" do
- arg_err do
- actions :foo do
- allow all, opt => :bar
- end
- end
- end
-
- it "should raise an ArgumentError when deny is called with #{opt} option" do
- arg_err do
- actions :foo do
- deny all, opt => :bar
- end
- end
- end
- end
- it "empty actions block should do nothing" do
- acl do
- actions :foo do
- end
- allow all
- end.permit(nil).permit(nil, :foo)
- end
- it "#allow should limit its scope to specified actions" do
- @user << :bee
- acl do
- actions :edit do
- allow :bee
- end
- end.
- permit(@user, :edit).
- forbid(@user, :update)
- end
- it "#deny should limit its scope to specified actions" do
- @user << :bee
- acl do
- default :allow
- actions :edit do
- deny :bee
- end
- end.
- forbid(@user, :edit).
- permit(@user, :update)
- end
- it "#allow and #deny should work together inside actions block" do
- @foo = ThatFoo.new
- @user << [:owner, @foo]
- @user2 << :hacker
- @user2 << :the_destroyer
- @user3 << [:owner, @foo]
- @user3 << :hacker
- list = acl do
- actions :show, :index do
- allow all
- end
- actions :edit, :update do
- allow :owner, :of => :object
- deny :hacker
- end
- actions :delete, :destroy do
- allow :owner, :of => :object
- allow :the_destroyer
- end
- end
- @all_actions = %w(show index edit update delete destroy)
- permit_some(list, @user, @all_actions, :object => @foo)
- permit_some(list, @user2, %w(show index delete destroy))
- permit_some(list, @user3, %w(show index delete destroy), :object => @foo)
- end
- end
- end