permit 0.9.0 → 1.0.0
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/VERSION.yml +4 -4
- data/lib/models/association.rb +48 -31
- data/lib/models/person.rb +13 -7
- data/lib/permit.rb +34 -23
- data/lib/permit/controller.rb +68 -17
- data/lib/permit/permit_rule.rb +48 -27
- data/lib/permit/permit_rules.rb +23 -2
- data/lib/permit/support.rb +34 -13
- data/permit.gemspec +3 -3
- data/spec/models/person_spec.rb +109 -31
- data/spec/models/role_spec.rb +7 -0
- data/spec/permit/controller_spec.rb +88 -48
- data/spec/permit/permit_rule_spec.rb +417 -104
- metadata +12 -5
data/VERSION.yml
CHANGED
data/lib/models/association.rb
CHANGED
@@ -4,17 +4,19 @@ module Permit
|
|
4
4
|
# associations to help with querying for common cases. Some of these methods
|
5
5
|
# do not show up in the documentation because they are dynamically created
|
6
6
|
# with class_eval so that they can be explicit to the models you use for the
|
7
|
-
# Person and Role models.
|
7
|
+
# Person and Role models. See the documentation for {#method_missing} for
|
8
|
+
# additionally created methods.
|
8
9
|
module AssociationExtensions
|
9
10
|
include Permit::Support
|
10
11
|
|
11
|
-
# Finds all authorizations for the given
|
12
|
+
# Finds all authorizations for the given resources
|
12
13
|
#
|
13
|
-
# @param [permit_authorizable, nil, :any
|
14
|
-
# authorizations for. :any may be given
|
14
|
+
# @param [permit_authorizable, nil, :any, <permit_authorizable, nil>]
|
15
|
+
# resource the resources to find authorizations for. :any may be given
|
16
|
+
# to find matches for any resource.
|
15
17
|
# @return [<permit_authorization>] the authorizations found for the resource.
|
16
|
-
def for(
|
17
|
-
conditions = authorization_conditions(nil,
|
18
|
+
def for(resources)
|
19
|
+
conditions = authorization_conditions(nil, resources)
|
18
20
|
find(:all, :conditions => conditions)
|
19
21
|
end
|
20
22
|
|
@@ -35,8 +37,8 @@ module Permit
|
|
35
37
|
# @param [permit_role, String, Symbol, <permit_role, String, Symbol>]
|
36
38
|
# roles the roles to find authorizations for.
|
37
39
|
# @return [<permit_authorization>] the authorizations found for the resource and role(s)
|
38
|
-
def
|
39
|
-
conditions = authorization_conditions(roles,
|
40
|
+
def for_resources_as(resources, roles)
|
41
|
+
conditions = authorization_conditions(roles, resources)
|
40
42
|
find(:all, :conditions => conditions)
|
41
43
|
end
|
42
44
|
|
@@ -50,38 +52,53 @@ module Permit
|
|
50
52
|
as(roles).collect(&:resource).uniq
|
51
53
|
end
|
52
54
|
|
55
|
+
# Defines three methods used for getting your subject models for a
|
56
|
+
# resource, or as various roles, as well as role models for a given
|
57
|
+
# resource.
|
58
|
+
#
|
59
|
+
# @overload people_for(resources)
|
60
|
+
# Finds all of the subjects that have authorizations for the given
|
61
|
+
# resources. Where "people" is the plural name of your subject model.
|
62
|
+
#
|
63
|
+
# @param [permit_authorizable, nil, :any, <permit_authorizable, nil>]
|
64
|
+
# resource the resources to find authorizations for. :any may be given
|
65
|
+
# to find matches for any resource.
|
66
|
+
# @return [<permit_person>] a unique list of the people with
|
67
|
+
# authorizations for the resource.
|
68
|
+
#
|
69
|
+
# @overload people_as(roles)
|
70
|
+
# Finds all of the subjects that have authorizations for the given
|
71
|
+
# role(s). Where "people" is the plural name of your subject model.
|
72
|
+
#
|
73
|
+
# @param [permit_role, String, Symbol, <permit_role, String, Symbol>]
|
74
|
+
# roles the roles to find authorizations for.
|
75
|
+
# @return [<permit_person>] a unique list of the people with
|
76
|
+
# authorizations for the role(s).
|
77
|
+
#
|
78
|
+
# @overload roles_for(resources)
|
79
|
+
# Finds all of the roles authorized for the given resources. Where
|
80
|
+
# "roles" is the plural name of your role model.
|
81
|
+
#
|
82
|
+
# @param [permit_authorizable, nil, :any, <permit_authorizable, nil>]
|
83
|
+
# resource the resources to find authorizations for. :any may be given
|
84
|
+
# to find matches for any resource.
|
85
|
+
# @return [<permit_role>] a unique list of roles authorized for the
|
86
|
+
# resource.
|
87
|
+
def method_missing(*args, &block); super; end
|
88
|
+
|
53
89
|
def self.extended(klass)
|
54
90
|
class_eval <<-END
|
55
|
-
#
|
56
|
-
|
57
|
-
# @param [permit_authorizable, nil, :any] resource the resource to find
|
58
|
-
# authorizations for. :any may be given to find matches for any resource.
|
59
|
-
# @return [<permit_person>] a unique list of the people with
|
60
|
-
# authorizations for the resource.
|
61
|
-
def #{Permit::Config.person_class.plural_class_symbol.to_s}_for(resource)
|
62
|
-
self.for(resource).collect(&:#{Permit::Config.person_class.class_symbol.to_s}).uniq
|
91
|
+
def #{Permit::Config.person_class.plural_class_symbol.to_s}_for(resources)
|
92
|
+
self.for(resources).collect(&:#{Permit::Config.person_class.class_symbol.to_s}).uniq
|
63
93
|
end
|
64
94
|
|
65
|
-
# Finds all of the people that have authorizations for the given role(s).
|
66
|
-
#
|
67
|
-
# @param [permit_role, String, Symbol, <permit_role, String, Symbol>]
|
68
|
-
# roles the roles to find authorizations for.
|
69
|
-
# @return [<permit_person>] a unique list of the people with
|
70
|
-
# authorizations for the role(s).
|
71
95
|
def #{Permit::Config.person_class.plural_class_symbol.to_s}_as(roles)
|
72
96
|
as(roles).collect(&:#{Permit::Config.person_class.class_symbol.to_s}).uniq
|
73
97
|
end
|
74
98
|
|
75
|
-
#
|
76
|
-
|
77
|
-
# @param [permit_authorizable, nil, :any] resource the resource to find
|
78
|
-
# authorizations for. :any may be given to find matches for any resource.
|
79
|
-
# @return [<permit_role>] a unique list of roles authorized for the
|
80
|
-
# resource.
|
81
|
-
def #{Permit::Config.role_class.plural_class_symbol.to_s}_for(resource)
|
82
|
-
self.for(resource).collect(&:#{Permit::Config.role_class.class_symbol.to_s}).uniq
|
99
|
+
def #{Permit::Config.role_class.plural_class_symbol.to_s}_for(resources)
|
100
|
+
self.for(resources).collect(&:#{Permit::Config.role_class.class_symbol.to_s}).uniq
|
83
101
|
end
|
84
|
-
|
85
102
|
END
|
86
103
|
end
|
87
104
|
end
|
data/lib/models/person.rb
CHANGED
@@ -24,15 +24,15 @@ module Permit
|
|
24
24
|
#
|
25
25
|
# @param [Role, String, Symbol, <Role, String, Symbol>] roles the roles
|
26
26
|
# to check for authorization on.
|
27
|
-
# @param [Authorizable, nil, :any]
|
27
|
+
# @param [Authorizable, nil, :any, <Authorizable, nil>] resources the resources to check for
|
28
28
|
# authorization on.
|
29
29
|
# @return [true, false] true if the person is authorized on any of the a
|
30
30
|
# roles, false otherwise.
|
31
|
-
def authorized?(roles,
|
31
|
+
def authorized?(roles, resources)
|
32
32
|
permit_arrayify(roles).each do |r|
|
33
33
|
role = get_role(r)
|
34
34
|
next unless role
|
35
|
-
conditions = authorization_conditions(role,
|
35
|
+
conditions = authorization_conditions(role, resources)
|
36
36
|
return true if permit_authorizations_proxy.exists?(conditions)
|
37
37
|
end
|
38
38
|
return false
|
@@ -43,16 +43,22 @@ module Permit
|
|
43
43
|
#
|
44
44
|
# @param [permit_role, String, Symbol, <permit_role, String, Symbol>]
|
45
45
|
# roles the roles to check for authorization on.
|
46
|
-
# @param [permit_authorizable, nil, :any]
|
46
|
+
# @param [permit_authorizable, nil, :any, <permit_authorizable, nil>] resources the resources to check for
|
47
47
|
# authorization on.
|
48
48
|
# @return [true, false] true if the person is authorized on all of the a
|
49
49
|
# roles, false otherwise.
|
50
|
-
def authorized_all?(roles,
|
50
|
+
def authorized_all?(roles, resources)
|
51
51
|
permit_arrayify(roles).each do |r|
|
52
52
|
role = get_role(r)
|
53
53
|
return false unless role
|
54
|
-
conditions = authorization_conditions(role,
|
55
|
-
|
54
|
+
conditions = authorization_conditions(role, resources)
|
55
|
+
if resources == :any
|
56
|
+
# No idea how many authz they should have. As long as they have
|
57
|
+
# something, that's good enough.
|
58
|
+
return false unless permit_authorizations_proxy.exists?(conditions)
|
59
|
+
else
|
60
|
+
return false unless permit_authorizations_proxy.count(:conditions => conditions) == permit_arrayify(resources).size
|
61
|
+
end
|
56
62
|
end
|
57
63
|
return true
|
58
64
|
end
|
data/lib/permit.rb
CHANGED
@@ -32,12 +32,12 @@ module Permit
|
|
32
32
|
# of all classes that are authorizable to roles by having defined
|
33
33
|
# +permit_authorizable+.
|
34
34
|
class Config
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@@controller_subject_method = nil
|
35
|
+
@authorization_class, @person_class, @role_class = nil, nil, nil
|
36
|
+
@authorizable_classes = []
|
37
|
+
@controller_subject_method = nil
|
39
38
|
|
40
|
-
|
39
|
+
|
40
|
+
@action_aliases = {
|
41
41
|
:create => [:new, :create],
|
42
42
|
:update => [:edit, :update],
|
43
43
|
:destroy => [:delete, :destroy],
|
@@ -48,44 +48,55 @@ module Permit
|
|
48
48
|
# Indicates the response returned by {PermitRules#permitted?} when no rules
|
49
49
|
# match. If set to +:allow+ then the person will be granted access. If set
|
50
50
|
# to anything else, they will be denied.
|
51
|
-
|
51
|
+
@default_access = :deny
|
52
52
|
|
53
53
|
class << self
|
54
|
+
# Actions that when given to {PermitRules#allow}, and {PermitRules#deny}
|
55
|
+
# will be expanded into the actions given in the value array.
|
56
|
+
#
|
57
|
+
# Defaults to:
|
58
|
+
# {
|
59
|
+
# :create => [:new, :create],
|
60
|
+
# :update => [:edit, :update],
|
61
|
+
# :destroy => [:delete, :destroy],
|
62
|
+
# :read => [:index, :show],
|
63
|
+
# :write => [:new, :create, :edit, :update]
|
64
|
+
# }
|
65
|
+
attr_reader :action_aliases
|
66
|
+
|
54
67
|
# The class that currently represents authorizations in the system, as set
|
55
68
|
# by {set_core_models}.
|
56
|
-
|
69
|
+
attr_reader :authorization_class
|
57
70
|
# The class that currently represents authorization subjects in the
|
58
71
|
# system, as set by {set_core_models}.
|
59
|
-
|
72
|
+
attr_reader :person_class
|
60
73
|
# The class that curretly represents roles in the system, as set by
|
61
74
|
# {set_core_models}.
|
62
|
-
|
75
|
+
attr_reader :role_class
|
63
76
|
# Classes that are marked as authorizable resources using
|
64
77
|
# {Permit::Models::AuthorizableExtensions::AuthorizableClassMethods#permit_authorizable permit_authorizable}.
|
65
|
-
|
78
|
+
attr_reader :authorizable_classes
|
66
79
|
|
67
|
-
#
|
68
|
-
# will be expanded into the actions given in the value array.
|
69
|
-
def action_aliases; @@action_aliases; end
|
80
|
+
#def action_aliases; @@action_aliases; end
|
70
81
|
|
71
82
|
# Indicates the response that PermitRules will take if no
|
72
83
|
# authorizations match. If set to +:allow+ then a subject will be given
|
73
84
|
# access unless denied. By default this is set to +:deny+
|
74
85
|
#
|
75
86
|
# @return the current default access.
|
76
|
-
def default_access;
|
87
|
+
def default_access; @default_access; end
|
77
88
|
|
78
89
|
# Sets the response that PermitRules will use when no rules match.
|
79
90
|
#
|
80
91
|
# @param [:allow, :deny] access the default response to use.
|
81
|
-
def default_access=(access);
|
92
|
+
def default_access=(access); @default_access = access; end
|
82
93
|
|
83
94
|
# The method to use to retrieve the current authorization subject when
|
84
95
|
# rules are being evaluated. If nil, then the method will be inferred from
|
85
96
|
# the subject set in the call to {set_core_models}.
|
86
97
|
#
|
87
98
|
# @return [Symbol, nil]
|
88
|
-
def controller_subject_method;
|
99
|
+
def controller_subject_method; @controller_subject_method; end
|
89
100
|
|
90
101
|
# Sets the name of the method to use to retrieve the current subject
|
91
102
|
# while checking authorizations. Set to nil, to infer the value from the
|
@@ -93,7 +104,7 @@ module Permit
|
|
93
104
|
# authorizations are not being used.
|
94
105
|
#
|
95
106
|
# @param [nil, Symbol] method a symbol representing the method to use.
|
96
|
-
def controller_subject_method=(method);
|
107
|
+
def controller_subject_method=(method); @controller_subject_method = method; end
|
97
108
|
|
98
109
|
# Sets the core authorization, person, and role models to be used for
|
99
110
|
# named authorizations, and configures them with their respective permit_*
|
@@ -108,13 +119,13 @@ module Permit
|
|
108
119
|
def set_core_models(authorization, person, role)
|
109
120
|
#raise PermitConfigurationError, "Core models cannot be redefined." if @@models_defined
|
110
121
|
|
111
|
-
|
112
|
-
|
113
|
-
|
122
|
+
@authorization_class = authorization
|
123
|
+
@person_class = person
|
124
|
+
@role_class = role
|
114
125
|
|
115
|
-
|
116
|
-
|
117
|
-
|
126
|
+
@authorization_class.send :permit_authorization
|
127
|
+
@person_class.send :permit_person
|
128
|
+
@role_class.send :permit_role
|
118
129
|
end
|
119
130
|
|
120
131
|
# Forces Permit to reload its core classes based off of those given in the
|
data/lib/permit/controller.rb
CHANGED
@@ -80,27 +80,78 @@ module Permit
|
|
80
80
|
true
|
81
81
|
end
|
82
82
|
|
83
|
-
#
|
84
|
-
#
|
83
|
+
# Determines if a person is allowed access by evaluating rules for a
|
84
|
+
# controller/action, or for a custom rule.
|
85
85
|
#
|
86
|
-
#
|
87
|
-
#
|
86
|
+
# @overload allowed?(roles, options = {})
|
87
|
+
# Creates a PermitRule with the arguments that are given, and attempts
|
88
|
+
# to match it based on the current subject and binding context.
|
89
|
+
#
|
90
|
+
# For information on the parameters for this method see
|
91
|
+
# {PermitRule#initialize}.
|
92
|
+
#
|
93
|
+
# @return [Boolean] true if the rule matches, otherwise false.
|
94
|
+
#
|
95
|
+
# @overload allowed?(options)
|
96
|
+
# Attempts to evaluate the rules for the given action against the
|
97
|
+
# specified controller using the current subject, and binding context.
|
88
98
|
#
|
89
|
-
#
|
90
|
-
|
91
|
-
|
92
|
-
|
99
|
+
# Keep in mind that the evaluation is performed using the binding of the
|
100
|
+
# current controller. Any instance variables that may normally be needed
|
101
|
+
# for the rules on another controller need to exist in the current
|
102
|
+
# controller.
|
103
|
+
#
|
104
|
+
# @param [Hash] options the controller/action to evaluate rules for.
|
105
|
+
# @option options [String, Symbol] controller the name of the controller to
|
106
|
+
# evaluate the rules from. If this is not given then the current
|
107
|
+
# controller is used. You may use the string syntax 'namespaced/teams'
|
108
|
+
# for a namespaced controller Namespaced::TeamsController.
|
109
|
+
# @option options [Symbol] action the action to evaluate rules for.
|
110
|
+
#
|
111
|
+
# @return [Boolean] true if the rule matches, otherwise false.
|
112
|
+
def allowed?(*args)
|
113
|
+
options = args.extract_options!
|
114
|
+
if options.has_key? :action
|
115
|
+
name = options[:controller]
|
116
|
+
klass = (name ? "#{name}_controller".camelize.constantize : self)
|
117
|
+
klass.permit_rules.permitted? permit_authorization_subject, options[:action], binding
|
118
|
+
else
|
119
|
+
rule = PermitRule.new args[0], options
|
120
|
+
rule.matches? permit_authorization_subject, binding
|
121
|
+
end
|
93
122
|
end
|
94
123
|
|
95
|
-
#
|
96
|
-
#
|
124
|
+
# Determines if a person is denied access by evaluating rules for a
|
125
|
+
# controller/action, or for a custom rule.
|
97
126
|
#
|
98
|
-
#
|
99
|
-
#
|
127
|
+
# @overload denied?(roles, options = {})
|
128
|
+
# Creates a PermitRule with the arguments that are given, and attempts
|
129
|
+
# to match it based on the current subject and binding context.
|
130
|
+
#
|
131
|
+
# For information on the parameters for this method see
|
132
|
+
# {PermitRule#initialize}.
|
133
|
+
#
|
134
|
+
# @return [Boolean] true if the rule does not match, otherwise false.
|
135
|
+
#
|
136
|
+
# @overload denied?(options)
|
137
|
+
# Attempts to evaluate the rules for the given action against the
|
138
|
+
# specified controller using the current subject, and binding context.
|
139
|
+
#
|
140
|
+
# Keep in mind that the evaluation is performed using the binding of the
|
141
|
+
# current controller. Any instance variables that may normally be needed
|
142
|
+
# for the rules on another controller need to exist in the current
|
143
|
+
# controller.
|
144
|
+
#
|
145
|
+
# @param [Hash] options the controller/action to evaluate rules for.
|
146
|
+
# @option options [String, Symbol] controller the name of the controller to
|
147
|
+
# evaluate the rules from. If this is not given then the current
|
148
|
+
# controller is used. You may use the string syntax 'namespaced/teams'
|
149
|
+
# for a namespaced controller Namespaced::TeamsController.
|
150
|
+
# @option options [Symbol] action the action to evaluate rules for.
|
100
151
|
#
|
101
|
-
#
|
102
|
-
def denied?(
|
103
|
-
!allowed?
|
152
|
+
# @return [Boolean] true if the subject is denied, otherwise false.
|
153
|
+
def denied?(*args)
|
154
|
+
!allowed? *args
|
104
155
|
end
|
105
156
|
|
106
157
|
# Shortcut for +current_person#authorized?+. If the current person is a
|
@@ -108,8 +159,8 @@ module Permit
|
|
108
159
|
#
|
109
160
|
# For information on the parameters for this method see
|
110
161
|
# {Permit::Models::PersonExtensions::PersonInstanceMethods#authorized?}
|
111
|
-
def authorized?(roles,
|
112
|
-
permit_authorization_subject.guest? ? false : permit_authorization_subject.authorized?(roles,
|
162
|
+
def authorized?(roles, resources)
|
163
|
+
permit_authorization_subject.guest? ? false : permit_authorization_subject.authorized?(roles, resources)
|
113
164
|
end
|
114
165
|
|
115
166
|
private
|
data/lib/permit/permit_rule.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
module Permit
|
2
|
+
# Defines an authorization rule to match against.
|
2
3
|
class PermitRule
|
3
4
|
include Permit::Support
|
4
5
|
|
5
6
|
VALID_OPTION_KEYS = [:who, :that, :of, :on, :if, :unless]
|
6
7
|
BUILTIN_ROLES = [:person, :guest, :everyone]
|
7
8
|
|
8
|
-
attr_reader :roles, :
|
9
|
+
attr_reader :roles, :target_vars, :method, :if, :unless
|
9
10
|
|
10
11
|
# Creates a new PermitRule.
|
11
12
|
#
|
@@ -35,8 +36,8 @@ module Permit
|
|
35
36
|
# +is_owner()+, +is_owner?()+, +owner()+, +owner+, +owners.exist?()+. If
|
36
37
|
# this option is given +:of+/+:on+ must also be given.
|
37
38
|
# @option options [Symbol] :that alias for +:who+
|
38
|
-
# @option options [Symbol] :of The name of the
|
39
|
-
# the target resource.
|
39
|
+
# @option options [Symbol, nil, :any, <Symbol, nil>] :of The name of the
|
40
|
+
# instance variable(s) to use as the target resource(s).
|
40
41
|
#
|
41
42
|
# In a dynamic authorization this is the object that will be tested using
|
42
43
|
# the value of +:who+/+:that+.
|
@@ -46,12 +47,15 @@ module Permit
|
|
46
47
|
# indicate a match if the person has one of the roles for any resource. If
|
47
48
|
# not given, or set to +nil+, then the match will apply to a person that
|
48
49
|
# has a matching role authorization for a nil resource.
|
49
|
-
# @option options [Symbol] :on alias for +:of+
|
50
|
+
# @option options [Symbol, nil, :any, <Symbol, nil>] :on alias for +:of+
|
50
51
|
# @option options [Symbol, String, Proc] :if code to evaluate at the end of the
|
51
|
-
# match if it is still valid. If it returns false, the rule will not
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
52
|
+
# match if it is still valid. If it returns false, the rule will not
|
53
|
+
# match. If a proc if given, it will be passed the current subject and
|
54
|
+
# binding. A method will be called without any arguments.
|
55
|
+
# @option options [Symbol, String, Proc] :unless code to evaluate at the end of
|
56
|
+
# the match if it is still valid. If it returns true, the rule will not
|
57
|
+
# match. If a proc if given, it will be passed the current subject and
|
58
|
+
# binding. A method will be called without any arguments.
|
55
59
|
#
|
56
60
|
# @raise [PermitConfigurationError] if the rule options are invalid.
|
57
61
|
def initialize(roles, options = {})
|
@@ -62,7 +66,7 @@ module Permit
|
|
62
66
|
validate_options options
|
63
67
|
|
64
68
|
@method = options[:who] || options[:that]
|
65
|
-
@
|
69
|
+
@target_vars = permit_arrayify(options[:of] || options[:on]).uniq.freeze
|
66
70
|
|
67
71
|
@if = options[:if]
|
68
72
|
@unless = options[:unless]
|
@@ -83,7 +87,7 @@ module Permit
|
|
83
87
|
has_named_authorizations? person, context_binding
|
84
88
|
end
|
85
89
|
|
86
|
-
passed_conditionals = matched ? passes_conditionals?(context_binding) : false
|
90
|
+
passed_conditionals = matched ? passes_conditionals?(person, context_binding) : false
|
87
91
|
passed = matched && passed_conditionals
|
88
92
|
return passed
|
89
93
|
end
|
@@ -121,24 +125,36 @@ module Permit
|
|
121
125
|
|
122
126
|
def has_named_authorizations?(person, context_binding)
|
123
127
|
return false if person.guest?
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
128
|
+
resources = []
|
129
|
+
@target_vars.each do |var_name|
|
130
|
+
resources << case var_name
|
131
|
+
when nil then nil
|
132
|
+
when :any then (resources = :any and break)
|
133
|
+
else get_resource(var_name, context_binding)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
person.authorized? @roles, resources
|
130
137
|
end
|
131
138
|
|
132
139
|
def has_dynamic_authorization?(person, context_binding)
|
133
140
|
return false if person.guest?
|
134
|
-
return true if @target_var.nil?
|
135
141
|
|
136
|
-
resource = get_resource context_binding
|
137
142
|
methods = determine_method_sequence @method
|
138
143
|
|
144
|
+
@target_vars.each do |var_name|
|
145
|
+
return true if var_name.nil?
|
146
|
+
|
147
|
+
resource = get_resource var_name, context_binding
|
148
|
+
return true if evaluate_dynamic_methods(var_name, resource, methods, person)
|
149
|
+
end
|
150
|
+
|
151
|
+
return false
|
152
|
+
end
|
153
|
+
|
154
|
+
def evaluate_dynamic_methods(var_name, resource, methods, person)
|
139
155
|
methods.each do |name, type|
|
140
156
|
next unless resource.respond_to? name
|
141
|
-
|
157
|
+
|
142
158
|
case type
|
143
159
|
when :method then return resource.send name, person
|
144
160
|
when :getter then return resource.send(name) == person
|
@@ -148,7 +164,7 @@ module Permit
|
|
148
164
|
end
|
149
165
|
|
150
166
|
# Target didn't respond to any attempts. This would be a problem.
|
151
|
-
raise PermitEvaluationError, "Target object ':#{
|
167
|
+
raise PermitEvaluationError, "Target object ':#{var_name}' evaluated as #{resource.inspect} did not respond to any of the following: #{methods.collect {|n,t| n}.join(', ')}"
|
152
168
|
end
|
153
169
|
|
154
170
|
# is_owner - is_owner(), is_owner?(), owner?(), owner, owners.exists()
|
@@ -174,20 +190,25 @@ module Permit
|
|
174
190
|
end
|
175
191
|
end
|
176
192
|
|
177
|
-
def get_resource(context_binding)
|
178
|
-
|
193
|
+
def get_resource(var, context_binding)
|
194
|
+
var_name = "@#{var.to_s}"
|
195
|
+
if eval(%Q{instance_variables.include? "#{var_name}"}, context_binding)
|
196
|
+
eval var_name, context_binding
|
197
|
+
else
|
198
|
+
raise PermitEvaluationError, "Target resource '#{var_name}' did not exist in the given context."
|
199
|
+
end
|
179
200
|
end
|
180
201
|
|
181
|
-
def passes_conditionals?(context_binding)
|
182
|
-
return false unless eval_conditional @if, true, context_binding
|
183
|
-
return false if eval_conditional @unless, false, context_binding
|
202
|
+
def passes_conditionals?(person, context_binding)
|
203
|
+
return false unless eval_conditional @if, true, person, context_binding
|
204
|
+
return false if eval_conditional @unless, false, person, context_binding
|
184
205
|
true
|
185
206
|
end
|
186
207
|
|
187
|
-
def eval_conditional(condition, default, context_binding)
|
208
|
+
def eval_conditional(condition, default, person, context_binding)
|
188
209
|
if condition
|
189
210
|
condition = condition.to_s if Symbol===condition
|
190
|
-
return (String===condition ? eval(condition, context_binding) : condition.call)
|
211
|
+
return (String===condition ? eval(condition, context_binding) : condition.call(person, context_binding))
|
191
212
|
else
|
192
213
|
return default
|
193
214
|
end
|