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,125 +1,125 @@
1
- #
2
- # = lib/annotation_security/exceptions.rb
3
- #
4
- # Provides some Exceptions used within AnnotationSecurity
5
-
6
- module AnnotationSecurity
7
-
8
- # Superclass of all security related errors thrown by anno sec
9
- class SecurityError < StandardError # :nodoc:
10
- end
11
-
12
- end
13
-
14
- # Exception indicating that some rights were violated.
15
- #
16
- class SecurityViolationError < AnnotationSecurity::SecurityError
17
-
18
- def self.access_denied(user,*args) # :nodoc:
19
- new(user,*args)
20
- end
21
-
22
- def initialize(user=nil,*args) # :nodoc:
23
- if user == nil || args.empty?
24
- super "Access denied"
25
- else
26
- super load_args(user,args)
27
- end
28
- end
29
-
30
- def load_args(user,args) # :nodoc:
31
- @user = user
32
- @action,@resclass,@res = AnnotationSecurity::Utils.parse_policy_arguments(args)
33
- "You (#@user) are missing the right '#@action' for #@resclass" +
34
- (@res.blank? ? '' : " '#@res'")
35
- end
36
-
37
- # user that violated the right
38
- #
39
- def user
40
- @user
41
- end
42
-
43
- # the action that should have been performed on the resource object
44
- #
45
- def action
46
- @action
47
- end
48
-
49
- # the resource type
50
- #
51
- def resource_class
52
- @resclass
53
- end
54
-
55
- # the resource that was accessed
56
- #
57
- def resource
58
- @res
59
- end
60
- end
61
-
62
- module AnnotationSecurity
63
-
64
- # = AnnotationSecurity::RuleError
65
- #
66
- # Will be raised if a right or relation is defined twice
67
- # or has an invalid name.
68
- #
69
- class RuleError < SecurityError
70
- def self.defined_twice(type,rule) # :nodoc:
71
- new "The #{type} #{rule} is defined twice"
72
- end
73
-
74
- def self.forbidden_name(type,rule) # :nodoc:
75
- new "#{rule} is not allowed as #{type} name"
76
- end
77
- end
78
-
79
- # = AnnotationSecurity::RuleExecutionError
80
- #
81
- # Will be raised if an error occured while evaluation a right or relation.
82
- #
83
- class RuleExecutionError < RuleError
84
-
85
- def initialize(rule, proc=false, ex = nil) # :nodoc:
86
- if ex
87
- log_backtrace(proc,ex)
88
- super("An error occured while evaluating #{rule}: \n" +
89
- ex.class.name + ": " + ex.message)
90
- else
91
- super("An error occured while evaluating #{rule}")
92
- end
93
- end
94
-
95
- def set_backtrace(array) # :nodoc:
96
- super((@bt || []) + array[1..-1])
97
- end
98
-
99
- private
100
-
101
- # Select all lines of the backtrace above "rule.rb evaluate".
102
- # so they can be appended to the backtrace
103
- def log_backtrace(proc,ex)
104
- return unless proc
105
- backtrace = ex.backtrace
106
- stop = backtrace.find { |l| l =~ /rule\.rb(.*)`evaluate'/ }
107
- stop = backtrace.index(stop) || 5
108
- backtrace = backtrace.first(stop)
109
- @bt = backtrace.reject { |l| l =~ /annotation_security|active_support/ }
110
- end
111
-
112
- end
113
-
114
- # = AnnotationSecurity::RuleNotFoundError
115
- #
116
- # Will be raised when attempting to acces a right or relation that was not
117
- # defined.
118
- #
119
- class RuleNotFoundError < RuleError
120
- def self.for_rule(rname,policy_class)
121
- new("Unknown #{policy_class.static? ? 'static' : 'dynamic'} " +
122
- "rule '#{rname}' for #{policy_class.name}")
123
- end
124
- end
1
+ #
2
+ # = lib/annotation_security/exceptions.rb
3
+ #
4
+ # Provides some Exceptions used within AnnotationSecurity
5
+
6
+ module AnnotationSecurity
7
+
8
+ # Superclass of all security related errors thrown by anno sec
9
+ class SecurityError < StandardError # :nodoc:
10
+ end
11
+
12
+ end
13
+
14
+ # Exception indicating that some rights were violated.
15
+ #
16
+ class SecurityViolationError < AnnotationSecurity::SecurityError
17
+
18
+ def self.access_denied(user,*args) # :nodoc:
19
+ new(user,*args)
20
+ end
21
+
22
+ def initialize(user=nil,*args) # :nodoc:
23
+ if user == nil || args.empty?
24
+ super "Access denied"
25
+ else
26
+ super load_args(user,args)
27
+ end
28
+ end
29
+
30
+ def load_args(user,args) # :nodoc:
31
+ @user = user
32
+ @action,@resclass,@res = AnnotationSecurity::Utils.parse_policy_arguments(args)
33
+ "You (#@user) are missing the right '#@action' for #@resclass" +
34
+ (@res.blank? ? '' : " '#@res'")
35
+ end
36
+
37
+ # user that violated the right
38
+ #
39
+ def user
40
+ @user
41
+ end
42
+
43
+ # the action that should have been performed on the resource object
44
+ #
45
+ def action
46
+ @action
47
+ end
48
+
49
+ # the resource type
50
+ #
51
+ def resource_class
52
+ @resclass
53
+ end
54
+
55
+ # the resource that was accessed
56
+ #
57
+ def resource
58
+ @res
59
+ end
60
+ end
61
+
62
+ module AnnotationSecurity
63
+
64
+ # = AnnotationSecurity::RuleError
65
+ #
66
+ # Will be raised if a right or relation is defined twice
67
+ # or has an invalid name.
68
+ #
69
+ class RuleError < SecurityError
70
+ def self.defined_twice(type,rule) # :nodoc:
71
+ new "The #{type} #{rule} is defined twice"
72
+ end
73
+
74
+ def self.forbidden_name(type,rule) # :nodoc:
75
+ new "#{rule} is not allowed as #{type} name"
76
+ end
77
+ end
78
+
79
+ # = AnnotationSecurity::RuleExecutionError
80
+ #
81
+ # Will be raised if an error occured while evaluation a right or relation.
82
+ #
83
+ class RuleExecutionError < RuleError
84
+
85
+ def initialize(rule, proc=false, ex = nil) # :nodoc:
86
+ if ex
87
+ log_backtrace(proc,ex)
88
+ super("An error occured while evaluating #{rule}: \n" +
89
+ ex.class.name + ": " + ex.message)
90
+ else
91
+ super("An error occured while evaluating #{rule}")
92
+ end
93
+ end
94
+
95
+ def set_backtrace(array) # :nodoc:
96
+ super((@bt || []) + array[1..-1])
97
+ end
98
+
99
+ private
100
+
101
+ # Select all lines of the backtrace above "rule.rb evaluate".
102
+ # so they can be appended to the backtrace
103
+ def log_backtrace(proc,ex)
104
+ return unless proc
105
+ backtrace = ex.backtrace
106
+ stop = backtrace.find { |l| l =~ /rule\.rb(.*)`evaluate'/ }
107
+ stop = backtrace.index(stop) || 5
108
+ backtrace = backtrace.first(stop)
109
+ @bt = backtrace.reject { |l| l =~ /annotation_security|active_support/ }
110
+ end
111
+
112
+ end
113
+
114
+ # = AnnotationSecurity::RuleNotFoundError
115
+ #
116
+ # Will be raised when attempting to acces a right or relation that was not
117
+ # defined.
118
+ #
119
+ class RuleNotFoundError < RuleError
120
+ def self.for_rule(rname,policy_class)
121
+ new("Unknown #{policy_class.static? ? 'static' : 'dynamic'} " +
122
+ "rule '#{rname}' for #{policy_class.name}")
123
+ end
124
+ end
125
125
  end
@@ -1,189 +1,189 @@
1
- require 'optparse'
2
- require 'fileutils'
3
-
4
- # = lib/annotation_security/exec.rb
5
- # This file is borrowed heavily from HAML
6
- #
7
-
8
- module AnnotationSecurity
9
- module Exec # :nodoc:
10
-
11
- # An abstract class that encapsulates the executable
12
- # code for all executables.
13
- class Generic # :nodoc:
14
-
15
- # Parsed options
16
- def options
17
- @options ||= {}
18
- end
19
-
20
- # @param args [Array<String>] The command-line arguments
21
- def initialize(args)
22
- @args = args
23
- end
24
-
25
- # Parses the command-line arguments and runs the executable.
26
- # Calls `Kernel#exit` at the end, so it never returns.
27
- def parse!
28
- begin
29
- @opts = OptionParser.new(&method(:set_opts))
30
- @opts.parse!(@args)
31
-
32
- process_result
33
-
34
- options
35
- rescue Exception => e
36
- raise e if e.is_a?(SystemExit) || options[:trace]
37
-
38
- $stderr.puts e.message
39
- exit 1
40
- end
41
- exit 0
42
- end
43
-
44
- # @return [String] A description of the executable
45
- def to_s
46
- @opts.to_s
47
- end
48
-
49
- protected
50
-
51
- # Tells optparse how to parse the arguments
52
- # available for all executables.
53
- #
54
- # This is meant to be overridden by subclasses
55
- # so they can add their own options.
56
- #
57
- # @param opts [OptionParser]
58
- def set_opts(opts)
59
- opts.on("--force", "Force command execution, override assets without asking") do
60
- options[:force] = true
61
- end
62
-
63
- opts.on("--trace", "Shows full stack trace in case of errors") do
64
- options[:trace] = true
65
- end
66
-
67
- opts.on_tail("-?", "-h", "--help", "Show this message") do
68
- puts opts
69
- exit
70
- end
71
-
72
- opts.on_tail("-v", "--version", "Print version") do
73
- puts("AnnotationSecurity 0.01")
74
- exit
75
- end
76
- end
77
-
78
- # Processes the options set by the command-line arguments.
79
- #
80
- # This is meant to be overridden by subclasses
81
- # so they can run their respective programs.
82
- def process_result; end
83
- end
84
-
85
- # An abstrac class that encapsulates the code
86
- # specific to executables.
87
- class RailsInstaller < Generic # :nodoc:
88
-
89
- ASSET_FILES = %w{
90
- config/initializers/annotation_security.rb
91
- config/security/relations.rb
92
- config/security/rights.yml
93
- app/helpers/annotation_security_helper.rb
94
- vendor/plugins/annotation_security/init.rb
95
- }
96
-
97
- # @param args [Array<String>] The command-line arguments
98
- def initialize(args)
99
- super
100
- @name = "annosec"
101
- end
102
-
103
- protected
104
-
105
- # Tells optparse how to parse the arguments.
106
- #
107
- # This is meant to be overridden by subclasses
108
- # so they can add their own options.
109
- #
110
- # @param opts [OptionParser]
111
- def set_opts(opts)
112
- opts.banner = <<END
113
- Usage: #{@name.downcase} [options]
114
-
115
- Description:
116
- Installs the AnnotationSecurity layer into a rails app
117
-
118
- Options:
119
- END
120
-
121
- opts.on('--rails RAILS_DIR', "Install AnnotationSecurity layer from the Gem to a Rails project") do |dir|
122
- options[:rails_dir] = dir
123
- end
124
-
125
- super
126
- end
127
-
128
- # Processes the options set by the command-line arguments.
129
- # In particular, sets `@options[:for_engine][:filename]` to the input filename
130
- # and requires the appropriate file.
131
- #
132
- # This is meant to be overridden by subclasses
133
- # so they can run their respective programs.
134
- def process_result
135
-
136
- unless options[:rails_dir]
137
- puts @opts
138
- exit
139
- end
140
-
141
- options[:cur_dir] = File.dirname(__FILE__)
142
- options[:assets_dir] = File.join(options[:cur_dir], '..', '..', 'assets')
143
-
144
- assert_exists('config')
145
- assert_exists('vendor')
146
- assert_exists('app/helpers')
147
-
148
- ASSET_FILES.each { |f| install_file(f) }
149
-
150
- puts "AnnotationSecurity plugin added to #{options[:rails_dir]}"
151
- exit
152
- end
153
-
154
- private
155
-
156
- def assert_exists(dir)
157
- dir = File.join(options[:rails_dir], dir)
158
- unless File.exists?(dir)
159
- if options[:force]
160
- puts "Creating #{dir}"
161
- FileUtils.mkdir_p dir
162
- else
163
- puts "Directory #{dir} does not exist"
164
- exit
165
- end
166
- end
167
- end
168
-
169
- def install_file(f)
170
- orign = File.join(options[:assets_dir], f)
171
- dest = File.join(options[:rails_dir], f)
172
-
173
- if File.exists?(dest) && !options[:force]
174
- print "File #{dest} already exists, overwrite [y/N]? "
175
- return if gets !~ /y/i
176
- end
177
-
178
- dir = File.dirname(dest)
179
- unless File.exists?(dir)
180
- puts "Creating #{dir}"
181
- FileUtils.mkdir_p(dir)
182
- end
183
-
184
- FileUtils.install(orign, dest)
185
- puts "Installed #{dest}"
186
- end
187
- end
188
- end
1
+ require 'optparse'
2
+ require 'fileutils'
3
+
4
+ # = lib/annotation_security/exec.rb
5
+ # This file is borrowed heavily from HAML
6
+ #
7
+
8
+ module AnnotationSecurity
9
+ module Exec # :nodoc:
10
+
11
+ # An abstract class that encapsulates the executable
12
+ # code for all executables.
13
+ class Generic # :nodoc:
14
+
15
+ # Parsed options
16
+ def options
17
+ @options ||= {}
18
+ end
19
+
20
+ # @param args [Array<String>] The command-line arguments
21
+ def initialize(args)
22
+ @args = args
23
+ end
24
+
25
+ # Parses the command-line arguments and runs the executable.
26
+ # Calls `Kernel#exit` at the end, so it never returns.
27
+ def parse!
28
+ begin
29
+ @opts = OptionParser.new(&method(:set_opts))
30
+ @opts.parse!(@args)
31
+
32
+ process_result
33
+
34
+ options
35
+ rescue Exception => e
36
+ raise e if e.is_a?(SystemExit) || options[:trace]
37
+
38
+ $stderr.puts e.message
39
+ exit 1
40
+ end
41
+ exit 0
42
+ end
43
+
44
+ # @return [String] A description of the executable
45
+ def to_s
46
+ @opts.to_s
47
+ end
48
+
49
+ protected
50
+
51
+ # Tells optparse how to parse the arguments
52
+ # available for all executables.
53
+ #
54
+ # This is meant to be overridden by subclasses
55
+ # so they can add their own options.
56
+ #
57
+ # @param opts [OptionParser]
58
+ def set_opts(opts)
59
+ opts.on("--force", "Force command execution, override assets without asking") do
60
+ options[:force] = true
61
+ end
62
+
63
+ opts.on("--trace", "Shows full stack trace in case of errors") do
64
+ options[:trace] = true
65
+ end
66
+
67
+ opts.on_tail("-?", "-h", "--help", "Show this message") do
68
+ puts opts
69
+ exit
70
+ end
71
+
72
+ opts.on_tail("-v", "--version", "Print version") do
73
+ puts("AnnotationSecurity 0.01")
74
+ exit
75
+ end
76
+ end
77
+
78
+ # Processes the options set by the command-line arguments.
79
+ #
80
+ # This is meant to be overridden by subclasses
81
+ # so they can run their respective programs.
82
+ def process_result; end
83
+ end
84
+
85
+ # An abstrac class that encapsulates the code
86
+ # specific to executables.
87
+ class RailsInstaller < Generic # :nodoc:
88
+
89
+ ASSET_FILES = %w{
90
+ config/initializers/annotation_security.rb
91
+ config/security/relations.rb
92
+ config/security/rights.yml
93
+ app/helpers/annotation_security_helper.rb
94
+ vendor/plugins/annotation_security/init.rb
95
+ }
96
+
97
+ # @param args [Array<String>] The command-line arguments
98
+ def initialize(args)
99
+ super
100
+ @name = "annosec"
101
+ end
102
+
103
+ protected
104
+
105
+ # Tells optparse how to parse the arguments.
106
+ #
107
+ # This is meant to be overridden by subclasses
108
+ # so they can add their own options.
109
+ #
110
+ # @param opts [OptionParser]
111
+ def set_opts(opts)
112
+ opts.banner = <<END
113
+ Usage: #{@name.downcase} [options]
114
+
115
+ Description:
116
+ Installs the AnnotationSecurity layer into a rails app
117
+
118
+ Options:
119
+ END
120
+
121
+ opts.on('--rails RAILS_DIR', "Install AnnotationSecurity layer from the Gem to a Rails project") do |dir|
122
+ options[:rails_dir] = dir
123
+ end
124
+
125
+ super
126
+ end
127
+
128
+ # Processes the options set by the command-line arguments.
129
+ # In particular, sets `@options[:for_engine][:filename]` to the input filename
130
+ # and requires the appropriate file.
131
+ #
132
+ # This is meant to be overridden by subclasses
133
+ # so they can run their respective programs.
134
+ def process_result
135
+
136
+ unless options[:rails_dir]
137
+ puts @opts
138
+ exit
139
+ end
140
+
141
+ options[:cur_dir] = File.dirname(__FILE__)
142
+ options[:assets_dir] = File.join(options[:cur_dir], '..', '..', 'assets')
143
+
144
+ assert_exists('config')
145
+ assert_exists('vendor')
146
+ assert_exists('app/helpers')
147
+
148
+ ASSET_FILES.each { |f| install_file(f) }
149
+
150
+ puts "AnnotationSecurity plugin added to #{options[:rails_dir]}"
151
+ exit
152
+ end
153
+
154
+ private
155
+
156
+ def assert_exists(dir)
157
+ dir = File.join(options[:rails_dir], dir)
158
+ unless File.exists?(dir)
159
+ if options[:force]
160
+ puts "Creating #{dir}"
161
+ FileUtils.mkdir_p dir
162
+ else
163
+ puts "Directory #{dir} does not exist"
164
+ exit
165
+ end
166
+ end
167
+ end
168
+
169
+ def install_file(f)
170
+ orign = File.join(options[:assets_dir], f)
171
+ dest = File.join(options[:rails_dir], f)
172
+
173
+ if File.exists?(dest) && !options[:force]
174
+ print "File #{dest} already exists, overwrite [y/N]? "
175
+ return if gets !~ /y/i
176
+ end
177
+
178
+ dir = File.dirname(dest)
179
+ unless File.exists?(dir)
180
+ puts "Creating #{dir}"
181
+ FileUtils.mkdir_p(dir)
182
+ end
183
+
184
+ FileUtils.install(orign, dest)
185
+ puts "Installed #{dest}"
186
+ end
187
+ end
188
+ end
189
189
  end