annotation_security 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/CHANGELOG.md +14 -0
  2. data/HOW-TO.md +275 -0
  3. data/{MIT-LICENSE → LICENSE} +1 -1
  4. data/README.md +39 -0
  5. data/Rakefile +62 -55
  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 +13 -13
  10. data/bin/annotation_security +7 -7
  11. data/lib/annotation_security/exceptions.rb +124 -124
  12. data/lib/annotation_security/exec.rb +188 -188
  13. data/lib/annotation_security/filters.rb +37 -37
  14. data/lib/annotation_security/includes/action_controller.rb +144 -143
  15. data/lib/annotation_security/includes/active_record.rb +27 -27
  16. data/lib/annotation_security/includes/helper.rb +215 -215
  17. data/lib/annotation_security/includes/resource.rb +84 -84
  18. data/lib/annotation_security/includes/role.rb +30 -30
  19. data/lib/annotation_security/includes/user.rb +26 -26
  20. data/lib/annotation_security/manager/policy_factory.rb +29 -29
  21. data/lib/annotation_security/manager/policy_manager.rb +79 -79
  22. data/lib/annotation_security/manager/relation_loader.rb +272 -272
  23. data/lib/annotation_security/manager/resource_manager.rb +36 -36
  24. data/lib/annotation_security/manager/right_loader.rb +87 -87
  25. data/lib/annotation_security/model_observer.rb +61 -61
  26. data/lib/annotation_security/policy/abstract_policy.rb +344 -344
  27. data/lib/annotation_security/policy/abstract_static_policy.rb +75 -75
  28. data/lib/annotation_security/policy/all_resources_policy.rb +20 -20
  29. data/lib/annotation_security/policy/rule.rb +340 -340
  30. data/lib/annotation_security/policy/rule_set.rb +138 -138
  31. data/lib/annotation_security/rails.rb +38 -38
  32. data/lib/annotation_security/user_wrapper.rb +73 -73
  33. data/lib/annotation_security/utils.rb +141 -141
  34. data/lib/annotation_security/version.rb +10 -0
  35. data/lib/annotation_security.rb +102 -97
  36. data/lib/extensions/action_controller.rb +32 -32
  37. data/lib/extensions/active_record.rb +34 -34
  38. data/lib/extensions/filter.rb +133 -133
  39. data/lib/extensions/object.rb +10 -10
  40. data/lib/security_context.rb +589 -551
  41. data/spec/annotation_security/exceptions_spec.rb +16 -16
  42. data/spec/annotation_security/includes/helper_spec.rb +82 -82
  43. data/spec/annotation_security/manager/policy_manager_spec.rb +15 -15
  44. data/spec/annotation_security/manager/resource_manager_spec.rb +17 -17
  45. data/spec/annotation_security/manager/right_loader_spec.rb +17 -17
  46. data/spec/annotation_security/policy/abstract_policy_spec.rb +16 -16
  47. data/spec/annotation_security/policy/all_resources_policy_spec.rb +24 -24
  48. data/spec/annotation_security/policy/rule_set_spec.rb +112 -112
  49. data/spec/annotation_security/policy/rule_spec.rb +77 -77
  50. data/spec/annotation_security/policy/test_policy_spec.rb +80 -80
  51. data/spec/annotation_security/security_context_spec.rb +78 -78
  52. data/spec/annotation_security/utils_spec.rb +73 -73
  53. data/spec/helper/test_controller.rb +65 -65
  54. data/spec/helper/test_helper.rb +5 -5
  55. data/spec/helper/test_relations.rb +6 -6
  56. data/spec/helper/test_resource.rb +38 -38
  57. data/spec/helper/test_role.rb +21 -21
  58. data/spec/helper/test_user.rb +31 -31
  59. data/spec/rails_stub.rb +37 -37
  60. metadata +94 -72
  61. data/CHANGELOG +0 -2
  62. data/HOW-TO +0 -261
  63. data/README +0 -39
