walruz 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +56 -53
- data/Rakefile +1 -0
- data/VERSION.yml +1 -1
- data/lib/walruz/actor.rb +79 -51
- data/lib/walruz/core_ext/array.rb +79 -0
- data/lib/walruz/policy.rb +48 -53
- data/lib/walruz/subject.rb +37 -17
- data/lib/walruz/utils.rb +73 -19
- data/lib/walruz.rb +21 -1
- data/spec/scenario.rb +26 -17
- data/spec/walruz/actor_spec.rb +26 -22
- data/spec/walruz/core_ext/array_spec.rb +84 -0
- data/spec/walruz/utils_spec.rb +4 -6
- data/spec/walruz/walruz_spec.rb +15 -1
- metadata +6 -3
data/lib/walruz/policy.rb
CHANGED
@@ -1,42 +1,42 @@
|
|
1
1
|
module Walruz
|
2
2
|
|
3
3
|
#
|
4
|
-
# One of the cores of the framework,
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# an actor is actually authorized to manage the subject.
|
4
|
+
# One of the cores of the framework, its purpose is to encapsulate an authorization logic
|
5
|
+
# with a given actor and subject. It's main method <tt>authorized?(actor, subject)</tt>
|
6
|
+
# verifies that an actor is authorized to manage the subject.
|
8
7
|
#
|
9
8
|
class Policy
|
10
9
|
extend Walruz::Utils
|
11
10
|
|
12
|
-
|
13
|
-
# :nodoc:
|
14
|
-
def self.inherited(child)
|
11
|
+
|
12
|
+
def self.inherited(child) # :nodoc:
|
15
13
|
@policies ||= {}
|
16
14
|
unless child.policy_label.nil?
|
17
15
|
@policies[child.policy_label] = child
|
18
16
|
end
|
19
17
|
end
|
20
18
|
|
21
|
-
|
22
|
-
#
|
23
|
-
#
|
19
|
+
|
20
|
+
# @see Walruz.policies
|
24
21
|
def self.policies
|
25
22
|
@policies || {}
|
26
23
|
end
|
27
24
|
|
28
|
-
#
|
29
|
-
#
|
25
|
+
#
|
26
|
+
# Creates a new policy class based on an existing one, you may use this method
|
27
|
+
# when you want to reuse a Policy class for a subject's association.
|
28
|
+
#
|
29
|
+
# @param [Symbol] Name of the association that will be the subject of the policy.
|
30
|
+
# @return [Walruz::Policy] New generated policy that will pass the association as the subject of the original <em>policy</em>.
|
30
31
|
#
|
31
|
-
# See the "Policy Combinators" section on the README for more info
|
32
|
+
# @see http://github.com/noomii/walruz See the "Policy Combinators" section on the README for more info and examples.
|
32
33
|
#
|
33
34
|
def self.for_subject(key, &block)
|
34
|
-
|
35
|
-
clazz = Class.new(Walruz::Policy) do
|
35
|
+
|
36
|
+
clazz = Class.new(Walruz::Policy) do # :nodoc:
|
36
37
|
extend Walruz::Utils::PolicyCompositionHelper
|
37
38
|
|
38
|
-
# :nodoc:
|
39
|
-
def authorized?(actor, subject)
|
39
|
+
def authorized?(actor, subject) # :nodoc:
|
40
40
|
params = self.class.params
|
41
41
|
new_subject = subject.send(params[:key])
|
42
42
|
result = self.class.policy.new.safe_authorized?(actor, new_subject)
|
@@ -51,16 +51,17 @@ module Walruz
|
|
51
51
|
end
|
52
52
|
|
53
53
|
#
|
54
|
-
# Returns a Proc with a curried actor, making it easier
|
55
|
-
#
|
56
|
-
# Params:
|
57
|
-
# - actor: The actor who checks if it is authorized
|
58
|
-
#
|
59
|
-
# Returns: (subject -> [Bool, Hash])
|
54
|
+
# Returns a Proc with a curried actor, making it easier to perform validations of a policy
|
55
|
+
# in an Array of subjects.
|
60
56
|
#
|
61
|
-
#
|
62
|
-
#
|
57
|
+
# @param [Walruz::Actor] The actor who checks if he is authorized.
|
58
|
+
# @return [Proc] A proc that receives as a parameter subject and returns what the <tt>authorized?</tt>
|
59
|
+
# method returns.
|
60
|
+
#
|
61
|
+
# @example
|
62
|
+
# subjects.select(&PolicyXYZ.with_actor(some_user))
|
63
63
|
#
|
64
|
+
# @see Walruz::CoreExt::Array#only_authorized_for
|
64
65
|
def self.with_actor(actor)
|
65
66
|
policy_instance = self.new
|
66
67
|
lambda do |subject|
|
@@ -71,13 +72,18 @@ module Walruz
|
|
71
72
|
#
|
72
73
|
# Stablish other Policy dependencies, so that they are executed
|
73
74
|
# before the current one, giving chances to receive the previous
|
74
|
-
# policies return parameters
|
75
|
+
# policies return parameters.
|
76
|
+
#
|
77
|
+
# @param [Array<Walruz::Policies>] Policies in wich this policy depends on.
|
78
|
+
# @return self
|
75
79
|
#
|
76
|
-
#
|
80
|
+
# @example
|
77
81
|
# class FriendEditProfilePolicy
|
78
82
|
# depends_on FriendPolicy
|
79
83
|
#
|
80
84
|
# def authorized?(actor, subject)
|
85
|
+
# # The FriendPolicy returns a hash with a key of :friend_relationship
|
86
|
+
# # this will be available via the params method.
|
81
87
|
# params[:friend_relationship].can_edit? # for friend metadata
|
82
88
|
# end
|
83
89
|
#
|
@@ -88,23 +94,17 @@ module Walruz
|
|
88
94
|
end
|
89
95
|
|
90
96
|
# Utility for depends_on macro
|
91
|
-
#
|
92
|
-
# :nodoc:
|
93
|
-
def self.policy_dependencies=(dependencies)
|
97
|
+
def self.policy_dependencies=(dependencies) # :nodoc:
|
94
98
|
@_policy_dependencies = dependencies
|
95
99
|
end
|
96
100
|
|
97
101
|
# Utility for depends_on macro
|
98
|
-
#
|
99
|
-
# :nodoc:
|
100
|
-
def self.policy_dependencies
|
102
|
+
def self.policy_dependencies # :nodoc:
|
101
103
|
@_policy_dependencies
|
102
104
|
end
|
103
105
|
|
104
106
|
# Utility for depends_on macro
|
105
|
-
#
|
106
|
-
# :nodoc:
|
107
|
-
def self.return_policy
|
107
|
+
def self.return_policy # :nodoc:
|
108
108
|
if policy_dependencies.nil?
|
109
109
|
self
|
110
110
|
else
|
@@ -112,10 +112,8 @@ module Walruz
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
-
# Utility method (
|
116
|
-
#
|
117
|
-
# :nodoc:
|
118
|
-
def self.underscore(camel_cased_word)
|
115
|
+
# Utility method (from ActiveSupport)
|
116
|
+
def self.underscore(camel_cased_word) # :nodoc:
|
119
117
|
if camel_cased_word.empty?
|
120
118
|
camel_cased_word
|
121
119
|
else
|
@@ -130,11 +128,12 @@ module Walruz
|
|
130
128
|
|
131
129
|
#
|
132
130
|
# Verifies if the actor is authorized to interact with the subject
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
131
|
+
# @param [Walruz::Actor] The object who checks if it is authorized
|
132
|
+
# @param [Walruz::Subject] The object that is going to be accesed
|
133
|
+
# @return It may return a Boolean, or an Array with the first position being a boolean and the second
|
134
|
+
# being a Hash of parameters returned from the policy.
|
135
|
+
#
|
136
136
|
#
|
137
|
-
# Returns: [Bool, Hash]
|
138
137
|
#
|
139
138
|
def authorized?(actor, subject)
|
140
139
|
raise NotImplementedError.new("You need to implement policy")
|
@@ -144,9 +143,8 @@ module Walruz
|
|
144
143
|
# Returns the identifier of the Policy that will be setted on the
|
145
144
|
# policy params hash once the authorization is executed.
|
146
145
|
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
# was setted, in that case the policy label will be used) with an '?' appended
|
146
|
+
# @return [Symbol] By default it will return a symbol with the name of the Policy class in underscore (unless the policy label
|
147
|
+
# was setted, in that case the policy label will be used) with an '?' appended.
|
150
148
|
#
|
151
149
|
def self.policy_keyword
|
152
150
|
if self.policy_label.nil?
|
@@ -171,21 +169,18 @@ module Walruz
|
|
171
169
|
# - label: Symbol that represents the policy
|
172
170
|
#
|
173
171
|
def self.set_policy_label(label)
|
172
|
+
Walruz.policies[label] = Walruz.policies.delete(self.policy_label)
|
174
173
|
@policy_label = label
|
175
174
|
end
|
176
175
|
|
177
|
-
#
|
178
|
-
# :nodoc:
|
179
|
-
def safe_authorized?(actor, subject)
|
176
|
+
def safe_authorized?(actor, subject) # :nodoc:
|
180
177
|
result = Array(authorized?(actor, subject))
|
181
178
|
result[1] ||= {}
|
182
179
|
result[1][self.class.policy_keyword] = result[0] unless self.class.policy_keyword.nil?
|
183
180
|
result
|
184
181
|
end
|
185
182
|
|
186
|
-
#
|
187
|
-
# :nodoc:
|
188
|
-
def set_params(params)
|
183
|
+
def set_params(params) # :nodoc:
|
189
184
|
@params = params
|
190
185
|
self
|
191
186
|
end
|
data/lib/walruz/subject.rb
CHANGED
@@ -1,7 +1,30 @@
|
|
1
1
|
module Walruz
|
2
|
+
|
3
|
+
#
|
4
|
+
# This module provides the methods that enable a <em>subject</em> to register
|
5
|
+
# the diferent actions that can be performed to it, and associates the policies
|
6
|
+
# that apply to each of these actions.
|
7
|
+
#
|
8
|
+
# == Associating policies with actions on the <em>subject</em>.
|
9
|
+
#
|
10
|
+
# To associate policies and actions related to a <em>subject</em>, we use the <tt>check_authorizations</tt>
|
11
|
+
# method, this will receive a Hash, where the keys are the name of the actions, and the values are the policies
|
12
|
+
# associated to this actions.
|
13
|
+
#
|
14
|
+
# === Example:
|
15
|
+
# class Profile < ActiveRecord::Base
|
16
|
+
# include Walruz::Subject
|
17
|
+
# belongs_to :user
|
18
|
+
# check_authorizations :read => ProfileReadPolicy,
|
19
|
+
# :update => ProfileUpdatePolicy
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# Once the actions are registered on the <em>subject</em>, you can check if an <em>actor</em> can perform
|
23
|
+
# an action on it, using the <tt>Walruz::Actor</tt> methods
|
24
|
+
#
|
2
25
|
module Subject
|
3
26
|
|
4
|
-
def self.included(base)
|
27
|
+
def self.included(base) # :nodoc:
|
5
28
|
base.class_eval do
|
6
29
|
|
7
30
|
def self._walruz_policies=(policies)
|
@@ -16,9 +39,7 @@ module Walruz
|
|
16
39
|
end
|
17
40
|
end
|
18
41
|
|
19
|
-
#
|
20
|
-
# :nodoc:
|
21
|
-
def can_be?(action, actor)
|
42
|
+
def can_be?(action, actor) # :nodoc:
|
22
43
|
check_authorization_actions_are_setted(action)
|
23
44
|
action = if self.class._walruz_policies.key?(:default)
|
24
45
|
self.class._walruz_policies.key?(action) ? action : :default
|
@@ -39,9 +60,7 @@ module Walruz
|
|
39
60
|
result
|
40
61
|
end
|
41
62
|
|
42
|
-
#
|
43
|
-
# :nodoc:
|
44
|
-
def check_authorization_actions_are_setted(action)
|
63
|
+
def check_authorization_actions_are_setted(action) # :nodoc:
|
45
64
|
if self.class._walruz_policies.nil?
|
46
65
|
message =<<BEGIN
|
47
66
|
You need to invoke `check_authorizations :#{action} => Policies::SomePolicy` on the #{self.class.name} class
|
@@ -55,10 +74,16 @@ BEGIN
|
|
55
74
|
#
|
56
75
|
# Stablishes the actions that can be made with a subject. You may
|
57
76
|
# specify as many actions as you like, and also you may have a default
|
58
|
-
# policy, that will get
|
59
|
-
# You just have to pass the action :default, or
|
77
|
+
# policy, that will get executed if a specified flag doesn't exist.
|
78
|
+
# You just have to pass the action :default, or the policy class only.
|
60
79
|
#
|
61
|
-
#
|
80
|
+
# Once you stablish the authorizations policies on a subject, you can
|
81
|
+
# check if an actor is able to interact with it via the Walruz::Actor methods
|
82
|
+
#
|
83
|
+
# @param [Hash] Set of actions with associated policies
|
84
|
+
# @return self
|
85
|
+
#
|
86
|
+
# @example
|
62
87
|
# # Without :default key
|
63
88
|
# class UserProfile
|
64
89
|
# check_authorizations :read => Policies::FriendPolicy,
|
@@ -78,13 +103,8 @@ BEGIN
|
|
78
103
|
# check_authorizations Policies::OwnerPolicy
|
79
104
|
# end
|
80
105
|
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
# Example: current_user.can?(:read, profile)
|
85
|
-
#
|
86
|
-
# It's recommended (but not mandatory) that a policy specified to the action
|
87
|
-
# is inherting from Walruz::Policy
|
106
|
+
# @example Invoking the actions from the actor
|
107
|
+
# current_user.can?(:read, profile)
|
88
108
|
#
|
89
109
|
def check_authorizations(policy_map)
|
90
110
|
case policy_map
|
data/lib/walruz/utils.rb
CHANGED
@@ -1,9 +1,45 @@
|
|
1
1
|
module Walruz
|
2
|
+
#
|
3
|
+
# This module provides pretty handy methods to do compositions of basic policies to create
|
4
|
+
# more complex ones.
|
5
|
+
#
|
6
|
+
# === Using a policies file to manage complex policies
|
7
|
+
#
|
8
|
+
# It's always a good idea to keep the policy composition in one place, you may place a file in your
|
9
|
+
# project where you manage all the authorization policies, and then you use them on your models.
|
10
|
+
#
|
11
|
+
# Say for example you have a <tt>lib/policies.rb</tt> in your project where you manage the composition of policies,
|
12
|
+
# and a <tt>lib/policies</tt> folder where you create your custom policies.
|
13
|
+
#
|
14
|
+
# The <tt>lib/policies.rb</tt> file could be something like this:
|
15
|
+
#
|
16
|
+
# module Policies
|
17
|
+
# include Walruz::Utils
|
18
|
+
#
|
19
|
+
# # Requiring basic Walruz::Policy classes
|
20
|
+
# BASE = File.join(File.dirname(__FILE__), "policies") unless defined?(BASE)
|
21
|
+
# require File.join(BASE, "actor_is_admin")
|
22
|
+
# require File.join(BASE, "user_is_owner")
|
23
|
+
# require File.join(BASE, "user_is_friend")
|
24
|
+
#
|
25
|
+
# #####
|
26
|
+
# # User Policies
|
27
|
+
# #
|
28
|
+
# UserCreatePolicy = ActorIsAdmin
|
29
|
+
# UserReadPolicy = any(UserIsOwner, UserIsFriend, ActorIsAdmin)
|
30
|
+
# UserUpdatePolicy = any(UserIsOwner, ActorIsAdmin)
|
31
|
+
# UserDestroyPolicy = ActorIsAdmin
|
32
|
+
#
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# Using a policies file on your project, keeps all your authorization logic just in one place
|
36
|
+
# that way, when you change the authorizations you just have to go to one place only.
|
37
|
+
#
|
2
38
|
module Utils
|
3
39
|
|
4
|
-
module PolicyCompositionHelper
|
40
|
+
module PolicyCompositionHelper # :nodoc: all
|
5
41
|
|
6
|
-
|
42
|
+
#-- NOTE: Not using cattr_accessor to avoid dependencies with ActiveSupport
|
7
43
|
|
8
44
|
def policies=(policies)
|
9
45
|
@policies = policies
|
@@ -32,13 +68,21 @@ module Walruz
|
|
32
68
|
|
33
69
|
end
|
34
70
|
|
71
|
+
#
|
72
|
+
# Generates a new policy that merges together different policies by an <em>OR</em> association.
|
73
|
+
# As soon as one of the policies succeed, the parameters of that policy will be returned.
|
74
|
+
#
|
75
|
+
# @param [Array<Walruz::Policy>] A set of policies that will be merged by an <em>OR</em> association.
|
76
|
+
# @return [Walruz::Policy] A new policy class that will execute each policy until one of them succeeds.
|
77
|
+
#
|
78
|
+
# @example
|
79
|
+
# UserReadPolicy = any(UserIsOwner, UserIsAdmin)
|
80
|
+
#
|
35
81
|
def any(*policies)
|
36
|
-
# :nodoc:
|
37
|
-
clazz = Class.new(Walruz::Policy) do
|
82
|
+
clazz = Class.new(Walruz::Policy) do # :nodoc:
|
38
83
|
extend PolicyCompositionHelper
|
39
84
|
|
40
|
-
# :nodoc:
|
41
|
-
def authorized?(actor, subject)
|
85
|
+
def authorized?(actor, subject) # :nodoc:
|
42
86
|
result = nil
|
43
87
|
self.class.policies.detect do |policy|
|
44
88
|
result = policy.new.set_params(params).safe_authorized?(actor, subject)
|
@@ -52,13 +96,20 @@ module Walruz
|
|
52
96
|
clazz
|
53
97
|
end
|
54
98
|
|
99
|
+
#
|
100
|
+
# Generates a new policy that merges together different policies by an <em>AND</em> association.
|
101
|
+
# This will execute every <em>policy</em> on the list, if all of them return true then the policy will
|
102
|
+
# succeed. This process will merge the parameters of each policy, so you may be able to use the parameters
|
103
|
+
# of previous policies, and at the end it will return all the parameters from every policy.
|
104
|
+
#
|
105
|
+
# @param [Array<Walruz::Policy>] A set of policies that will be merged by an <em>AND</em> association.
|
106
|
+
# @return [Walruz::Policy] A new policy class that will check true for each policy.
|
107
|
+
#
|
55
108
|
def all(*policies)
|
56
|
-
# :nodoc:
|
57
|
-
clazz = Class.new(Walruz::Policy) do
|
109
|
+
clazz = Class.new(Walruz::Policy) do # :nodoc:
|
58
110
|
extend PolicyCompositionHelper
|
59
111
|
|
60
|
-
# :nodoc:
|
61
|
-
def authorized?(actor, subject)
|
112
|
+
def authorized?(actor, subject) # :nodoc:
|
62
113
|
acum = [true, self.params || {}]
|
63
114
|
self.class.policies.each do |policy|
|
64
115
|
break unless acum[0]
|
@@ -69,8 +120,7 @@ module Walruz
|
|
69
120
|
acum[0] ? acum : acum[0]
|
70
121
|
end
|
71
122
|
|
72
|
-
# :nodoc:
|
73
|
-
def self.policy_keyword
|
123
|
+
def self.policy_keyword # :nodoc:
|
74
124
|
(self.policies.map { |p| p.policy_keyword.to_s[0..-2] }.join('_and_') + "?").to_sym
|
75
125
|
end
|
76
126
|
|
@@ -79,20 +129,24 @@ module Walruz
|
|
79
129
|
clazz
|
80
130
|
end
|
81
131
|
|
132
|
+
#
|
133
|
+
# Generates a new policy that negates the result of the given policy.
|
134
|
+
# @param [Walruz::Policy] The policy which result is going to be negated.
|
135
|
+
# @param [Walruz::Policy] A new policy that will negate the result of the given policy.
|
136
|
+
#
|
82
137
|
def negate(policy)
|
83
|
-
# :nodoc:
|
84
|
-
clazz = Class.new(Walruz::Policy) do
|
138
|
+
clazz = Class.new(Walruz::Policy) do # :nodoc:
|
85
139
|
extend PolicyCompositionHelper
|
86
140
|
|
87
141
|
# :nodoc:
|
88
142
|
def authorized?(actor, subject)
|
89
|
-
self.class.policy.set_params(params)
|
90
|
-
result =
|
91
|
-
|
143
|
+
result = self.class.policy.new.set_params(params).safe_authorized?(actor, subject)
|
144
|
+
result[0] = !result[0]
|
145
|
+
result
|
92
146
|
end
|
93
147
|
|
94
|
-
|
95
|
-
def self.policy_keyword
|
148
|
+
|
149
|
+
def self.policy_keyword # :nodoc:
|
96
150
|
keyword = self.policy.policy_keyword.to_s[0..-2]
|
97
151
|
:"not(#{keyword})?"
|
98
152
|
end
|
data/lib/walruz.rb
CHANGED
@@ -42,15 +42,33 @@ module Walruz
|
|
42
42
|
autoload :Policy, base_path + '/walruz/policy'
|
43
43
|
autoload :Utils, base_path + '/walruz/utils'
|
44
44
|
|
45
|
+
|
45
46
|
def self.setup
|
46
47
|
config = Config.new
|
47
48
|
yield config
|
48
49
|
end
|
49
50
|
|
51
|
+
# Holds all the policies declared on the system
|
52
|
+
# @return [Hash<Symbol, Walruz::Policy>] A hash of policies, each identified by it's policy label
|
53
|
+
# @todo Make this thread-safe
|
50
54
|
def self.policies
|
51
55
|
Walruz::Policy.policies
|
52
56
|
end
|
53
57
|
|
58
|
+
# Returns a Walruz::Policy Class represented by the specified label
|
59
|
+
#
|
60
|
+
# @param [Symbol] policy_label The label that identifies a policy
|
61
|
+
# @return [Walruz::Policy] A Policy class.
|
62
|
+
# @raise [Walruz::ActionNotFound] if the policy label is not recognized.
|
63
|
+
# @example Fetching a policy with label :actor_is_admin
|
64
|
+
# Walruz.fetch_policy(:actor_is_admin) # => ActorIsAdmin
|
65
|
+
#
|
66
|
+
def self.fetch_policy(policy_label)
|
67
|
+
policy_clz = Walruz.policies[policy_label]
|
68
|
+
raise ActionNotFound.new(:policy_label, :label => policy_label) if policy_clz.nil?
|
69
|
+
policy_clz
|
70
|
+
end
|
71
|
+
|
54
72
|
class Config
|
55
73
|
|
56
74
|
def actors=(actors)
|
@@ -67,5 +85,7 @@ module Walruz
|
|
67
85
|
|
68
86
|
end
|
69
87
|
|
88
|
+
end
|
70
89
|
|
71
|
-
|
90
|
+
require File.dirname(__FILE__) + '/walruz/core_ext/array'
|
91
|
+
Array.send(:include, Walruz::CoreExt::Array)
|
data/spec/scenario.rb
CHANGED
@@ -30,11 +30,12 @@ class Beatle
|
|
30
30
|
"Ok John, Let's Play '%s'" % song.name
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
unless defined?(RINGO)
|
34
|
+
JOHN = self.new("John")
|
35
|
+
PAUL = self.new("Paul")
|
36
|
+
RINGO = self.new("Ringo")
|
37
|
+
GEORGE = self.new("George")
|
38
|
+
end
|
38
39
|
end
|
39
40
|
|
40
41
|
class Colaboration
|
@@ -50,9 +51,12 @@ class Colaboration
|
|
50
51
|
@songs = []
|
51
52
|
end
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
54
|
+
unless defined?(JOHN_PAUL)
|
55
|
+
JOHN_PAUL = self.new(Beatle::JOHN, Beatle::PAUL)
|
56
|
+
JOHN_PAUL_GEORGE = self.new(Beatle::JOHN, Beatle::PAUL, Beatle::GEORGE)
|
57
|
+
JOHN_GEORGE = self.new(Beatle::JOHN, Beatle::GEORGE)
|
58
|
+
end
|
59
|
+
|
56
60
|
end
|
57
61
|
|
58
62
|
class SubjectIsActorPolicy < Walruz::Policy
|
@@ -74,12 +78,14 @@ end
|
|
74
78
|
# end
|
75
79
|
#
|
76
80
|
# end
|
77
|
-
|
78
|
-
AuthorPolicy = SubjectIsActorPolicy.for_subject(:author) do |authorized, params, actor, subject|
|
79
|
-
|
81
|
+
unless defined?(AuthorPolicy)
|
82
|
+
AuthorPolicy = SubjectIsActorPolicy.for_subject(:author) do |authorized, params, actor, subject|
|
83
|
+
params.merge!(:owner => actor) if authorized
|
84
|
+
end
|
80
85
|
end
|
81
86
|
|
82
87
|
class AuthorInColaborationPolicy < Walruz::Policy
|
88
|
+
set_policy_label :in_colaboration
|
83
89
|
|
84
90
|
def authorized?(beatle, song)
|
85
91
|
return false unless song.colaboration
|
@@ -123,11 +129,14 @@ class Song
|
|
123
129
|
owner.songs << self
|
124
130
|
end
|
125
131
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
+
unless defined?(A_DAY_IN_LIFE)
|
133
|
+
A_DAY_IN_LIFE = self.new("A Day In Life", Colaboration::JOHN_PAUL)
|
134
|
+
YELLOW_SUBMARINE = self.new("Yellow Submarine", Colaboration::JOHN_PAUL)
|
135
|
+
TAXMAN = self.new("Taxman", Colaboration::JOHN_GEORGE)
|
136
|
+
YESTERDAY = self.new("Yesterday", Beatle::PAUL)
|
137
|
+
ALL_YOU_NEED_IS_LOVE = self.new("All You Need Is Love", Beatle::JOHN)
|
138
|
+
BLUE_JAY_WAY = self.new("Blue Jay Way", Beatle::GEORGE)
|
139
|
+
end
|
140
|
+
|
132
141
|
end
|
133
142
|
|
data/spec/walruz/actor_spec.rb
CHANGED
@@ -68,9 +68,9 @@ describe 'Walruz::Actor' do
|
|
68
68
|
describe '#can?' do
|
69
69
|
|
70
70
|
it "should be invoked only the first time and then return a cached solution" do
|
71
|
-
Song::
|
72
|
-
Beatle::JOHN.can?(:sing, Song::
|
73
|
-
Beatle::JOHN.can?(:sing, Song::
|
71
|
+
Song::YELLOW_SUBMARINE.should_receive(:can_be?).once.and_return([true, {}])
|
72
|
+
Beatle::JOHN.can?(:sing, Song::YELLOW_SUBMARINE, true)
|
73
|
+
Beatle::JOHN.can?(:sing, Song::YELLOW_SUBMARINE)
|
74
74
|
end
|
75
75
|
|
76
76
|
it "if a boolean third parameter is received it should not use the cached result" do
|
@@ -108,34 +108,38 @@ describe 'Walruz::Actor' do
|
|
108
108
|
|
109
109
|
describe '#satisfies?' do
|
110
110
|
|
111
|
-
it "should
|
112
|
-
|
111
|
+
it "should raise a Walruz::ActionNotFound error if the policy is not found" do
|
112
|
+
lambda do
|
113
|
+
Beatle::GEORGE.satisfies?(:unknown_policy, Song::TAXMAN)
|
114
|
+
end.should raise_error(Walruz::ActionNotFound)
|
113
115
|
end
|
114
116
|
|
115
|
-
it "should
|
117
|
+
it "should return false if the actor and the subject dont satisfy the given policy" do
|
116
118
|
Beatle::PAUL.satisfies?(:colaborating_with_john_policy, Song::TAXMAN).should be_false
|
117
119
|
end
|
118
120
|
|
119
|
-
it "should
|
120
|
-
|
121
|
-
Beatle::GEORGE.satisfies?(:unknown_policy, Song::TAXMAN)
|
122
|
-
end.should raise_error(Walruz::ActionNotFound)
|
121
|
+
it "should return true if the actor and the subject satisfy the given policy" do
|
122
|
+
Beatle::GEORGE.satisfies(:colaborating_with_john_policy, Song::TAXMAN).should be_true
|
123
123
|
end
|
124
124
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "#satisfies" do
|
128
|
+
|
129
|
+
it "should return nil if the actor and the subject do not satisfy the given policy" do
|
130
|
+
Beatle::PAUL.satisfies(:colaborating_with_john_policy, Song::TAXMAN).should be_nil
|
130
131
|
end
|
131
132
|
|
132
|
-
it "should
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
133
|
+
it "should return the parameters from the policy if the actor and the subject satisfy the policy" do
|
134
|
+
policy_params = Beatle::GEORGE.satisfies(:colaborating_with_john_policy, Song::TAXMAN)
|
135
|
+
policy_params.should_not be_nil
|
136
|
+
policy_params[:in_colaboration?].should be_true
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should raise a Walruz::ActionNotFound error if the policy is not found" do
|
140
|
+
lambda do
|
141
|
+
Beatle::GEORGE.satisfies(:unknown_policy, Song::TAXMAN)
|
142
|
+
end.should raise_error(Walruz::ActionNotFound)
|
139
143
|
end
|
140
144
|
|
141
145
|
end
|