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.
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