annotation_security 1.0.1 → 1.0.2
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/CHANGELOG.md +14 -0
- data/HOW-TO.md +275 -0
- data/{MIT-LICENSE → LICENSE} +1 -1
- data/README.md +39 -0
- data/Rakefile +62 -55
- data/assets/app/helpers/annotation_security_helper.rb +8 -8
- data/assets/config/initializers/annotation_security.rb +11 -11
- data/assets/config/security/relations.rb +20 -20
- data/assets/vendor/plugins/annotation_security/init.rb +13 -13
- data/bin/annotation_security +7 -7
- data/lib/annotation_security/exceptions.rb +124 -124
- data/lib/annotation_security/exec.rb +188 -188
- data/lib/annotation_security/filters.rb +37 -37
- data/lib/annotation_security/includes/action_controller.rb +144 -143
- data/lib/annotation_security/includes/active_record.rb +27 -27
- data/lib/annotation_security/includes/helper.rb +215 -215
- data/lib/annotation_security/includes/resource.rb +84 -84
- data/lib/annotation_security/includes/role.rb +30 -30
- data/lib/annotation_security/includes/user.rb +26 -26
- data/lib/annotation_security/manager/policy_factory.rb +29 -29
- data/lib/annotation_security/manager/policy_manager.rb +79 -79
- data/lib/annotation_security/manager/relation_loader.rb +272 -272
- data/lib/annotation_security/manager/resource_manager.rb +36 -36
- data/lib/annotation_security/manager/right_loader.rb +87 -87
- data/lib/annotation_security/model_observer.rb +61 -61
- data/lib/annotation_security/policy/abstract_policy.rb +344 -344
- data/lib/annotation_security/policy/abstract_static_policy.rb +75 -75
- data/lib/annotation_security/policy/all_resources_policy.rb +20 -20
- data/lib/annotation_security/policy/rule.rb +340 -340
- data/lib/annotation_security/policy/rule_set.rb +138 -138
- data/lib/annotation_security/rails.rb +38 -38
- data/lib/annotation_security/user_wrapper.rb +73 -73
- data/lib/annotation_security/utils.rb +141 -141
- data/lib/annotation_security/version.rb +10 -0
- data/lib/annotation_security.rb +102 -97
- data/lib/extensions/action_controller.rb +32 -32
- data/lib/extensions/active_record.rb +34 -34
- data/lib/extensions/filter.rb +133 -133
- data/lib/extensions/object.rb +10 -10
- data/lib/security_context.rb +589 -551
- data/spec/annotation_security/exceptions_spec.rb +16 -16
- data/spec/annotation_security/includes/helper_spec.rb +82 -82
- data/spec/annotation_security/manager/policy_manager_spec.rb +15 -15
- data/spec/annotation_security/manager/resource_manager_spec.rb +17 -17
- data/spec/annotation_security/manager/right_loader_spec.rb +17 -17
- data/spec/annotation_security/policy/abstract_policy_spec.rb +16 -16
- data/spec/annotation_security/policy/all_resources_policy_spec.rb +24 -24
- data/spec/annotation_security/policy/rule_set_spec.rb +112 -112
- data/spec/annotation_security/policy/rule_spec.rb +77 -77
- data/spec/annotation_security/policy/test_policy_spec.rb +80 -80
- data/spec/annotation_security/security_context_spec.rb +78 -78
- data/spec/annotation_security/utils_spec.rb +73 -73
- data/spec/helper/test_controller.rb +65 -65
- data/spec/helper/test_helper.rb +5 -5
- data/spec/helper/test_relations.rb +6 -6
- data/spec/helper/test_resource.rb +38 -38
- data/spec/helper/test_role.rb +21 -21
- data/spec/helper/test_user.rb +31 -31
- data/spec/rails_stub.rb +37 -37
- metadata +94 -72
- data/CHANGELOG +0 -2
- data/HOW-TO +0 -261
- data/README +0 -39
@@ -1,273 +1,273 @@
|
|
1
|
-
#
|
2
|
-
# = lib/annotation_security/manager/relation_loader.rb
|
3
|
-
#
|
4
|
-
|
5
|
-
# Class responsible for loading the relation definitions for resources.
|
6
|
-
#
|
7
|
-
# == Defining a relation for a resource
|
8
|
-
#
|
9
|
-
# This example defines the owner relation between a picture and a user.
|
10
|
-
# A relation definition is a proc that returns true if the relation exists.
|
11
|
-
# All three examples are equivalent. However, in most cases the first way is
|
12
|
-
# the way you want to use.
|
13
|
-
# AnnotationSecurity.define_relations do
|
14
|
-
# resource :picture do
|
15
|
-
# owner { |user,picture| picture.user == user }
|
16
|
-
# end
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# If you need only one relation for a resource class, use this example:
|
20
|
-
# AnnotationSecurity.define_relations do
|
21
|
-
# picture.owner { |user,picture| picture.user == user }
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# If the entire file contains definitions for only one resource class,
|
25
|
-
# you might try this:
|
26
|
-
# AnnotationSecurity.define_relations :picture do
|
27
|
-
# owner { |user,picture| picture.user == user }
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
# === Defining a relation for many resources
|
31
|
-
#
|
32
|
-
# Use +resources+ to define a relation once for more than one resource class.
|
33
|
-
# AnnotationSecurity.define_relations do
|
34
|
-
# resources(:picture, :comment) do
|
35
|
-
# owner { |user,res| res.user == user }
|
36
|
-
# end
|
37
|
-
# end
|
38
|
-
# As for one resource, you can also use
|
39
|
-
# AnnotationSecurity.define_relations do
|
40
|
-
# resources(:picture, :comment).owner { |user,res| res.user == user }
|
41
|
-
# end
|
42
|
-
# or
|
43
|
-
# AnnotationSecurity.define_relations(:picture, :comment) do
|
44
|
-
# owner { |user,res| res.user == user }
|
45
|
-
# end
|
46
|
-
#
|
47
|
-
# It is also possible to define relations for all resources:
|
48
|
-
# AnnotationSecurity.define_relations do
|
49
|
-
# all_resources do
|
50
|
-
# related { owner or friend_of_owner }
|
51
|
-
# end
|
52
|
-
# end
|
53
|
-
# or
|
54
|
-
# AnnotationSecurity.define_relations do
|
55
|
-
# all_resources.related { owner or friend_of_owner }
|
56
|
-
# end
|
57
|
-
#
|
58
|
-
# Notice that +owner+ and +friend_of_owner+ are relations that can be defined
|
59
|
-
# individually for each resource. The 2 parameters +user+ and +resource_object+
|
60
|
-
# dont need to be specified if they are not used.
|
61
|
-
#
|
62
|
-
# == Details on defining a relation
|
63
|
-
#
|
64
|
-
# As you have seen, the default way to define a relation is using a proc,
|
65
|
-
# like
|
66
|
-
# owner { |user,picture| picture.user == user }
|
67
|
-
# related { owner or friend_of_owner }
|
68
|
-
#
|
69
|
-
# If the condition is simple and uses only other relations,
|
70
|
-
# it also can be specified by a string:
|
71
|
-
# related 'if owner or friend_of_owner'
|
72
|
-
#
|
73
|
-
# === Implicit conditions
|
74
|
-
# Besides a string or a proc, a rule definition can contain a list of flags
|
75
|
-
# and an options-hash.
|
76
|
-
#
|
77
|
-
# ==== The :is option
|
78
|
-
#
|
79
|
-
# A Relation to which the <tt>:is => symbol</tt> option is passed as a parameter
|
80
|
-
# only exists if the relation exists and <tt>is_symbol?</tt> invoked on the
|
81
|
-
# current user evaluates to true.
|
82
|
-
#
|
83
|
-
# Let the user class have a method <tt>is_super_user?</tt>, which returns true
|
84
|
-
# or false, depending on wheter the user is a super user. This method can be
|
85
|
-
# used for defining a relation +super_owner+, that is true if the user is the
|
86
|
-
# owner and a super user.
|
87
|
-
#
|
88
|
-
# owner { |user,picture| picture.user == user }
|
89
|
-
# super_owner(:is => :super_user) "if owner"
|
90
|
-
#
|
91
|
-
# super_user(:system, :is => :super_user)
|
92
|
-
#
|
93
|
-
# ==== The :as option
|
94
|
-
#
|
95
|
-
# For a relation to which the <tt>:as => symbol</tt> option is passed as a
|
96
|
-
# parameter the current user is replaced by the invocation of
|
97
|
-
# <tt>current_credential.as_[symbol]</tt>. The method invocation may return +nil+
|
98
|
-
# indicating that the transformation failed. In this case the relation for
|
99
|
-
# which <tt>:as => ..</tt> was specified does not exist.
|
100
|
-
#
|
101
|
-
# ==== :require_credential
|
102
|
-
# By default, a relation requires a user to be executed. Therefore, rights will
|
103
|
-
# always fail if the user is nil. To enable rights like 'unless logged_in', the
|
104
|
-
# :require_credential option can be set to false.
|
105
|
-
# logged_in(:system, :require_credential => false) { |user| not user.nil? }
|
106
|
-
#
|
107
|
-
# === Evaluation time
|
108
|
-
# While most relations are between the user and a resource object, some are
|
109
|
-
# beween the user and an entire class of objects. This means that no instance of
|
110
|
-
# a resource is required to tell whether the user has that relation or not.
|
111
|
-
#
|
112
|
-
# ==== The :resource flag
|
113
|
-
# This flag is set by default. It is set for relations that need a resource.
|
114
|
-
#
|
115
|
-
# owner { |user,picture| picture.user == user }
|
116
|
-
# # is short for
|
117
|
-
# # owner(:resource) { |user,picture| picture.user == user }
|
118
|
-
#
|
119
|
-
# ==== The :system flag
|
120
|
-
# You can use the :system flag to denote that a relation does not
|
121
|
-
# require a resource object.
|
122
|
-
#
|
123
|
-
# all_resources do
|
124
|
-
# super_user(:system, :is => :super_user)
|
125
|
-
# end
|
126
|
-
#
|
127
|
-
# It is possible to define system relations only for certain resources, and they
|
128
|
-
# do not conflict with resource relations.
|
129
|
-
#
|
130
|
-
# resource :present do
|
131
|
-
# receiver(:system) { |user| user.was_good? }
|
132
|
-
# receiver { |user,present| present.receiver == user }
|
133
|
-
# end
|
134
|
-
#
|
135
|
-
# The advantage of system relations is that they improve the rights evaluation.
|
136
|
-
# Consider the right
|
137
|
-
# present:
|
138
|
-
# receive: if receiver
|
139
|
-
#
|
140
|
-
# If an action is invoked requiring the receive-present right,
|
141
|
-
# AnnotationSecurity will evaluate the system relation before even entering the
|
142
|
-
# action, thus improving the fail fast behavior and avoiding unnecessary
|
143
|
-
# operations.
|
144
|
-
#
|
145
|
-
# Once a present object is observed during the action, the resource relation
|
146
|
-
# will be evaluated as well.
|
147
|
-
#
|
148
|
-
# ==== The :pretest flag
|
149
|
-
#
|
150
|
-
# Using the :pretest flag, it is possible to define both resource and system
|
151
|
-
# relations in one block.
|
152
|
-
#
|
153
|
-
# resource :present do
|
154
|
-
# receiver(:pretest) do |user, present|
|
155
|
-
# if present
|
156
|
-
# present.receiver == user
|
157
|
-
# else
|
158
|
-
# user.was_good?
|
159
|
-
# end
|
160
|
-
# end
|
161
|
-
# end
|
162
|
-
#
|
163
|
-
# This can be helpfull if your relation depends on other relations, where a
|
164
|
-
# resource and a system version is available.
|
165
|
-
#
|
166
|
-
# all_resources do
|
167
|
-
# responsible(:pretest) { lecturer or corrector }
|
168
|
-
# lecturer(:system, :as => :lecturer)
|
169
|
-
# corrector(:system, :as => :corrector)
|
170
|
-
# end
|
171
|
-
#
|
172
|
-
# resource :course do
|
173
|
-
# lecturer(:as => :lecturer) { |lecturer, course| course.lecturers.include? lecturer }
|
174
|
-
# corrector(:as => :corrector) { |corrector, course| course.correctors.include? corrector }
|
175
|
-
# end
|
176
|
-
# # For other resources, lecturer and corrector are defined differently
|
177
|
-
#
|
178
|
-
# === Defining relations as strings
|
179
|
-
#
|
180
|
-
# Instead of a block, a string can be used to define the relation.
|
181
|
-
# responsible :pretest, "if lecturer or corrector"
|
182
|
-
#
|
183
|
-
# The string syntax provides more simplifications, like referring to relations
|
184
|
-
# of other resources.
|
185
|
-
#
|
186
|
-
# This example will evaluate the course-correction relation for the course
|
187
|
-
# property of an assignment resource.
|
188
|
-
# resource :assignment do
|
189
|
-
# corrector "if course.corrector: course"
|
190
|
-
# end
|
191
|
-
#
|
192
|
-
# As the course class includes AnnotationSecurity::Resource, the resource type
|
193
|
-
# is not explicitly needed.
|
194
|
-
# resource :assignment_result do
|
195
|
-
# corrector "if corrector: assignment.course"
|
196
|
-
# end
|
197
|
-
#
|
198
|
-
#
|
199
|
-
class AnnotationSecurity::RelationLoader
|
200
|
-
|
201
|
-
# Load relations of the +block+
|
202
|
-
# * +resources+ (optional) list of resources
|
203
|
-
# * +block+ block with relation definitions
|
204
|
-
def self.define_relations(*resources, &block)
|
205
|
-
if resources.blank?
|
206
|
-
class_eval(&block)
|
207
|
-
else
|
208
|
-
resources(*resources,&block)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
#
|
213
|
-
def self.method_missing(symbol,*args,&block) #:nodoc:
|
214
|
-
return super unless args.empty?
|
215
|
-
resources(symbol,&block)
|
216
|
-
end
|
217
|
-
|
218
|
-
# Defines relations for a resource
|
219
|
-
# * +block+ (optional) proc with relation definitions
|
220
|
-
def self.resource(resource,&block)
|
221
|
-
resources(resource,&block)
|
222
|
-
end
|
223
|
-
|
224
|
-
# Defines relations for a list of resources
|
225
|
-
# * +block+ (optional) proc with relation definitions
|
226
|
-
def self.resources(*resources,&block)
|
227
|
-
new(resources,&block)
|
228
|
-
end
|
229
|
-
|
230
|
-
# Defines relations for all resources
|
231
|
-
# * +block+ (optional) proc with relation definitions
|
232
|
-
def self.all_resources(&block)
|
233
|
-
resources(:all_resources,&block)
|
234
|
-
end
|
235
|
-
|
236
|
-
## ===========================================================================
|
237
|
-
## Instance
|
238
|
-
|
239
|
-
# An instance of RelationLoader is responsible for loading the relations
|
240
|
-
# for a set of resources.
|
241
|
-
def initialize(resources,&block) #:nodoc:
|
242
|
-
@factories = get_factories_for(resources)
|
243
|
-
instance_eval(&block) if block
|
244
|
-
end
|
245
|
-
|
246
|
-
# if a method is missing this will be a new relation for the resource class
|
247
|
-
def method_missing(symbol,*args,&block) #:nodoc:
|
248
|
-
define_relation(symbol,*args,&block)
|
249
|
-
end
|
250
|
-
|
251
|
-
# Defines a new relation for the current resources. However, instead of using
|
252
|
-
# define_relation(:relation_name,args) { |user,res| some_condition }
|
253
|
-
# it is recommended to use
|
254
|
-
# relation_name(args) { |user,res| some_condition }
|
255
|
-
#
|
256
|
-
# ==== Parameters
|
257
|
-
# * +symbol+ name of the relation
|
258
|
-
# * +args+ additonal arguments, see AnnotationSecurity::Rule for details
|
259
|
-
# * +block+ (optional) The condition can be passed either as string or as proc
|
260
|
-
#
|
261
|
-
def define_relation(symbol,*args,&block)
|
262
|
-
@factories.each do |factory|
|
263
|
-
factory.add_rule(symbol,*args,&block)
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
private
|
268
|
-
|
269
|
-
def get_factories_for(resources)
|
270
|
-
resources.collect{ |res| AnnotationSecurity::PolicyManager.policy_factory(res) }
|
271
|
-
end
|
272
|
-
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/manager/relation_loader.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
# Class responsible for loading the relation definitions for resources.
|
6
|
+
#
|
7
|
+
# == Defining a relation for a resource
|
8
|
+
#
|
9
|
+
# This example defines the owner relation between a picture and a user.
|
10
|
+
# A relation definition is a proc that returns true if the relation exists.
|
11
|
+
# All three examples are equivalent. However, in most cases the first way is
|
12
|
+
# the way you want to use.
|
13
|
+
# AnnotationSecurity.define_relations do
|
14
|
+
# resource :picture do
|
15
|
+
# owner { |user,picture| picture.user == user }
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# If you need only one relation for a resource class, use this example:
|
20
|
+
# AnnotationSecurity.define_relations do
|
21
|
+
# picture.owner { |user,picture| picture.user == user }
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# If the entire file contains definitions for only one resource class,
|
25
|
+
# you might try this:
|
26
|
+
# AnnotationSecurity.define_relations :picture do
|
27
|
+
# owner { |user,picture| picture.user == user }
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# === Defining a relation for many resources
|
31
|
+
#
|
32
|
+
# Use +resources+ to define a relation once for more than one resource class.
|
33
|
+
# AnnotationSecurity.define_relations do
|
34
|
+
# resources(:picture, :comment) do
|
35
|
+
# owner { |user,res| res.user == user }
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
# As for one resource, you can also use
|
39
|
+
# AnnotationSecurity.define_relations do
|
40
|
+
# resources(:picture, :comment).owner { |user,res| res.user == user }
|
41
|
+
# end
|
42
|
+
# or
|
43
|
+
# AnnotationSecurity.define_relations(:picture, :comment) do
|
44
|
+
# owner { |user,res| res.user == user }
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# It is also possible to define relations for all resources:
|
48
|
+
# AnnotationSecurity.define_relations do
|
49
|
+
# all_resources do
|
50
|
+
# related { owner or friend_of_owner }
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
# or
|
54
|
+
# AnnotationSecurity.define_relations do
|
55
|
+
# all_resources.related { owner or friend_of_owner }
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# Notice that +owner+ and +friend_of_owner+ are relations that can be defined
|
59
|
+
# individually for each resource. The 2 parameters +user+ and +resource_object+
|
60
|
+
# dont need to be specified if they are not used.
|
61
|
+
#
|
62
|
+
# == Details on defining a relation
|
63
|
+
#
|
64
|
+
# As you have seen, the default way to define a relation is using a proc,
|
65
|
+
# like
|
66
|
+
# owner { |user,picture| picture.user == user }
|
67
|
+
# related { owner or friend_of_owner }
|
68
|
+
#
|
69
|
+
# If the condition is simple and uses only other relations,
|
70
|
+
# it also can be specified by a string:
|
71
|
+
# related 'if owner or friend_of_owner'
|
72
|
+
#
|
73
|
+
# === Implicit conditions
|
74
|
+
# Besides a string or a proc, a rule definition can contain a list of flags
|
75
|
+
# and an options-hash.
|
76
|
+
#
|
77
|
+
# ==== The :is option
|
78
|
+
#
|
79
|
+
# A Relation to which the <tt>:is => symbol</tt> option is passed as a parameter
|
80
|
+
# only exists if the relation exists and <tt>is_symbol?</tt> invoked on the
|
81
|
+
# current user evaluates to true.
|
82
|
+
#
|
83
|
+
# Let the user class have a method <tt>is_super_user?</tt>, which returns true
|
84
|
+
# or false, depending on wheter the user is a super user. This method can be
|
85
|
+
# used for defining a relation +super_owner+, that is true if the user is the
|
86
|
+
# owner and a super user.
|
87
|
+
#
|
88
|
+
# owner { |user,picture| picture.user == user }
|
89
|
+
# super_owner(:is => :super_user) "if owner"
|
90
|
+
#
|
91
|
+
# super_user(:system, :is => :super_user)
|
92
|
+
#
|
93
|
+
# ==== The :as option
|
94
|
+
#
|
95
|
+
# For a relation to which the <tt>:as => symbol</tt> option is passed as a
|
96
|
+
# parameter the current user is replaced by the invocation of
|
97
|
+
# <tt>current_credential.as_[symbol]</tt>. The method invocation may return +nil+
|
98
|
+
# indicating that the transformation failed. In this case the relation for
|
99
|
+
# which <tt>:as => ..</tt> was specified does not exist.
|
100
|
+
#
|
101
|
+
# ==== :require_credential
|
102
|
+
# By default, a relation requires a user to be executed. Therefore, rights will
|
103
|
+
# always fail if the user is nil. To enable rights like 'unless logged_in', the
|
104
|
+
# :require_credential option can be set to false.
|
105
|
+
# logged_in(:system, :require_credential => false) { |user| not user.nil? }
|
106
|
+
#
|
107
|
+
# === Evaluation time
|
108
|
+
# While most relations are between the user and a resource object, some are
|
109
|
+
# beween the user and an entire class of objects. This means that no instance of
|
110
|
+
# a resource is required to tell whether the user has that relation or not.
|
111
|
+
#
|
112
|
+
# ==== The :resource flag
|
113
|
+
# This flag is set by default. It is set for relations that need a resource.
|
114
|
+
#
|
115
|
+
# owner { |user,picture| picture.user == user }
|
116
|
+
# # is short for
|
117
|
+
# # owner(:resource) { |user,picture| picture.user == user }
|
118
|
+
#
|
119
|
+
# ==== The :system flag
|
120
|
+
# You can use the :system flag to denote that a relation does not
|
121
|
+
# require a resource object.
|
122
|
+
#
|
123
|
+
# all_resources do
|
124
|
+
# super_user(:system, :is => :super_user)
|
125
|
+
# end
|
126
|
+
#
|
127
|
+
# It is possible to define system relations only for certain resources, and they
|
128
|
+
# do not conflict with resource relations.
|
129
|
+
#
|
130
|
+
# resource :present do
|
131
|
+
# receiver(:system) { |user| user.was_good? }
|
132
|
+
# receiver { |user,present| present.receiver == user }
|
133
|
+
# end
|
134
|
+
#
|
135
|
+
# The advantage of system relations is that they improve the rights evaluation.
|
136
|
+
# Consider the right
|
137
|
+
# present:
|
138
|
+
# receive: if receiver
|
139
|
+
#
|
140
|
+
# If an action is invoked requiring the receive-present right,
|
141
|
+
# AnnotationSecurity will evaluate the system relation before even entering the
|
142
|
+
# action, thus improving the fail fast behavior and avoiding unnecessary
|
143
|
+
# operations.
|
144
|
+
#
|
145
|
+
# Once a present object is observed during the action, the resource relation
|
146
|
+
# will be evaluated as well.
|
147
|
+
#
|
148
|
+
# ==== The :pretest flag
|
149
|
+
#
|
150
|
+
# Using the :pretest flag, it is possible to define both resource and system
|
151
|
+
# relations in one block.
|
152
|
+
#
|
153
|
+
# resource :present do
|
154
|
+
# receiver(:pretest) do |user, present|
|
155
|
+
# if present
|
156
|
+
# present.receiver == user
|
157
|
+
# else
|
158
|
+
# user.was_good?
|
159
|
+
# end
|
160
|
+
# end
|
161
|
+
# end
|
162
|
+
#
|
163
|
+
# This can be helpfull if your relation depends on other relations, where a
|
164
|
+
# resource and a system version is available.
|
165
|
+
#
|
166
|
+
# all_resources do
|
167
|
+
# responsible(:pretest) { lecturer or corrector }
|
168
|
+
# lecturer(:system, :as => :lecturer)
|
169
|
+
# corrector(:system, :as => :corrector)
|
170
|
+
# end
|
171
|
+
#
|
172
|
+
# resource :course do
|
173
|
+
# lecturer(:as => :lecturer) { |lecturer, course| course.lecturers.include? lecturer }
|
174
|
+
# corrector(:as => :corrector) { |corrector, course| course.correctors.include? corrector }
|
175
|
+
# end
|
176
|
+
# # For other resources, lecturer and corrector are defined differently
|
177
|
+
#
|
178
|
+
# === Defining relations as strings
|
179
|
+
#
|
180
|
+
# Instead of a block, a string can be used to define the relation.
|
181
|
+
# responsible :pretest, "if lecturer or corrector"
|
182
|
+
#
|
183
|
+
# The string syntax provides more simplifications, like referring to relations
|
184
|
+
# of other resources.
|
185
|
+
#
|
186
|
+
# This example will evaluate the course-correction relation for the course
|
187
|
+
# property of an assignment resource.
|
188
|
+
# resource :assignment do
|
189
|
+
# corrector "if course.corrector: course"
|
190
|
+
# end
|
191
|
+
#
|
192
|
+
# As the course class includes AnnotationSecurity::Resource, the resource type
|
193
|
+
# is not explicitly needed.
|
194
|
+
# resource :assignment_result do
|
195
|
+
# corrector "if corrector: assignment.course"
|
196
|
+
# end
|
197
|
+
#
|
198
|
+
#
|
199
|
+
class AnnotationSecurity::RelationLoader
|
200
|
+
|
201
|
+
# Load relations of the +block+
|
202
|
+
# * +resources+ (optional) list of resources
|
203
|
+
# * +block+ block with relation definitions
|
204
|
+
def self.define_relations(*resources, &block)
|
205
|
+
if resources.blank?
|
206
|
+
class_eval(&block)
|
207
|
+
else
|
208
|
+
resources(*resources,&block)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
#
|
213
|
+
def self.method_missing(symbol,*args,&block) #:nodoc:
|
214
|
+
return super unless args.empty?
|
215
|
+
resources(symbol,&block)
|
216
|
+
end
|
217
|
+
|
218
|
+
# Defines relations for a resource
|
219
|
+
# * +block+ (optional) proc with relation definitions
|
220
|
+
def self.resource(resource,&block)
|
221
|
+
resources(resource,&block)
|
222
|
+
end
|
223
|
+
|
224
|
+
# Defines relations for a list of resources
|
225
|
+
# * +block+ (optional) proc with relation definitions
|
226
|
+
def self.resources(*resources,&block)
|
227
|
+
new(resources,&block)
|
228
|
+
end
|
229
|
+
|
230
|
+
# Defines relations for all resources
|
231
|
+
# * +block+ (optional) proc with relation definitions
|
232
|
+
def self.all_resources(&block)
|
233
|
+
resources(:all_resources,&block)
|
234
|
+
end
|
235
|
+
|
236
|
+
## ===========================================================================
|
237
|
+
## Instance
|
238
|
+
|
239
|
+
# An instance of RelationLoader is responsible for loading the relations
|
240
|
+
# for a set of resources.
|
241
|
+
def initialize(resources,&block) #:nodoc:
|
242
|
+
@factories = get_factories_for(resources)
|
243
|
+
instance_eval(&block) if block
|
244
|
+
end
|
245
|
+
|
246
|
+
# if a method is missing this will be a new relation for the resource class
|
247
|
+
def method_missing(symbol,*args,&block) #:nodoc:
|
248
|
+
define_relation(symbol,*args,&block)
|
249
|
+
end
|
250
|
+
|
251
|
+
# Defines a new relation for the current resources. However, instead of using
|
252
|
+
# define_relation(:relation_name,args) { |user,res| some_condition }
|
253
|
+
# it is recommended to use
|
254
|
+
# relation_name(args) { |user,res| some_condition }
|
255
|
+
#
|
256
|
+
# ==== Parameters
|
257
|
+
# * +symbol+ name of the relation
|
258
|
+
# * +args+ additonal arguments, see AnnotationSecurity::Rule for details
|
259
|
+
# * +block+ (optional) The condition can be passed either as string or as proc
|
260
|
+
#
|
261
|
+
def define_relation(symbol,*args,&block)
|
262
|
+
@factories.each do |factory|
|
263
|
+
factory.add_rule(symbol,*args,&block)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
private
|
268
|
+
|
269
|
+
def get_factories_for(resources)
|
270
|
+
resources.collect{ |res| AnnotationSecurity::PolicyManager.policy_factory(res) }
|
271
|
+
end
|
272
|
+
|
273
273
|
end
|
@@ -1,36 +1,36 @@
|
|
1
|
-
#
|
2
|
-
# = lib/annotation_security/manager/resource_manager.rb
|
3
|
-
#
|
4
|
-
|
5
|
-
# Needed to find resource objects when only their id is known
|
6
|
-
#
|
7
|
-
class AnnotationSecurity::ResourceManager # :nodoc:
|
8
|
-
|
9
|
-
@classes = {}
|
10
|
-
|
11
|
-
def self.add_resource_class(res_type,klass)
|
12
|
-
@classes.delete_if { |k,v| v == klass }
|
13
|
-
@classes[res_type] = klass
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.get_resource_class(res_type)
|
17
|
-
@classes[res_type]
|
18
|
-
end
|
19
|
-
|
20
|
-
unless RAILS_ENV == 'production'
|
21
|
-
def self.get_resource_class(res_type)
|
22
|
-
c = @classes[res_type]
|
23
|
-
unless c
|
24
|
-
res_type.to_s.camelize.constantize # load the class
|
25
|
-
c = @classes[res_type]
|
26
|
-
end
|
27
|
-
c
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# Call get_resource of the class that is registered for +res_type+
|
32
|
-
def self.get_resource(res_type,object)
|
33
|
-
c = get_resource_class(res_type)
|
34
|
-
c ? c.get_resource(object) : object
|
35
|
-
end
|
36
|
-
end
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/manager/resource_manager.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
# Needed to find resource objects when only their id is known
|
6
|
+
#
|
7
|
+
class AnnotationSecurity::ResourceManager # :nodoc:
|
8
|
+
|
9
|
+
@classes = {}
|
10
|
+
|
11
|
+
def self.add_resource_class(res_type,klass)
|
12
|
+
@classes.delete_if { |k,v| v == klass }
|
13
|
+
@classes[res_type] = klass
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.get_resource_class(res_type)
|
17
|
+
@classes[res_type]
|
18
|
+
end
|
19
|
+
|
20
|
+
unless RAILS_ENV == 'production'
|
21
|
+
def self.get_resource_class(res_type)
|
22
|
+
c = @classes[res_type]
|
23
|
+
unless c
|
24
|
+
res_type.to_s.camelize.constantize # load the class
|
25
|
+
c = @classes[res_type]
|
26
|
+
end
|
27
|
+
c
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Call get_resource of the class that is registered for +res_type+
|
32
|
+
def self.get_resource(res_type,object)
|
33
|
+
c = get_resource_class(res_type)
|
34
|
+
c ? c.get_resource(object) : object
|
35
|
+
end
|
36
|
+
end
|