@@ -1,139 +1,139 @@
1
- #
2
- # = lib/annotation_security/policy/rule_set.rb
3
- #
4
-
5
- # = AnnotationSecurity::RuleSet
6
- # Contains all rule objects for a policy
7
- #
8
- class AnnotationSecurity::RuleSet # :nodoc:
9
-
10
- # Initializes the rule set
11
- # * +pclass+ Policy class this rule set belongs to
12
- #
13
- def initialize(pclass)
14
- super()
15
- @pclass = pclass
16
- @rights = {}
17
- @static = {}
18
- @dynamic = {}
19
- end
20
-
21
- def to_s
22
- "<RuleSet of #@pclass>"
23
- end
24
-
25
- # Returns a rule object or nil if the rule does not exist.
26
- # * +symbol+ name of the rule
27
- # * +static+ boolean specifing whether the rule is static or dynamic
28
- def get_rule(symbol,static)
29
- static ? get_static_rule(symbol) : get_dynamic_rule(symbol)
30
- end
31
-
32
- # Returns a dynamic rule or nil if the rule does not exist.
33
- # * +symbol+ name of the rule
34
- def get_dynamic_rule(symbol)
35
- # If no rule is available, maybe there is a right that can be used
36
- @dynamic[symbol] ||= get_dynamic_right(symbol)
37
- end
38
-
39
- # Returns a static rule or nil if the rule does not exist.
40
- # * +symbol+ name of the rule
41
- def get_static_rule(symbol)
42
- # If no rule is available, maybe there is a right that can be used
43
- @static[symbol] ||= get_static_right(symbol)
44
- end
45
-
46
- # Copies a rule from another rule set.
47
- # Returns the newly created rule or nil if the operation had no effect.
48
- # * +symbol+ name of the rule
49
- # * +source+ rule set to copy from
50
- # * +static+ boolean specifing whether the rule is static or dynamic
51
- def copy_rule_from(symbol,source,static)
52
- add_copy(source.get_rule(symbol,static))
53
- end
54
-
55
- # Creates a dynamic rule that redirects to a static rule with the same name.
56
- # Returns the newly created rule or nil if the operation had no effect.
57
- # * +symbol+ name of the rule
58
- def create_dynamic_copy(symbol)
59
- rule = get_static_rule(symbol)
60
- if rule
61
- add_rule(symbol,
62
- "static_policy.#{symbol}(*args)",
63
- :resource,
64
- :require_credential => rule.requires_credential?)
65
- end
66
- end
67
-
68
- # Adds a new rule to this rule set. The rule will be classified either
69
- # as dynamic, static, both or right.
70
- # Returns the newly create rule.
71
- # For an explainition of the parameters see AnnotationSecurity::Rule#initialize.
72
- def add_rule(symbol,*args,&block)
73
- __add__ AnnotationSecurity::Rule.new(symbol,@pclass,*args,&block)
74
- end
75
-
76
- private
77
-
78
- # Copies a rule object to this rule set.
79
- # Returns the newly created rule or nil.
80
- # * +rule+ rule object to copy or nil.
81
- def add_copy(rule)
82
- __add__(rule.copy(@pclass)) if rule
83
- end
84
-
85
- # Adds a new rule to this rule set. The rule will be classified either
86
- # as dynamic, static, both or right.
87
- # * +rule+ rule object
88
- def __add__(rule)
89
- if rule.right?
90
- # if the rule is a right, its not clear yet whether
91
- # it is static or dynamic. These rules will be analyzed later.
92
- raise_if_forbidden_name 'right', rule
93
- raise_if_exists 'right', @rights[rule.name]
94
- @rights[rule.name] = rule
95
- else
96
- raise_if_forbidden_name 'relation', rule
97
- if rule.dynamic?
98
- raise_if_exists 'dynamic relation', @dynamic[rule.name]
99
- @dynamic[rule.name] = rule
100
- end
101
- if rule.static?
102
- raise_if_exists 'static relation', @static[rule.name]
103
- @static[rule.name] = rule
104
- end
105
- end
106
- rule
107
- end
108
-
109
- # Raises an error if +rule+ is not nil.
110
- # * +type+ type of rule, like 'right' or 'dynamic relation'
111
- # * +rule+ existing rule object or nil
112
- def raise_if_exists(type,rule)
113
- raise AnnotationSecurity::RuleError.defined_twice(type,rule) if rule
114
- end
115
-
116
- # Raises an error if +rule+ has a forbidden name.
117
- # * +type+ type of rule, like 'right' or 'relation'
118
- # * +rule+ rule object
119
- def raise_if_forbidden_name(type,rule)
120
- if AnnotationSecurity::AbstractPolicy.forbidden_rule_names.include? rule.name.to_s
121
- raise AnnotationSecurity::RuleError.forbidden_name(type,rule)
122
- end
123
- end
124
-
125
- # Returns a dynamic rule that was defined as right
126
- # * +symbol+ name of the rule
127
- def get_dynamic_right(symbol)
128
- r = @rights[symbol]
129
- r and r.dynamic? ? r : nil
130
- end
131
-
132
- # Returns a static rule that was defined as right
133
- # * +symbol+ name of the rule
134
- def get_static_right(symbol)
135
- r = @rights[symbol]
136
- r and r.static? ? r : nil
137
- end
138
-
1
+ #
2
+ # = lib/annotation_security/policy/rule_set.rb
3
+ #
4
+
5
+ # = AnnotationSecurity::RuleSet
6
+ # Contains all rule objects for a policy
7
+ #
8
+ class AnnotationSecurity::RuleSet # :nodoc:
9
+
10
+ # Initializes the rule set
11
+ # * +pclass+ Policy class this rule set belongs to
12
+ #
13
+ def initialize(pclass)
14
+ super()
15
+ @pclass = pclass
16
+ @rights = {}
17
+ @static = {}
18
+ @dynamic = {}
19
+ end
20
+
21
+ def to_s
22
+ "<RuleSet of #@pclass>"
23
+ end
24
+
25
+ # Returns a rule object or nil if the rule does not exist.
26
+ # * +symbol+ name of the rule
27
+ # * +static+ boolean specifing whether the rule is static or dynamic
28
+ def get_rule(symbol,static)
29
+ static ? get_static_rule(symbol) : get_dynamic_rule(symbol)
30
+ end
31
+
32
+ # Returns a dynamic rule or nil if the rule does not exist.
33
+ # * +symbol+ name of the rule
34
+ def get_dynamic_rule(symbol)
35
+ # If no rule is available, maybe there is a right that can be used
36
+ @dynamic[symbol] ||= get_dynamic_right(symbol)
37
+ end
38
+
39
+ # Returns a static rule or nil if the rule does not exist.
40
+ # * +symbol+ name of the rule
41
+ def get_static_rule(symbol)
42
+ # If no rule is available, maybe there is a right that can be used
43
+ @static[symbol] ||= get_static_right(symbol)
44
+ end
45
+
46
+ # Copies a rule from another rule set.
47
+ # Returns the newly created rule or nil if the operation had no effect.
48
+ # * +symbol+ name of the rule
49
+ # * +source+ rule set to copy from
50
+ # * +static+ boolean specifing whether the rule is static or dynamic
51
+ def copy_rule_from(symbol,source,static)
52
+ add_copy(source.get_rule(symbol,static))
53
+ end
54
+
55
+ # Creates a dynamic rule that redirects to a static rule with the same name.
56
+ # Returns the newly created rule or nil if the operation had no effect.
57
+ # * +symbol+ name of the rule
58
+ def create_dynamic_copy(symbol)
59
+ rule = get_static_rule(symbol)
60
+ if rule
61
+ add_rule(symbol,
62
+ "static_policy.#{symbol}(*args)",
63
+ :resource,
64
+ :require_credential => rule.requires_credential?)
65
+ end
66
+ end
67
+
68
+ # Adds a new rule to this rule set. The rule will be classified either
69
+ # as dynamic, static, both or right.
70
+ # Returns the newly create rule.
71
+ # For an explainition of the parameters see AnnotationSecurity::Rule#initialize.
72
+ def add_rule(symbol,*args,&block)
73
+ __add__ AnnotationSecurity::Rule.new(symbol,@pclass,*args,&block)
74
+ end
75
+
76
+ private
77
+
78
+ # Copies a rule object to this rule set.
79
+ # Returns the newly created rule or nil.
80
+ # * +rule+ rule object to copy or nil.
81
+ def add_copy(rule)
82
+ __add__(rule.copy(@pclass)) if rule
83
+ end
84
+
85
+ # Adds a new rule to this rule set. The rule will be classified either
86
+ # as dynamic, static, both or right.
87
+ # * +rule+ rule object
88
+ def __add__(rule)
89
+ if rule.right?
90
+ # if the rule is a right, its not clear yet whether
91
+ # it is static or dynamic. These rules will be analyzed later.
92
+ raise_if_forbidden_name 'right', rule
93
+ raise_if_exists 'right', @rights[rule.name]
94
+ @rights[rule.name] = rule
95
+ else
96
+ raise_if_forbidden_name 'relation', rule
97
+ if rule.dynamic?
98
+ raise_if_exists 'dynamic relation', @dynamic[rule.name]
99
+ @dynamic[rule.name] = rule
100
+ end
101
+ if rule.static?
102
+ raise_if_exists 'static relation', @static[rule.name]
103
+ @static[rule.name] = rule
104
+ end
105
+ end
106
+ rule
107
+ end
108
+
109
+ # Raises an error if +rule+ is not nil.
110
+ # * +type+ type of rule, like 'right' or 'dynamic relation'
111
+ # * +rule+ existing rule object or nil
112
+ def raise_if_exists(type,rule)
113
+ raise AnnotationSecurity::RuleError.defined_twice(type,rule) if rule
114
+ end
115
+
116
+ # Raises an error if +rule+ has a forbidden name.
117
+ # * +type+ type of rule, like 'right' or 'relation'
118
+ # * +rule+ rule object
119
+ def raise_if_forbidden_name(type,rule)
120
+ if AnnotationSecurity::AbstractPolicy.forbidden_rule_names.include? rule.name.to_s
121
+ raise AnnotationSecurity::RuleError.forbidden_name(type,rule)
122
+ end
123
+ end
124
+
125
+ # Returns a dynamic rule that was defined as right
126
+ # * +symbol+ name of the rule
127
+ def get_dynamic_right(symbol)
128
+ r = @rights[symbol]
129
+ r and r.dynamic? ? r : nil
130
+ end
131
+
132
+ # Returns a static rule that was defined as right
133
+ # * +symbol+ name of the rule
134
+ def get_static_right(symbol)
135
+ r = @rights[symbol]
136
+ r and r.static? ? r : nil
137
+ end
138
+
139
139
  end
