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