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