@@ -1,39 +1,39 @@
1
- #
2
- # = annotation_security/rails/init.rb
3
- #
4
- # Loads the annotation security layer for a rails app
5
-
6
- require "action_controller/dispatcher"
7
- require "action_controller/base"
8
-
9
- module AnnotationSecurity
10
-
11
- # Contains rails specific initializer
12
- class Rails
13
- def self.init!(config)
14
-
15
- # Policy files are situated under RAILS_ROOT/config/security
16
- # Default policy file is internal, load it
17
- ::AnnotationSecurity.load_relations(File.dirname(__FILE__) + '/policy/all_resources_policy')
18
-
19
- # Add AnnotationSecurity::ModelObserver to observe changes in models.
20
- # See http://riotprojects.com/2009/1/18/active-record-observers-in-gems-plugins
21
- #
22
- config.after_initialize do
23
- # Set up a dummy security context that does not interfer with script
24
- ::SecurityContext.initialize nil
25
-
26
- ::ActiveRecord::Base.observers << ::AnnotationSecurity::ModelObserver
27
-
28
- # In development mode, the models we observe get reloaded with each request. Using
29
- # this hook allows us to reload the observer relationships each time as well.
30
- ::ActionController::Dispatcher.to_prepare(:cache_advance_reload) do
31
- ::AnnotationSecurity.reset
32
- ::AnnotationSecurity::ModelObserver.instance.reload_model_observer
33
- end
34
- end
35
-
36
- puts "Security layer initialized"
37
- end
38
- end
1
+ #
2
+ # = annotation_security/rails/init.rb
3
+ #
4
+ # Loads the annotation security layer for a rails app
5
+
6
+ require "action_controller/dispatcher"
7
+ require "action_controller/base"
8
+
9
+ module AnnotationSecurity
10
+
11
+ # Contains rails specific initializer
12
+ class Rails
13
+ def self.init!(config)
14
+
15
+ # Policy files are situated under RAILS_ROOT/config/security
16
+ # Default policy file is internal, load it
17
+ ::AnnotationSecurity.load_relations(File.dirname(__FILE__) + '/policy/all_resources_policy')
18
+
19
+ # Add AnnotationSecurity::ModelObserver to observe changes in models.
20
+ # See http://riotprojects.com/2009/1/18/active-record-observers-in-gems-plugins
21
+ #
22
+ config.after_initialize do
23
+ # Set up a dummy security context that does not interfer with script
24
+ ::SecurityContext.initialize nil
25
+
26
+ ::ActiveRecord::Base.observers << ::AnnotationSecurity::ModelObserver
27
+
28
+ # In development mode, the models we observe get reloaded with each request. Using
29
+ # this hook allows us to reload the observer relationships each time as well.
30
+ ::ActionController::Dispatcher.to_prepare(:cache_advance_reload) do
31
+ ::AnnotationSecurity.reset
32
+ ::AnnotationSecurity::ModelObserver.instance.reload_model_observer
33
+ end
34
+ end
35
+
36
+ puts "Security layer initialized"
37
+ end
38
+ end
39
39
  end
