annotation_security 1.0.2 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/CHANGELOG +22 -0
  2. data/HOW-TO +261 -0
  3. data/{LICENSE → MIT-LICENSE} +1 -1
  4. data/README +39 -0
  5. data/Rakefile +53 -62
  6. data/assets/app/helpers/annotation_security_helper.rb +8 -8
  7. data/assets/config/initializers/annotation_security.rb +11 -11
  8. data/assets/config/security/relations.rb +20 -20
  9. data/assets/vendor/plugins/annotation_security/init.rb +14 -14
  10. data/bin/annotation_security +7 -7
  11. data/lib/annotation_security.rb +94 -103
  12. data/lib/annotation_security/exceptions.rb +124 -124
  13. data/lib/annotation_security/exec.rb +188 -188
  14. data/lib/annotation_security/includes/helper.rb +215 -215
  15. data/lib/annotation_security/includes/resource.rb +84 -84
  16. data/lib/annotation_security/includes/role.rb +30 -30
  17. data/lib/annotation_security/includes/user.rb +26 -26
  18. data/lib/annotation_security/manager/policy_factory.rb +29 -29
  19. data/lib/annotation_security/manager/policy_manager.rb +87 -79
  20. data/lib/annotation_security/manager/relation_loader.rb +272 -272
  21. data/lib/annotation_security/manager/resource_manager.rb +36 -36
  22. data/lib/annotation_security/manager/right_loader.rb +87 -87
  23. data/lib/annotation_security/policy/abstract_policy.rb +344 -344
  24. data/lib/annotation_security/policy/abstract_static_policy.rb +75 -75
  25. data/lib/annotation_security/policy/all_resources_policy.rb +20 -20
  26. data/lib/annotation_security/policy/rule.rb +340 -340
  27. data/lib/annotation_security/policy/rule_set.rb +138 -138
  28. data/lib/annotation_security/rails.rb +22 -39
  29. data/lib/{extensions → annotation_security/rails/2/extensions}/filter.rb +131 -133
  30. data/lib/annotation_security/rails/2/includes/action_controller.rb +144 -0
  31. data/lib/annotation_security/rails/2/includes/active_record.rb +28 -0
  32. data/lib/annotation_security/rails/2/initializer.rb +35 -0
  33. data/lib/annotation_security/{model_observer.rb → rails/2/model_observer.rb} +61 -61
  34. data/lib/annotation_security/rails/3/extensions/filter.rb +28 -0
  35. data/lib/annotation_security/{includes → rails/3/includes}/action_controller.rb +143 -144
  36. data/lib/annotation_security/{includes → rails/3/includes}/active_record.rb +27 -27
  37. data/lib/annotation_security/rails/3/initializer.rb +40 -0
  38. data/lib/annotation_security/rails/3/model_observer.rb +61 -0
  39. data/lib/annotation_security/rails/extensions.rb +21 -0
  40. data/lib/{extensions → annotation_security/rails/extensions}/action_controller.rb +31 -32
  41. data/lib/{extensions → annotation_security/rails/extensions}/active_record.rb +33 -34
  42. data/lib/{extensions → annotation_security/rails/extensions}/object.rb +10 -10
  43. data/lib/annotation_security/{filters.rb → rails/filters.rb} +37 -37
  44. data/lib/annotation_security/user_wrapper.rb +73 -73
  45. data/lib/annotation_security/utils.rb +141 -141
  46. data/lib/security_context.rb +588 -589
  47. data/spec/annotation_security/exceptions_spec.rb +16 -16
  48. data/spec/annotation_security/includes/helper_spec.rb +82 -82
  49. data/spec/annotation_security/manager/policy_manager_spec.rb +15 -15
  50. data/spec/annotation_security/manager/resource_manager_spec.rb +17 -17
  51. data/spec/annotation_security/manager/right_loader_spec.rb +17 -17
  52. data/spec/annotation_security/policy/abstract_policy_spec.rb +16 -16
  53. data/spec/annotation_security/policy/all_resources_policy_spec.rb +24 -24
  54. data/spec/annotation_security/policy/rule_set_spec.rb +112 -112
  55. data/spec/annotation_security/policy/rule_spec.rb +77 -77
  56. data/spec/annotation_security/policy/test_policy_spec.rb +80 -80
  57. data/spec/annotation_security/security_context_spec.rb +129 -78
  58. data/spec/annotation_security/utils_spec.rb +73 -73
  59. data/spec/helper/test_controller.rb +65 -65
  60. data/spec/helper/test_helper.rb +5 -5
  61. data/spec/helper/test_relations.rb +6 -6
  62. data/spec/helper/test_resource.rb +38 -38
  63. data/spec/helper/test_role.rb +21 -21
  64. data/spec/helper/test_user.rb +31 -31
  65. data/spec/rails_stub.rb +44 -37
  66. metadata +110 -96
  67. data/CHANGELOG.md +0 -14
  68. data/HOW-TO.md +0 -275
  69. data/README.md +0 -39
  70. data/lib/annotation_security/version.rb +0 -10
@@ -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