walruz 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,99 @@
1
+ module Walruz
2
+ module Subject
3
+
4
+ def self.included(base)
5
+ base.class_eval do
6
+
7
+ def self._walruz_policies=(policies)
8
+ @_walruz_policies = policies
9
+ end
10
+
11
+ def self._walruz_policies
12
+ @_walruz_policies
13
+ end
14
+
15
+ extend ClassMethods
16
+ end
17
+ end
18
+
19
+ # @private
20
+ def can_be?(action, actor)
21
+ check_authorization_actions_are_setted(action)
22
+ action = if self.class._walruz_policies.key?(:default)
23
+ self.class._walruz_policies.key?(action) ? action : :default
24
+ else
25
+ if self.class._walruz_policies.key?(action)
26
+ action
27
+ else
28
+ raise ActionNotFound.new(:subject_action, :subject => self,
29
+ :action => action)
30
+ end
31
+ end
32
+
33
+ result = self.class._walruz_policies[action].
34
+ return_policy.
35
+ new.
36
+ safe_authorized?(actor, self)
37
+
38
+ result
39
+ end
40
+
41
+ # @private
42
+ def check_authorization_actions_are_setted(action)
43
+ if self.class._walruz_policies.nil?
44
+ message =<<BEGIN
45
+ You need to invoke `check_authorizations :#{action} => Policies::SomePolicy` on the #{self.class.name} class
46
+ BEGIN
47
+ raise AuthorizationActionsNotDefined.new(message)
48
+ end
49
+ end
50
+
51
+ module ClassMethods
52
+
53
+ #
54
+ # Stablishes the actions that can be made with a subject. You may
55
+ # specify as many actions as you like, and also you may have a default
56
+ # policy, that will get execute if a specified flag doesn't exist.
57
+ # You just have to pass the action :default, or just the policy class.
58
+ #
59
+ # Example:
60
+ # # Without :default key
61
+ # class UserProfile
62
+ # check_authorizations :read => Policies::FriendPolicy,
63
+ # :write => Policies::OwnerPolicy
64
+ # end
65
+ #
66
+ # # With :default key
67
+ # class UserProfile
68
+ # check_authorizations :read => Policies::FriendPolicy,
69
+ # :write => Policies::OwnerPolicy,
70
+ # :default => Policies::AdminPolicy
71
+ # end
72
+ #
73
+ # # Without any key at all
74
+ # class UserProfile
75
+ # # this policy is the default one
76
+ # check_authorizations Policies::OwnerPolicy
77
+ # end
78
+ #
79
+ # Once you stablish the authorizations policies on a subject, you can
80
+ # check if an actor is able to interact with it via the Actor#can? method
81
+ #
82
+ # Example: current_user.can?(:read, profile)
83
+ #
84
+ # It's recommended (but not mandatory) that a policy specified to the action
85
+ # is inherting from Walruz::Policy
86
+ #
87
+ def check_authorizations(policy_map)
88
+ case policy_map
89
+ when Hash
90
+ self._walruz_policies = policy_map
91
+ else
92
+ self._walruz_policies = { :default => policy_map }
93
+ end
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+ end
@@ -0,0 +1,119 @@
1
+ module Walruz
2
+ module Utils
3
+
4
+ module PolicyCompositionHelper
5
+
6
+ # NOTE: Not using cattr_accessor to avoid dependencies with ActiveSupport
7
+
8
+ def policies=(policies)
9
+ @policies = policies
10
+ end
11
+
12
+ def policies
13
+ @policies
14
+ end
15
+
16
+ def policy=(policy)
17
+ @policy = policy
18
+ end
19
+
20
+ def policy
21
+ @policy
22
+ end
23
+
24
+ def set_params(params = {})
25
+ @params ||= {}
26
+ @params.merge!(params)
27
+ end
28
+
29
+ def params
30
+ @params
31
+ end
32
+
33
+ end
34
+
35
+ def orP(*policies)
36
+ clazz = Class.new(Walruz::Policy) do
37
+ extend PolicyCompositionHelper
38
+
39
+ def authorized?(actor, subject)
40
+ result = nil
41
+ self.class.policies.detect do |policy|
42
+ result = policy.new.safe_authorized?(actor, subject)
43
+ result[0]
44
+ end
45
+ result[0] ? result : result[0]
46
+ end
47
+
48
+ end
49
+ clazz.policies = policies
50
+ clazz
51
+ end
52
+
53
+ def andP(*policies)
54
+ clazz = Class.new(Walruz::Policy) do
55
+ extend PolicyCompositionHelper
56
+
57
+ def authorized?(actor, subject)
58
+ acum = [true, {}]
59
+ self.class.policies.each do |policy|
60
+ break unless acum[0]
61
+ policy_instance = policy.new
62
+ policy_instance.set_params(acum[1])
63
+ result = policy_instance.safe_authorized?(actor, subject)
64
+ acum[0] &&= result[0]
65
+ acum[1].merge!(result[1])
66
+ end
67
+ acum[0] ? acum : acum[0]
68
+ end
69
+
70
+ def self.policy_keyword
71
+ (self.policies.map { |p| p.policy_keyword.to_s[0..-2] }.join('_and_') + "?").to_sym
72
+ end
73
+
74
+ end
75
+ clazz.policies = policies
76
+ clazz
77
+ end
78
+
79
+ def notP(policy)
80
+ clazz = Class.new(Walruz::Policy) do
81
+ extend PolicyCompositionHelper
82
+
83
+ def authorized?(actor, subject)
84
+ result = self.class.policy.new.safe_authorized?(actor, subject)
85
+ !result[0]
86
+ end
87
+
88
+ def self.policy_keyword
89
+ keyword = self.policy.policy_keyword.to_s[0..-2]
90
+ :"not(#{keyword})?"
91
+ end
92
+
93
+ end
94
+ clazz.policy = policy
95
+ clazz
96
+ end
97
+
98
+ def lift_subject(key, policy, &block)
99
+ clazz = Class.new(Walruz::Policy) do
100
+ extend PolicyCompositionHelper
101
+
102
+ def authorized?(actor, subject)
103
+ params = self.class.params
104
+ new_subject = subject.send(params[:key])
105
+ result = self.class.policy.new.safe_authorized?(actor, new_subject)
106
+ params[:callback].call(result[0], result[1], actor, subject) if params[:callback]
107
+ result
108
+ end
109
+
110
+ end
111
+ clazz.policy = policy
112
+ clazz.set_params(:key => key, :callback => block)
113
+ clazz
114
+ end
115
+
116
+ module_function(:orP, :andP, :notP, :lift_subject)
117
+
118
+ end
119
+ end
data/lib/walruz.rb ADDED
@@ -0,0 +1,54 @@
1
+ module Walruz
2
+
3
+ class NotAuthorized < Exception
4
+ end
5
+
6
+ class AuthorizationActionsNotDefined < Exception
7
+ end
8
+
9
+ class ActionNotFound < Exception
10
+
11
+ def initialize(failure, params = {})
12
+ case failure
13
+ when :subject_action
14
+ super("%s class doesn't have an authorization action called :%s nor a :default policy" % [params[:subject].class.name, params[:action]])
15
+ when :policy_label
16
+ super("There is no Policy with the label %s" % params[:label])
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ base_path = File.dirname(__FILE__)
23
+ autoload :Actor, base_path + '/walruz/actor'
24
+ autoload :Subject, base_path + '/walruz/subject'
25
+ autoload :Policy, base_path + '/walruz/policy'
26
+ autoload :Utils, base_path + '/walruz/utils'
27
+
28
+ def self.setup
29
+ config = Config.new
30
+ yield config
31
+ end
32
+
33
+ def self.policies
34
+ Walruz::Policy.policies
35
+ end
36
+
37
+ class Config
38
+
39
+ def actors=(actors)
40
+ Array(actors).each do |actor|
41
+ actor.send(:include, Actor)
42
+ end
43
+ end
44
+
45
+ def subjects=(subjects)
46
+ Array(subjects).each do |subject|
47
+ subject.send(:include, Subject)
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+
54
+ end
data/spec/scenario.rb ADDED
@@ -0,0 +1,133 @@
1
+ class Beatle
2
+ include Walruz::Actor
3
+ include Walruz::Subject
4
+
5
+ attr_reader :name
6
+ attr_accessor :songs
7
+ attr_accessor :colaborations
8
+
9
+ def initialize(name)
10
+ @name = name
11
+ @songs = []
12
+ @colaborations = []
13
+ end
14
+
15
+ def sing_the_song(song)
16
+ response = can!(:sing, song)
17
+ case response[:owner]
18
+ when Colaboration
19
+ authors = response[:owner].authors.dup
20
+ authors.delete(self)
21
+ authors.map! { |author| author.name }
22
+ "I need %s to play this song properly" % authors.join(', ')
23
+ when Beatle
24
+ "I just need myself, Let's Rock! \\m/"
25
+ end
26
+ end
27
+
28
+ def sing_with_john(song)
29
+ can!(:sing_with_john, song)
30
+ "Ok John, Let's Play '%s'" % song.name
31
+ end
32
+
33
+
34
+ JOHN = self.new("John")
35
+ PAUL = self.new("Paul")
36
+ RINGO = self.new("Ringo")
37
+ GEORGE = self.new("George")
38
+ end
39
+
40
+ class Colaboration
41
+
42
+ attr_accessor :authors
43
+ attr_accessor :songs
44
+
45
+ def initialize(*authors)
46
+ authors.each do |author|
47
+ author.colaborations << self
48
+ end
49
+ @authors = authors
50
+ @songs = []
51
+ end
52
+
53
+ JOHN_PAUL = self.new(Beatle::JOHN, Beatle::PAUL)
54
+ JOHN_PAUL_GEORGE = self.new(Beatle::JOHN, Beatle::PAUL, Beatle::GEORGE)
55
+ JOHN_GEORGE = self.new(Beatle::JOHN, Beatle::GEORGE)
56
+ end
57
+
58
+ class SubjectIsActorPolicy < Walruz::Policy
59
+
60
+ def authorized?(actor, subject)
61
+ actor == subject
62
+ end
63
+
64
+ end
65
+
66
+ # class AuthorPolicy < Walruz::Policy
67
+ #
68
+ # def authorized?(beatle, song)
69
+ # if song.author == beatle
70
+ # [true, { :owner => beatle }]
71
+ # else
72
+ # false
73
+ # end
74
+ # end
75
+ #
76
+ # end
77
+
78
+ AuthorPolicy = Walruz::Utils.lift_subject(:author, SubjectIsActorPolicy) do |authorized, params, actor, subject|
79
+ params.merge!(:owner => actor) if authorized
80
+ end
81
+
82
+ class AuthorInColaborationPolicy < Walruz::Policy
83
+
84
+ def authorized?(beatle, song)
85
+ return false unless song.colaboration
86
+ if song.colaboration.authors.include?(beatle)
87
+ [true, { :owner => song.colaboration }]
88
+ else
89
+ false
90
+ end
91
+ end
92
+
93
+ end
94
+
95
+ class ColaboratingWithJohnPolicy < Walruz::Policy
96
+ depends_on AuthorInColaborationPolicy
97
+
98
+ def authorized?(beatle, song)
99
+ params[:owner].authors.include?(Beatle::JOHN)
100
+ end
101
+
102
+ end
103
+
104
+ class Song
105
+ include Walruz::Subject
106
+ extend Walruz::Utils
107
+
108
+ check_authorizations :sing => orP(AuthorPolicy, AuthorInColaborationPolicy),
109
+ :sell => andP(AuthorPolicy, notP(AuthorInColaborationPolicy)),
110
+ :sing_with_john => ColaboratingWithJohnPolicy
111
+ attr_accessor :name
112
+ attr_accessor :colaboration
113
+ attr_accessor :author
114
+
115
+ def initialize(name, owner)
116
+ @name = name
117
+ case owner
118
+ when Colaboration
119
+ @colaboration = owner
120
+ when Beatle
121
+ @author = owner
122
+ end
123
+ owner.songs << self
124
+ end
125
+
126
+ A_DAY_IN_LIFE = self.new("A Day In Life", Colaboration::JOHN_PAUL)
127
+ YELLOW_SUBMARINE = self.new("Yellow Submarine", Colaboration::JOHN_PAUL)
128
+ TAXMAN = self.new("Taxman", Colaboration::JOHN_GEORGE)
129
+ YESTERDAY = self.new("Yesterday", Beatle::PAUL)
130
+ ALL_YOU_NEED_IS_LOVE = self.new("All You Need Is Love", Beatle::JOHN)
131
+ BLUE_JAY_WAY = self.new("Blue Jay Way", Beatle::GEORGE)
132
+ end
133
+
data/spec/spec.opts ADDED
@@ -0,0 +1,5 @@
1
+ --colour
2
+ --format specdoc
3
+ --loadby mtime
4
+ --reverse
5
+ --backtrace
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'pp'
4
+
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ require 'walruz'
8
+ require File.dirname(__FILE__) + '/scenario'
9
+
10
+ Spec::Runner.configure do |config|
11
+ end
@@ -0,0 +1,123 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe 'Walruz::Actor' do
4
+
5
+ it "should add an instance method `can!` to included classes" do
6
+ Beatle::JOHN.should respond_to(:can!)
7
+ end
8
+
9
+ it "should add an instance method `can?` to included classes" do
10
+ Beatle::JOHN.should respond_to(:can?)
11
+ end
12
+
13
+ it "should add an instance method `satisfies?` to included classes" do
14
+ Beatle::JOHN.should respond_to(:satisfies?)
15
+ end
16
+
17
+
18
+ describe "can!" do
19
+
20
+ it "should raise a Walruz::NotAuthorized error when the actor is not authorized" do
21
+ lambda do
22
+ Beatle::RINGO.sing_the_song(Song::ALL_YOU_NEED_IS_LOVE)
23
+ end.should raise_error(Walruz::NotAuthorized)
24
+ end
25
+
26
+ it "should not raise a Walruz::NotAuthorized error when the actor is authorized" do
27
+ lambda do
28
+ Beatle::JOHN.sing_the_song(Song::ALL_YOU_NEED_IS_LOVE)
29
+ end.should_not raise_error(Walruz::NotAuthorized)
30
+ end
31
+
32
+ it "should provide parameteres for the invokator correctly" do
33
+ Beatle::JOHN.sing_the_song(Song::ALL_YOU_NEED_IS_LOVE).should == "I just need myself, Let's Rock! \\m/"
34
+ Beatle::JOHN.sing_the_song(Song::YELLOW_SUBMARINE).should == "I need Paul to play this song properly"
35
+ end
36
+
37
+ end
38
+
39
+ describe '#can?' do
40
+
41
+ it "should be invoked only the first time and then return a cached solution" do
42
+ Song::ALL_YOU_NEED_IS_LOVE.should_receive(:can_be?).once.and_return([true, {}])
43
+ Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE)
44
+ Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE)
45
+ end
46
+
47
+ # @deprecated functionality
48
+ # WHY: When you execute `can?` you should probably have already executed `can!`
49
+ # it "should execute a given block if the condition is true" do
50
+ # proc_called = lambda { raise "Is being called" }
51
+ # lambda do
52
+ # Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE, &proc_called)
53
+ # end.should raise_error
54
+ # end
55
+
56
+ it "if a boolean third parameter is received it should not use the cached result" do
57
+ Beatle::JOHN.stub!(:can_without_caching?).and_return(true)
58
+ Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE).should be_true
59
+
60
+ Beatle::JOHN.stub!(:can_without_caching?).and_return(false)
61
+ Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE).should be_true
62
+ Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE, true).should be_false
63
+ end
64
+
65
+ it "should receive at least 2 parameters" do
66
+ lambda do
67
+ Beatle::JOHN.can?(:sing)
68
+ end.should raise_error(ArgumentError)
69
+ end
70
+
71
+ it "should receive at most 3 parameters" do
72
+ lambda do
73
+ Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE, true, false)
74
+ end.should raise_error(ArgumentError)
75
+ end
76
+
77
+
78
+ it "should execute a given block that receives a hash of return parameters of the policy" do
79
+ proc_called = lambda do |params|
80
+ params.should_not be_nil
81
+ params.should be_kind_of(Hash)
82
+ params[:author_policy?].should be_true
83
+ end
84
+ Beatle::JOHN.can?(:sing, Song::ALL_YOU_NEED_IS_LOVE, &proc_called)
85
+ end
86
+
87
+ end
88
+
89
+ describe '#satisfies?' do
90
+
91
+ it "should work with the symbol representation of the policy" do
92
+ Beatle::PAUL.satisfies?(:colaborating_with_john_policy, Song::TAXMAN).should be_false
93
+ end
94
+
95
+ it "should check only the specified policy" do
96
+ Beatle::PAUL.satisfies?(:colaborating_with_john_policy, Song::TAXMAN).should be_false
97
+ end
98
+
99
+ it "should raise a Walruz::ActionNotFound error if the policy is not found" do
100
+ lambda do
101
+ Beatle::GEORGE.satisfies?(:unknown_policy, Song::TAXMAN)
102
+ end.should raise_error(Walruz::ActionNotFound)
103
+ end
104
+
105
+ it "should execute the block if the condition is true" do
106
+ proc_called = Proc.new { raise "Is being called" }
107
+ lambda do
108
+ Beatle::GEORGE.satisfies?(:colaborating_with_john_policy, Song::TAXMAN, &proc_called)
109
+ end.should raise_error
110
+ end
111
+
112
+ it "should execute the block that receives a hash of return parameters of the policy" do
113
+ proc_called = lambda do |params|
114
+ params.should_not be_nil
115
+ params.should be_kind_of(Hash)
116
+ params[:author_in_colaboration_policy?].should be_true
117
+ end
118
+ Beatle::GEORGE.satisfies?(:colaborating_with_john_policy, Song::TAXMAN, &proc_called)
119
+ end
120
+
121
+ end
122
+
123
+ end
@@ -0,0 +1,62 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Walruz::Policy do
4
+
5
+ it "should provide the with_actor utility" do
6
+ AuthorPolicy.should respond_to(:with_actor)
7
+ end
8
+
9
+ it "should generate an indicator that the policy was executed after authorization queries" do
10
+ policy = Beatle::PAUL.can!(:sing, Song::YESTERDAY)
11
+ policy[:author_policy?].should be_true
12
+ end
13
+
14
+ it "should have a default label" do
15
+ AuthorPolicy.policy_label.should == :author_policy
16
+ end
17
+
18
+ it "should prioritize a label that is setted over the default one" do
19
+ AuthorPolicy.set_policy_label :is_author
20
+ AuthorPolicy.policy_label.should == :is_author
21
+ AuthorPolicy.set_policy_label(nil)
22
+ end
23
+
24
+ it "should raise an Walruz::ActionNotFound exception when the action is not specified, and there is no default one" do
25
+ lambda do
26
+ Beatle::RINGO.can!(:sing_drunk, Song::TAXMAN)
27
+ end.should raise_error(Walruz::ActionNotFound)
28
+ end
29
+
30
+ describe "when using the #with_actor method" do
31
+
32
+ before(:each) do
33
+ @songs = [Song::A_DAY_IN_LIFE, Song::YELLOW_SUBMARINE, Song::TAXMAN,
34
+ Song::YESTERDAY, Song::ALL_YOU_NEED_IS_LOVE, Song::BLUE_JAY_WAY]
35
+ end
36
+
37
+ it "should work properly" do
38
+ george_authorship_songs = @songs.select(&AuthorPolicy.with_actor(Beatle::GEORGE))
39
+ george_authorship_songs.should have(1).song
40
+ george_authorship_songs.should == [Song::BLUE_JAY_WAY]
41
+
42
+
43
+ john_and_paul_songs = @songs.select(&AuthorInColaborationPolicy.with_actor(Beatle::JOHN))
44
+ john_and_paul_songs.should have(3).songs
45
+ john_and_paul_songs.should == [Song::A_DAY_IN_LIFE, Song::YELLOW_SUBMARINE, Song::TAXMAN]
46
+ end
47
+
48
+ end
49
+
50
+ describe "when using dependence_on macro" do
51
+
52
+ it "should work properly" do
53
+ lambda do
54
+ Beatle::PAUL.sing_with_john(Song::YESTERDAY)
55
+ end.should raise_error(Walruz::NotAuthorized)
56
+
57
+ Beatle::PAUL.sing_with_john(Song::A_DAY_IN_LIFE).should == "Ok John, Let's Play 'A Day In Life'"
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Walruz::Subject do
4
+
5
+ it "should add a can_be? method" do
6
+ Song::A_DAY_IN_LIFE.should respond_to(:can_be?)
7
+ end
8
+
9
+ it "should add a class method called check_authorizations" do
10
+ Song.should respond_to(:check_authorizations)
11
+ end
12
+
13
+
14
+ describe "when executing validations on an invalid subject" do
15
+
16
+ it "should raise an Walruz::AuthorizationActionsNotDefined error" do
17
+ lambda do
18
+ Beatle::JOHN.can_be?(:talk_with, Beatle::PAUL)
19
+ end.should raise_error(Walruz::AuthorizationActionsNotDefined)
20
+ end
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Walruz::Utils do
4
+
5
+ def check_actor_can_on_subject(label, actor, subject)
6
+ lambda do
7
+ actor.can!(label, subject)
8
+ end.should_not raise_error(Walruz::NotAuthorized)
9
+ end
10
+
11
+ def check_actor_can_not_on_subject(label, actor, subject)
12
+ lambda do
13
+ actor.can!(label, subject)
14
+ end.should raise_error(Walruz::NotAuthorized)
15
+ end
16
+
17
+ describe "when using combinators `orP`, `andP` or `notP`" do
18
+
19
+ it "should work properly" do
20
+ check_actor_can_not_on_subject(:sell, Beatle::JOHN, Song::A_DAY_IN_LIFE)
21
+ check_actor_can_on_subject(:sell, Beatle::JOHN, Song::ALL_YOU_NEED_IS_LOVE)
22
+ end
23
+
24
+ end
25
+
26
+ describe "when using andP" do
27
+
28
+ it "should return as policy keyword, the name of the original policies keywords concatenated with `_and_`" do
29
+ Beatle::JOHN.can?(:sell, Song::ALL_YOU_NEED_IS_LOVE) do |policy_params|
30
+ policy_params[:"author_policy_and_not(author_in_colaboration_policy)?"].should be_true
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ describe "when using notP" do
37
+
38
+ it "should return as policy keyword, the name of the original policy keyword with a `not()` around" do
39
+ Beatle::JOHN.can?(:sell, Song::ALL_YOU_NEED_IS_LOVE) do |policy_params|
40
+ policy_params[:"not(author_in_colaboration_policy)?"].should be_true
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,20 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Walruz do
4
+
5
+ it "should have a policies method" do
6
+ Walruz.should respond_to(:policies)
7
+ end
8
+
9
+ describe '#policies' do
10
+
11
+ it "should return all the policies created that have a label" do
12
+ Walruz.policies.should_not be_nil
13
+ Walruz.policies[:author_policy].should be_nil
14
+ Walruz.policies[:author_in_colaboration_policy].should == AuthorInColaborationPolicy
15
+ Walruz.policies[:colaborating_with_john_policy].should == ColaboratingWithJohnPolicy
16
+ end
17
+
18
+ end
19
+
20
+ end