@@ -1,74 +1,74 @@
1
- #
2
- # = lib/annotation_security/user_wrapper.rb
3
- #
4
-
5
- # = AnnotationSecurity::UserWrapper
6
- #
7
- # This class is not in use!
8
- #
9
- # Needed for evaluating relations, especially if the :as-option is used.
10
- #
11
- # Merges a user and a role. If a role is given,
12
- #
13
- class AnnotationSecurity::UserWrapper # :nodoc:
14
-
15
- # Return user wrappers for the requested role. The role(s) will be
16
- # determined with sending user.as_'role'.
17
- # (Normally a user has a role only once, however it will work when he
18
- # has many roles of the same kind as well)
19
- def self.all_for_role(user,role_name)
20
- return [] if user.nil?
21
- user = user.__user__ if user.is_a? AnnotationSecurity::UserWrapper
22
- return [new(user)] if role_name.nil?
23
- roles = user.__send__("as_#{role_name}")
24
- return [] if roles.blank?
25
- roles = [roles] unless roles.is_a?(Array)
26
- roles.compact.collect { |role| new(user,role) }
27
- end
28
-
29
- def initialize(user,role=nil)
30
- @user = user
31
- @role = role
32
- end
33
-
34
- def id
35
- @role? @role.id : @user.id
36
- end
37
-
38
- def __user__
39
- @user
40
- end
41
-
42
- def __role__
43
- @role
44
- end
45
-
46
- def ==(obj)
47
- @user == obj or (!@role.nil? and @role == obj)
48
- end
49
-
50
- # Try to send to role, user and policy of args[0]
51
- #
52
- def method_missing(symbol,*args,&block)
53
- if @role && (@role.respond_to? symbol)
54
- @role.__send__(symbol,*args,&block)
55
- elsif @user.respond_to? symbol
56
- @user.__send__(symbol,*args,&block)
57
- elsif args.first.respond_to? :policy_for
58
- args.first.policy_for(@user).__send__(symbol,*args[1..-1])
59
- else
60
- # This will raise a NoMethodError
61
- @user.__send__(symbol,*args,&block)
62
- end
63
- end
64
-
65
- def is_a?(klass)
66
- return true if super(klass)
67
- if @role
68
- @role.is_a?(klass)
69
- else
70
- @user.is_a?(klass)
71
- end
72
- end
73
-
1
+ #
2
+ # = lib/annotation_security/user_wrapper.rb
3
+ #
4
+
5
+ # = AnnotationSecurity::UserWrapper
6
+ #
7
+ # This class is not in use!
8
+ #
9
+ # Needed for evaluating relations, especially if the :as-option is used.
10
+ #
11
+ # Merges a user and a role. If a role is given,
12
+ #
13
+ class AnnotationSecurity::UserWrapper # :nodoc:
14
+
15
+ # Return user wrappers for the requested role. The role(s) will be
16
+ # determined with sending user.as_'role'.
17
+ # (Normally a user has a role only once, however it will work when he
18
+ # has many roles of the same kind as well)
19
+ def self.all_for_role(user,role_name)
20
+ return [] if user.nil?
21
+ user = user.__user__ if user.is_a? AnnotationSecurity::UserWrapper
22
+ return [new(user)] if role_name.nil?
23
+ roles = user.__send__("as_#{role_name}")
24
+ return [] if roles.blank?
25
+ roles = [roles] unless roles.is_a?(Array)
26
+ roles.compact.collect { |role| new(user,role) }
27
+ end
28
+
29
+ def initialize(user,role=nil)
30
+ @user = user
31
+ @role = role
32
+ end
33
+
34
+ def id
35
+ @role? @role.id : @user.id
36
+ end
37
+
38
+ def __user__
39
+ @user
40
+ end
41
+
42
+ def __role__
43
+ @role
44
+ end
45
+
46
+ def ==(obj)
47
+ @user == obj or (!@role.nil? and @role == obj)
48
+ end
49
+
50
+ # Try to send to role, user and policy of args[0]
51
+ #
52
+ def method_missing(symbol,*args,&block)
53
+ if @role && (@role.respond_to? symbol)
54
+ @role.__send__(symbol,*args,&block)
55
+ elsif @user.respond_to? symbol
56
+ @user.__send__(symbol,*args,&block)
57
+ elsif args.first.respond_to? :policy_for
58
+ args.first.policy_for(@user).__send__(symbol,*args[1..-1])
59
+ else
60
+ # This will raise a NoMethodError
61
+ @user.__send__(symbol,*args,&block)
62
+ end
63
+ end
64
+
65
+ def is_a?(klass)
66
+ return true if super(klass)
67
+ if @role
68
+ @role.is_a?(klass)
69
+ else
70
+ @user.is_a?(klass)
71
+ end
72
+ end
73
+
74
74
  end