walruz 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|