annotation_security 1.0.2 → 1.3.1
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.
- data/CHANGELOG +22 -0
- data/HOW-TO +261 -0
- data/{LICENSE → MIT-LICENSE} +1 -1
- data/README +39 -0
- data/Rakefile +53 -62
- data/assets/app/helpers/annotation_security_helper.rb +8 -8
- data/assets/config/initializers/annotation_security.rb +11 -11
- data/assets/config/security/relations.rb +20 -20
- data/assets/vendor/plugins/annotation_security/init.rb +14 -14
- data/bin/annotation_security +7 -7
- data/lib/annotation_security.rb +94 -103
- data/lib/annotation_security/exceptions.rb +124 -124
- data/lib/annotation_security/exec.rb +188 -188
- data/lib/annotation_security/includes/helper.rb +215 -215
- data/lib/annotation_security/includes/resource.rb +84 -84
- data/lib/annotation_security/includes/role.rb +30 -30
- data/lib/annotation_security/includes/user.rb +26 -26
- data/lib/annotation_security/manager/policy_factory.rb +29 -29
- data/lib/annotation_security/manager/policy_manager.rb +87 -79
- data/lib/annotation_security/manager/relation_loader.rb +272 -272
- data/lib/annotation_security/manager/resource_manager.rb +36 -36
- data/lib/annotation_security/manager/right_loader.rb +87 -87
- data/lib/annotation_security/policy/abstract_policy.rb +344 -344
- data/lib/annotation_security/policy/abstract_static_policy.rb +75 -75
- data/lib/annotation_security/policy/all_resources_policy.rb +20 -20
- data/lib/annotation_security/policy/rule.rb +340 -340
- data/lib/annotation_security/policy/rule_set.rb +138 -138
- data/lib/annotation_security/rails.rb +22 -39
- data/lib/{extensions → annotation_security/rails/2/extensions}/filter.rb +131 -133
- data/lib/annotation_security/rails/2/includes/action_controller.rb +144 -0
- data/lib/annotation_security/rails/2/includes/active_record.rb +28 -0
- data/lib/annotation_security/rails/2/initializer.rb +35 -0
- data/lib/annotation_security/{model_observer.rb → rails/2/model_observer.rb} +61 -61
- data/lib/annotation_security/rails/3/extensions/filter.rb +28 -0
- data/lib/annotation_security/{includes → rails/3/includes}/action_controller.rb +143 -144
- data/lib/annotation_security/{includes → rails/3/includes}/active_record.rb +27 -27
- data/lib/annotation_security/rails/3/initializer.rb +40 -0
- data/lib/annotation_security/rails/3/model_observer.rb +61 -0
- data/lib/annotation_security/rails/extensions.rb +21 -0
- data/lib/{extensions → annotation_security/rails/extensions}/action_controller.rb +31 -32
- data/lib/{extensions → annotation_security/rails/extensions}/active_record.rb +33 -34
- data/lib/{extensions → annotation_security/rails/extensions}/object.rb +10 -10
- data/lib/annotation_security/{filters.rb → rails/filters.rb} +37 -37
- data/lib/annotation_security/user_wrapper.rb +73 -73
- data/lib/annotation_security/utils.rb +141 -141
- data/lib/security_context.rb +588 -589
- data/spec/annotation_security/exceptions_spec.rb +16 -16
- data/spec/annotation_security/includes/helper_spec.rb +82 -82
- data/spec/annotation_security/manager/policy_manager_spec.rb +15 -15
- data/spec/annotation_security/manager/resource_manager_spec.rb +17 -17
- data/spec/annotation_security/manager/right_loader_spec.rb +17 -17
- data/spec/annotation_security/policy/abstract_policy_spec.rb +16 -16
- data/spec/annotation_security/policy/all_resources_policy_spec.rb +24 -24
- data/spec/annotation_security/policy/rule_set_spec.rb +112 -112
- data/spec/annotation_security/policy/rule_spec.rb +77 -77
- data/spec/annotation_security/policy/test_policy_spec.rb +80 -80
- data/spec/annotation_security/security_context_spec.rb +129 -78
- data/spec/annotation_security/utils_spec.rb +73 -73
- data/spec/helper/test_controller.rb +65 -65
- data/spec/helper/test_helper.rb +5 -5
- data/spec/helper/test_relations.rb +6 -6
- data/spec/helper/test_resource.rb +38 -38
- data/spec/helper/test_role.rb +21 -21
- data/spec/helper/test_user.rb +31 -31
- data/spec/rails_stub.rb +44 -37
- metadata +110 -96
- data/CHANGELOG.md +0 -14
- data/HOW-TO.md +0 -275
- data/README.md +0 -39
- data/lib/annotation_security/version.rb +0 -10
@@ -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.
|
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 1.0.3")
|
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
|
@@ -1,215 +1,215 @@
|
|
1
|
-
#
|
2
|
-
# = lib/annotation_security/includes/helper.rb
|
3
|
-
#
|
4
|
-
|
5
|
-
# = AnnotationSecurity::Helper
|
6
|
-
#
|
7
|
-
# This module adds some useful helper methods to your templates.
|
8
|
-
#
|
9
|
-
module AnnotationSecurity::Helper
|
10
|
-
|
11
|
-
# Returns true if the operation defined by +policy_args+ is allowed.
|
12
|
-
#
|
13
|
-
# The following calls to #allowed? are possible:
|
14
|
-
#
|
15
|
-
# allowed? :show, :resource, @resource
|
16
|
-
# # => true if the current user has the right to show @resource,
|
17
|
-
# # which belongs to the :resource resource-class
|
18
|
-
#
|
19
|
-
# In case of model objects or other classes which implement a #resource_type
|
20
|
-
# method the the second argument may be ommited
|
21
|
-
#
|
22
|
-
# allowed? :show, @resource
|
23
|
-
# # equivalent to the above call if @resource.resource_type == :resource
|
24
|
-
#
|
25
|
-
# A policy description used as a controller annotation may also be used
|
26
|
-
# to check a right
|
27
|
-
#
|
28
|
-
# allowed? "show resource", @resource
|
29
|
-
# # => true if the current user has the right "show resource" for @resource
|
30
|
-
#
|
31
|
-
# A policy may also be applied without an object representing the context:
|
32
|
-
#
|
33
|
-
# allowed? :show, :resource
|
34
|
-
# # => true if the current may show resources.
|
35
|
-
#
|
36
|
-
# This will only check system and pretest rules. The result +true+ does not
|
37
|
-
# mean that the user may show all resources. However, a +false+ indicates
|
38
|
-
# that the user is not allowed to show any resources.
|
39
|
-
#
|
40
|
-
# If the resource class is omitted as well, only rules defined for all
|
41
|
-
# resources can be tested. See RelationLoader#all_resources for details.
|
42
|
-
#
|
43
|
-
# allowed? :administrate
|
44
|
-
# # => true if the user is allowed to administrate all resources.
|
45
|
-
#
|
46
|
-
# See SecurityContext#allowed?.
|
47
|
-
#
|
48
|
-
def allowed?(*args)
|
49
|
-
SecurityContext.allowed?(*args)
|
50
|
-
end
|
51
|
-
|
52
|
-
alias a? allowed?
|
53
|
-
|
54
|
-
# Equivalent to allowed?; is? is provided for better readability.
|
55
|
-
#
|
56
|
-
# allowed? :logged_in
|
57
|
-
# vs
|
58
|
-
# is? :logged_in
|
59
|
-
#
|
60
|
-
def is?(*args)
|
61
|
-
SecurityContext.is?(*args)
|
62
|
-
end
|
63
|
-
|
64
|
-
# Checks whether the user is allowed to access the action.
|
65
|
-
#
|
66
|
-
# Expects arguments like #link_to_if_allowed, just without name and block.
|
67
|
-
#
|
68
|
-
# Returns true if the action is allowed.
|
69
|
-
#
|
70
|
-
def action_allowed?(options, objects=nil, params=nil, html_options=nil)
|
71
|
-
|
72
|
-
options, objects, params, html_options =
|
73
|
-
parse_allow_action_args(options, objects, params, html_options)
|
74
|
-
|
75
|
-
controller = params.delete :controller
|
76
|
-
action = params.delete :action
|
77
|
-
SecurityContext.allow_action?(controller, action, objects, params)
|
78
|
-
end
|
79
|
-
|
80
|
-
# Returns a link tag with the specified name to the specified resource if
|
81
|
-
# the user is allowed to access it. See #link_to_unless and
|
82
|
-
# SecurityContext#action_allowed? for more documentation.
|
83
|
-
#
|
84
|
-
# There are two ways of using #link_to_if_allowed
|
85
|
-
#
|
86
|
-
# === As #link_to with alternative
|
87
|
-
# (or as #link_to_unless without explicit condition)
|
88
|
-
# link_to_if_allowed(name, options={}, html_options=nil) { 'alternative' }
|
89
|
-
# +options+ either is a hash, like
|
90
|
-
# { :controller => :comments, :action => edit, :id => @comment }
|
91
|
-
# a string, like
|
92
|
-
# "comments/1/edit"
|
93
|
-
# or
|
94
|
-
# edit_comment_path(@comment)
|
95
|
-
# or a single resource object.
|
96
|
-
#
|
97
|
-
# Notice that when providing a string, controller, action and parameters will
|
98
|
-
# be parsed. After that, the resource types of the parameters are *guessed*,
|
99
|
-
# the resources are retrieved and the rules of the action are evaluated.
|
100
|
-
#
|
101
|
-
# The block will be evaluated if the action is not allowed,
|
102
|
-
# like in #link_to_unless.
|
103
|
-
#
|
104
|
-
# === As #link_to with alternative and explicit objects
|
105
|
-
# link_to_if_allowed(name, options={}, objects=[], params={}, html_options=nil) { 'alternative' }
|
106
|
-
# In this case, controller and action will be derived from +options+ unless
|
107
|
-
# they are specified in +params+.
|
108
|
-
# All items in +objects+ and all remaining items in +params+ will be used
|
109
|
-
# for evaluating the rules of the action.
|
110
|
-
#
|
111
|
-
# If you want to specify +html_options+, provide at least an empty hash
|
112
|
-
# for +params+.
|
113
|
-
#
|
114
|
-
# Unlike to #link_to, you can also provide a symbol as +options+ value.
|
115
|
-
# In this case, the target url will be determined by sending symbol as
|
116
|
-
# message, providing +objects+ and +params+ as arguments, e.g.
|
117
|
-
# link_to_if_allowed("Show comment", :comment_path, [@article, @comment], {:details => true})
|
118
|
-
# will call
|
119
|
-
# comment_path(@article, @comment, {:details => true})
|
120
|
-
#
|
121
|
-
# === Examples
|
122
|
-
# <%= link_to_if_allowed("Show", @course) { } %>
|
123
|
-
# <%= link_to_if_allowed("New", new_course_path) { "You may not create a new course." } %>
|
124
|
-
#
|
125
|
-
# These two are equivalent, however, the second approach is more efficient:
|
126
|
-
# <%= link_to_if_allowed("Edit", edit_course_path(@course)) { } %>
|
127
|
-
# <%= link_to_if_allowed("Edit", :edit_course_path, @course) { } %>
|
128
|
-
#
|
129
|
-
# The HTML-options are taken into account when choosing the action.
|
130
|
-
# <%= link_to_if_allowed("Delete", @course, {:method => :delete}) { } %>
|
131
|
-
#
|
132
|
-
# You can also define all values explicitly
|
133
|
-
# <%= link_to_if_allowed("Edit comment", "articles/1/comments/5/edit", [@comment], {:article => @comment.article, :action => :edit, :controller => :comments}) { } %>
|
134
|
-
#
|
135
|
-
# === Parameters
|
136
|
-
# - +name+ Text of the link
|
137
|
-
# - +options+
|
138
|
-
# - +objects+
|
139
|
-
# - +params+
|
140
|
-
# - +html_options+
|
141
|
-
#
|
142
|
-
def link_to_if_allowed(name, options, objects=nil, params=nil, html_options=nil, &block)
|
143
|
-
|
144
|
-
options, objects, params, html_options =
|
145
|
-
parse_allow_action_args(options, objects, params, html_options)
|
146
|
-
|
147
|
-
controller = params.delete :controller
|
148
|
-
action = params.delete :action
|
149
|
-
allowed = SecurityContext.allow_action?(controller, action, objects, params)
|
150
|
-
|
151
|
-
link_to_if(allowed, name, options, html_options, &block)
|
152
|
-
end
|
153
|
-
|
154
|
-
alias link_if_a link_to_if_allowed
|
155
|
-
|
156
|
-
private
|
157
|
-
|
158
|
-
def parse_allow_action_args(*args)
|
159
|
-
if args.second && !(args.second.is_a? Hash)
|
160
|
-
# objects and params are specified
|
161
|
-
options, objects, params, html_options = args
|
162
|
-
objects = [objects] unless objects.is_a? Array
|
163
|
-
params ||= {}
|
164
|
-
html_options ||= {}
|
165
|
-
if options.is_a? Symbol
|
166
|
-
# options is a symbol, send the message to get the link path
|
167
|
-
path_args = objects + [params]
|
168
|
-
options = send(options, *path_args)
|
169
|
-
end
|
170
|
-
else
|
171
|
-
# retrieve objects and params from options
|
172
|
-
options = args.first
|
173
|
-
html_options = args.second || {}
|
174
|
-
objects = [] # everything will be in the params
|
175
|
-
if options.is_a? Hash
|
176
|
-
params = options.dup
|
177
|
-
else
|
178
|
-
params = parse_action_params(options, html_options)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
unless params[:controller] && params[:action]
|
183
|
-
# if controller and action are not given, parse from options
|
184
|
-
params = parse_controller_action(options, params, html_options)
|
185
|
-
end
|
186
|
-
|
187
|
-
[options, objects, params, html_options]
|
188
|
-
end
|
189
|
-
|
190
|
-
# uses options and html_options to retrieve controller and action,
|
191
|
-
# adds these values to params hash
|
192
|
-
def parse_controller_action(options, params, html_options)
|
193
|
-
path_info = get_path_info(options, html_options)
|
194
|
-
params[:controller] ||= path_info[:controller]
|
195
|
-
params[:action] ||= path_info[:action]
|
196
|
-
params
|
197
|
-
end
|
198
|
-
|
199
|
-
# uses options and html_options to retrieve controller, action
|
200
|
-
# and params
|
201
|
-
def parse_action_params(options, html_options)
|
202
|
-
get_path_info(options, html_options)
|
203
|
-
end
|
204
|
-
|
205
|
-
def get_path_info(options, html_options)
|
206
|
-
if options.is_a? String
|
207
|
-
path = options
|
208
|
-
else
|
209
|
-
path = url_for(options)
|
210
|
-
end
|
211
|
-
env = { :method => (html_options[:method] || :get ) }
|
212
|
-
ActionController::Routing::Routes.recognize_path(path, env)
|
213
|
-
end
|
214
|
-
|
215
|
-
end
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/includes/helper.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
# = AnnotationSecurity::Helper
|
6
|
+
#
|
7
|
+
# This module adds some useful helper methods to your templates.
|
8
|
+
#
|
9
|
+
module AnnotationSecurity::Helper
|
10
|
+
|
11
|
+
# Returns true if the operation defined by +policy_args+ is allowed.
|
12
|
+
#
|
13
|
+
# The following calls to #allowed? are possible:
|
14
|
+
#
|
15
|
+
# allowed? :show, :resource, @resource
|
16
|
+
# # => true if the current user has the right to show @resource,
|
17
|
+
# # which belongs to the :resource resource-class
|
18
|
+
#
|
19
|
+
# In case of model objects or other classes which implement a #resource_type
|
20
|
+
# method the the second argument may be ommited
|
21
|
+
#
|
22
|
+
# allowed? :show, @resource
|
23
|
+
# # equivalent to the above call if @resource.resource_type == :resource
|
24
|
+
#
|
25
|
+
# A policy description used as a controller annotation may also be used
|
26
|
+
# to check a right
|
27
|
+
#
|
28
|
+
# allowed? "show resource", @resource
|
29
|
+
# # => true if the current user has the right "show resource" for @resource
|
30
|
+
#
|
31
|
+
# A policy may also be applied without an object representing the context:
|
32
|
+
#
|
33
|
+
# allowed? :show, :resource
|
34
|
+
# # => true if the current may show resources.
|
35
|
+
#
|
36
|
+
# This will only check system and pretest rules. The result +true+ does not
|
37
|
+
# mean that the user may show all resources. However, a +false+ indicates
|
38
|
+
# that the user is not allowed to show any resources.
|
39
|
+
#
|
40
|
+
# If the resource class is omitted as well, only rules defined for all
|
41
|
+
# resources can be tested. See RelationLoader#all_resources for details.
|
42
|
+
#
|
43
|
+
# allowed? :administrate
|
44
|
+
# # => true if the user is allowed to administrate all resources.
|
45
|
+
#
|
46
|
+
# See SecurityContext#allowed?.
|
47
|
+
#
|
48
|
+
def allowed?(*args)
|
49
|
+
SecurityContext.allowed?(*args)
|
50
|
+
end
|
51
|
+
|
52
|
+
alias a? allowed?
|
53
|
+
|
54
|
+
# Equivalent to allowed?; is? is provided for better readability.
|
55
|
+
#
|
56
|
+
# allowed? :logged_in
|
57
|
+
# vs
|
58
|
+
# is? :logged_in
|
59
|
+
#
|
60
|
+
def is?(*args)
|
61
|
+
SecurityContext.is?(*args)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Checks whether the user is allowed to access the action.
|
65
|
+
#
|
66
|
+
# Expects arguments like #link_to_if_allowed, just without name and block.
|
67
|
+
#
|
68
|
+
# Returns true if the action is allowed.
|
69
|
+
#
|
70
|
+
def action_allowed?(options, objects=nil, params=nil, html_options=nil)
|
71
|
+
|
72
|
+
options, objects, params, html_options =
|
73
|
+
parse_allow_action_args(options, objects, params, html_options)
|
74
|
+
|
75
|
+
controller = params.delete :controller
|
76
|
+
action = params.delete :action
|
77
|
+
SecurityContext.allow_action?(controller, action, objects, params)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns a link tag with the specified name to the specified resource if
|
81
|
+
# the user is allowed to access it. See #link_to_unless and
|
82
|
+
# SecurityContext#action_allowed? for more documentation.
|
83
|
+
#
|
84
|
+
# There are two ways of using #link_to_if_allowed
|
85
|
+
#
|
86
|
+
# === As #link_to with alternative
|
87
|
+
# (or as #link_to_unless without explicit condition)
|
88
|
+
# link_to_if_allowed(name, options={}, html_options=nil) { 'alternative' }
|
89
|
+
# +options+ either is a hash, like
|
90
|
+
# { :controller => :comments, :action => edit, :id => @comment }
|
91
|
+
# a string, like
|
92
|
+
# "comments/1/edit"
|
93
|
+
# or
|
94
|
+
# edit_comment_path(@comment)
|
95
|
+
# or a single resource object.
|
96
|
+
#
|
97
|
+
# Notice that when providing a string, controller, action and parameters will
|
98
|
+
# be parsed. After that, the resource types of the parameters are *guessed*,
|
99
|
+
# the resources are retrieved and the rules of the action are evaluated.
|
100
|
+
#
|
101
|
+
# The block will be evaluated if the action is not allowed,
|
102
|
+
# like in #link_to_unless.
|
103
|
+
#
|
104
|
+
# === As #link_to with alternative and explicit objects
|
105
|
+
# link_to_if_allowed(name, options={}, objects=[], params={}, html_options=nil) { 'alternative' }
|
106
|
+
# In this case, controller and action will be derived from +options+ unless
|
107
|
+
# they are specified in +params+.
|
108
|
+
# All items in +objects+ and all remaining items in +params+ will be used
|
109
|
+
# for evaluating the rules of the action.
|
110
|
+
#
|
111
|
+
# If you want to specify +html_options+, provide at least an empty hash
|
112
|
+
# for +params+.
|
113
|
+
#
|
114
|
+
# Unlike to #link_to, you can also provide a symbol as +options+ value.
|
115
|
+
# In this case, the target url will be determined by sending symbol as
|
116
|
+
# message, providing +objects+ and +params+ as arguments, e.g.
|
117
|
+
# link_to_if_allowed("Show comment", :comment_path, [@article, @comment], {:details => true})
|
118
|
+
# will call
|
119
|
+
# comment_path(@article, @comment, {:details => true})
|
120
|
+
#
|
121
|
+
# === Examples
|
122
|
+
# <%= link_to_if_allowed("Show", @course) { } %>
|
123
|
+
# <%= link_to_if_allowed("New", new_course_path) { "You may not create a new course." } %>
|
124
|
+
#
|
125
|
+
# These two are equivalent, however, the second approach is more efficient:
|
126
|
+
# <%= link_to_if_allowed("Edit", edit_course_path(@course)) { } %>
|
127
|
+
# <%= link_to_if_allowed("Edit", :edit_course_path, @course) { } %>
|
128
|
+
#
|
129
|
+
# The HTML-options are taken into account when choosing the action.
|
130
|
+
# <%= link_to_if_allowed("Delete", @course, {:method => :delete}) { } %>
|
131
|
+
#
|
132
|
+
# You can also define all values explicitly
|
133
|
+
# <%= link_to_if_allowed("Edit comment", "articles/1/comments/5/edit", [@comment], {:article => @comment.article, :action => :edit, :controller => :comments}) { } %>
|
134
|
+
#
|
135
|
+
# === Parameters
|
136
|
+
# - +name+ Text of the link
|
137
|
+
# - +options+
|
138
|
+
# - +objects+
|
139
|
+
# - +params+
|
140
|
+
# - +html_options+
|
141
|
+
#
|
142
|
+
def link_to_if_allowed(name, options, objects=nil, params=nil, html_options=nil, &block)
|
143
|
+
|
144
|
+
options, objects, params, html_options =
|
145
|
+
parse_allow_action_args(options, objects, params, html_options)
|
146
|
+
|
147
|
+
controller = params.delete :controller
|
148
|
+
action = params.delete :action
|
149
|
+
allowed = SecurityContext.allow_action?(controller, action, objects, params)
|
150
|
+
|
151
|
+
link_to_if(allowed, name, options, html_options, &block)
|
152
|
+
end
|
153
|
+
|
154
|
+
alias link_if_a link_to_if_allowed
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def parse_allow_action_args(*args)
|
159
|
+
if args.second && !(args.second.is_a? Hash)
|
160
|
+
# objects and params are specified
|
161
|
+
options, objects, params, html_options = args
|
162
|
+
objects = [objects] unless objects.is_a? Array
|
163
|
+
params ||= {}
|
164
|
+
html_options ||= {}
|
165
|
+
if options.is_a? Symbol
|
166
|
+
# options is a symbol, send the message to get the link path
|
167
|
+
path_args = objects + [params]
|
168
|
+
options = send(options, *path_args)
|
169
|
+
end
|
170
|
+
else
|
171
|
+
# retrieve objects and params from options
|
172
|
+
options = args.first
|
173
|
+
html_options = args.second || {}
|
174
|
+
objects = [] # everything will be in the params
|
175
|
+
if options.is_a? Hash
|
176
|
+
params = options.dup
|
177
|
+
else
|
178
|
+
params = parse_action_params(options, html_options)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
unless params[:controller] && params[:action]
|
183
|
+
# if controller and action are not given, parse from options
|
184
|
+
params = parse_controller_action(options, params, html_options)
|
185
|
+
end
|
186
|
+
|
187
|
+
[options, objects, params, html_options]
|
188
|
+
end
|
189
|
+
|
190
|
+
# uses options and html_options to retrieve controller and action,
|
191
|
+
# adds these values to params hash
|
192
|
+
def parse_controller_action(options, params, html_options)
|
193
|
+
path_info = get_path_info(options, html_options)
|
194
|
+
params[:controller] ||= path_info[:controller]
|
195
|
+
params[:action] ||= path_info[:action]
|
196
|
+
params
|
197
|
+
end
|
198
|
+
|
199
|
+
# uses options and html_options to retrieve controller, action
|
200
|
+
# and params
|
201
|
+
def parse_action_params(options, html_options)
|
202
|
+
get_path_info(options, html_options)
|
203
|
+
end
|
204
|
+
|
205
|
+
def get_path_info(options, html_options)
|
206
|
+
if options.is_a? String
|
207
|
+
path = options
|
208
|
+
else
|
209
|
+
path = url_for(options)
|
210
|
+
end
|
211
|
+
env = { :method => (html_options[:method] || :get ) }
|
212
|
+
ActionController::Routing::Routes.recognize_path(path, env)
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|