timcharper-declarative_authorization 0.4.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +135 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +503 -0
- data/Rakefile +43 -0
- data/app/controllers/authorization_rules_controller.rb +259 -0
- data/app/controllers/authorization_usages_controller.rb +23 -0
- data/app/helpers/authorization_rules_helper.rb +218 -0
- data/app/views/authorization_rules/_change.erb +58 -0
- data/app/views/authorization_rules/_show_graph.erb +37 -0
- data/app/views/authorization_rules/_suggestions.erb +48 -0
- data/app/views/authorization_rules/change.html.erb +169 -0
- data/app/views/authorization_rules/graph.dot.erb +68 -0
- data/app/views/authorization_rules/graph.html.erb +40 -0
- data/app/views/authorization_rules/index.html.erb +17 -0
- data/app/views/authorization_usages/index.html.erb +36 -0
- data/authorization_rules.dist.rb +20 -0
- data/config/routes.rb +7 -0
- data/garlic_example.rb +20 -0
- data/init.rb +5 -0
- data/lib/declarative_authorization.rb +15 -0
- data/lib/declarative_authorization/authorization.rb +683 -0
- data/lib/declarative_authorization/development_support/analyzer.rb +252 -0
- data/lib/declarative_authorization/development_support/change_analyzer.rb +253 -0
- data/lib/declarative_authorization/development_support/change_supporter.rb +620 -0
- data/lib/declarative_authorization/development_support/development_support.rb +243 -0
- data/lib/declarative_authorization/helper.rb +60 -0
- data/lib/declarative_authorization/in_controller.rb +623 -0
- data/lib/declarative_authorization/in_model.rb +162 -0
- data/lib/declarative_authorization/maintenance.rb +198 -0
- data/lib/declarative_authorization/obligation_scope.rb +345 -0
- data/lib/declarative_authorization/rails_legacy.rb +14 -0
- data/lib/declarative_authorization/reader.rb +472 -0
- data/test/authorization_test.rb +971 -0
- data/test/controller_filter_resource_access_test.rb +511 -0
- data/test/controller_test.rb +465 -0
- data/test/dsl_reader_test.rb +157 -0
- data/test/helper_test.rb +171 -0
- data/test/maintenance_test.rb +46 -0
- data/test/model_test.rb +1694 -0
- data/test/schema.sql +54 -0
- data/test/test_helper.rb +134 -0
- metadata +119 -0
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the authorization plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the authorization plugin.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'Authorization'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.options << '--charset' << 'utf-8'
|
21
|
+
rdoc.rdoc_files.include('README.rdoc')
|
22
|
+
rdoc.rdoc_files.include('CHANGELOG')
|
23
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
24
|
+
end
|
25
|
+
|
26
|
+
# load up garlic if it's here
|
27
|
+
if File.directory?(File.join(File.dirname(__FILE__), 'garlic'))
|
28
|
+
require File.join(File.dirname(__FILE__), 'garlic/lib/garlic_tasks')
|
29
|
+
require File.join(File.dirname(__FILE__), 'garlic')
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "clone the garlic repo (for running ci tasks)"
|
33
|
+
task :get_garlic do
|
34
|
+
sh "git clone git://github.com/ianwhite/garlic.git garlic"
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Expand filelist in src gemspec"
|
38
|
+
task :build_gemspec do
|
39
|
+
gemspec_data = File.read("declarative_authorization.gemspec.src")
|
40
|
+
gemspec_data.gsub!(/\.files = (.*)/) {|m| ".files = #{eval($1).inspect}"}
|
41
|
+
File.open("declarative_authorization.gemspec", "w") {|f| f.write(gemspec_data)}
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,259 @@
|
|
1
|
+
if Authorization::activate_authorization_rules_browser?
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), %w{.. .. lib declarative_authorization development_support analyzer})
|
4
|
+
require File.join(File.dirname(__FILE__), %w{.. .. lib declarative_authorization development_support change_supporter})
|
5
|
+
require File.join(File.dirname(__FILE__), %w{.. .. lib declarative_authorization development_support development_support})
|
6
|
+
|
7
|
+
begin
|
8
|
+
# for nice auth_rules output:
|
9
|
+
require "parse_tree"
|
10
|
+
require "parse_tree_extensions"
|
11
|
+
require "ruby2ruby"
|
12
|
+
rescue LoadError; end
|
13
|
+
|
14
|
+
class AuthorizationRulesController < ApplicationController
|
15
|
+
unloadable
|
16
|
+
|
17
|
+
filter_access_to :all, :require => :read
|
18
|
+
def index
|
19
|
+
respond_to do |format|
|
20
|
+
format.html do
|
21
|
+
@auth_rules_script = File.read("#{RAILS_ROOT}/config/authorization_rules.rb")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def graph
|
27
|
+
if params[:format] == "svg"
|
28
|
+
render :text => dot_to_svg(auth_to_dot(graph_options)),
|
29
|
+
:content_type => "image/svg+xml"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def change
|
34
|
+
@users = find_all_users
|
35
|
+
@users.sort! {|a, b| a.login <=> b.login }
|
36
|
+
|
37
|
+
@privileges = authorization_engine.auth_rules.collect {|rule| rule.privileges.to_a}.flatten.uniq
|
38
|
+
@privileges = @privileges.collect do |priv|
|
39
|
+
priv = Authorization::DevelopmentSupport::AnalyzerEngine::Privilege.for_sym(priv, authorization_engine)
|
40
|
+
([priv] + priv.descendants + priv.ancestors).map(&:to_sym)
|
41
|
+
end.flatten.uniq
|
42
|
+
@privileges.sort_by {|priv| priv.to_s}
|
43
|
+
@privilege = params[:privilege].to_sym rescue @privileges.first
|
44
|
+
@contexts = authorization_engine.auth_rules.collect {|rule| rule.contexts.to_a}.flatten.uniq
|
45
|
+
@context = params[:context].to_sym rescue @contexts.first
|
46
|
+
|
47
|
+
respond_to do |format|
|
48
|
+
format.html
|
49
|
+
format.js do
|
50
|
+
render :partial => 'change'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def suggest_change
|
56
|
+
users_permission = params[:user].inject({}) do |memo, (user_id, data)|
|
57
|
+
if data[:permission] != "undetermined"
|
58
|
+
begin
|
59
|
+
memo[find_user_by_id(user_id)] = (data[:permission] == 'yes')
|
60
|
+
rescue ActiveRecord::NotFound
|
61
|
+
end
|
62
|
+
end
|
63
|
+
memo
|
64
|
+
end
|
65
|
+
|
66
|
+
prohibited_actions = (params[:prohibited_action] || []).collect do |spec|
|
67
|
+
deserialize_changes(spec).flatten
|
68
|
+
end
|
69
|
+
|
70
|
+
analyzer = Authorization::DevelopmentSupport::ChangeSupporter.new(authorization_engine)
|
71
|
+
|
72
|
+
privilege = params[:privilege].to_sym
|
73
|
+
context = params[:context].to_sym
|
74
|
+
all_users = User.all
|
75
|
+
@context = context
|
76
|
+
@approaches = analyzer.find_approaches_for(:users => all_users, :prohibited_actions => prohibited_actions) do
|
77
|
+
users.each_with_index do |user, idx|
|
78
|
+
unless users_permission[all_users[idx]].nil?
|
79
|
+
args = [privilege, {:context => context, :user => user}]
|
80
|
+
assert(users_permission[all_users[idx]] ? permit?(*args) : !permit?(*args))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
@affected_users = @approaches.each_with_object({}) do |approach, memo|
|
86
|
+
memo[approach] = approach.affected_users(authorization_engine, all_users, privilege, context).length
|
87
|
+
end
|
88
|
+
max_affected_users = @affected_users.values.max
|
89
|
+
if params[:affected_users]
|
90
|
+
@approaches = @approaches.sort_by do |approach|
|
91
|
+
affected_users_count = @affected_users[approach]
|
92
|
+
if params[:affected_users] == "many"
|
93
|
+
#approach.weight.to_f / [affected_users_count, 0.1].min
|
94
|
+
approach.weight + (max_affected_users - affected_users_count) * 10
|
95
|
+
else
|
96
|
+
#approach.weight * affected_users_count
|
97
|
+
approach.weight + affected_users_count * 10
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
@grouped_approaches = analyzer.group_approaches(@approaches)
|
103
|
+
|
104
|
+
respond_to do |format|
|
105
|
+
format.js do
|
106
|
+
render :partial => 'suggestions'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
def auth_to_dot (options = {})
|
113
|
+
options = {
|
114
|
+
:effective_role_privs => true,
|
115
|
+
:privilege_hierarchy => false,
|
116
|
+
:stacked_roles => false,
|
117
|
+
:only_relevant_contexts => true,
|
118
|
+
:only_relevant_roles => false,
|
119
|
+
:filter_roles => nil,
|
120
|
+
:filter_contexts => nil,
|
121
|
+
:highlight_privilege => nil,
|
122
|
+
:changes => nil,
|
123
|
+
:users => nil
|
124
|
+
}.merge(options)
|
125
|
+
|
126
|
+
@has_changes = options[:changes] && !options[:changes].empty?
|
127
|
+
@highlight_privilege = options[:highlight_privilege]
|
128
|
+
@stacked_roles = options[:stacked_roles]
|
129
|
+
|
130
|
+
@users = options[:users]
|
131
|
+
|
132
|
+
engine = authorization_engine.clone
|
133
|
+
@changes = replay_changes(engine, @users, options[:changes]) if options[:changes]
|
134
|
+
|
135
|
+
options[:filter_roles] ||= @users.collect {|user| user.role_symbols}.flatten.uniq if options[:only_relevant_roles] and @users
|
136
|
+
|
137
|
+
filter_roles_flattened = nil
|
138
|
+
if options[:filter_roles]
|
139
|
+
filter_roles_flattened = options[:filter_roles].collect do |role_sym|
|
140
|
+
Authorization::DevelopmentSupport::AnalyzerEngine::Role.for_sym(role_sym, engine).
|
141
|
+
ancestors.map(&:to_sym) + [role_sym]
|
142
|
+
end.flatten.uniq
|
143
|
+
end
|
144
|
+
|
145
|
+
@roles = engine.roles
|
146
|
+
@roles = @roles.select {|r| filter_roles_flattened.include?(r) } if options[:filter_roles]
|
147
|
+
@role_hierarchy = engine.role_hierarchy
|
148
|
+
@privilege_hierarchy = engine.privilege_hierarchy
|
149
|
+
|
150
|
+
@contexts = engine.auth_rules.
|
151
|
+
collect {|ar| ar.contexts.to_a}.flatten.uniq
|
152
|
+
@contexts = @contexts.select {|c| c == options[:filter_contexts] } if options[:filter_contexts]
|
153
|
+
@context_privs = {}
|
154
|
+
@role_privs = {}
|
155
|
+
engine.auth_rules.each do |auth_rule|
|
156
|
+
@role_privs[auth_rule.role] ||= []
|
157
|
+
auth_rule.contexts.
|
158
|
+
select {|c| options[:filter_contexts].nil? or c == options[:filter_contexts]}.
|
159
|
+
each do |context|
|
160
|
+
@context_privs[context] ||= []
|
161
|
+
@context_privs[context] += auth_rule.privileges.to_a
|
162
|
+
@context_privs[context].uniq!
|
163
|
+
@role_privs[auth_rule.role] += auth_rule.privileges.collect {|p| [context, p, auth_rule.attributes.empty?, auth_rule.to_long_s]}
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
if options[:effective_role_privs]
|
168
|
+
@roles.each do |role|
|
169
|
+
role = Authorization::DevelopmentSupport::AnalyzerEngine::Role.for_sym(role, engine)
|
170
|
+
@role_privs[role.to_sym] ||= []
|
171
|
+
role.ancestors.each do |lower_role|
|
172
|
+
@role_privs[role.to_sym].concat(@role_privs[lower_role.to_sym]).uniq!
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
@roles.delete_if do |role|
|
178
|
+
role = Authorization::DevelopmentSupport::AnalyzerEngine::Role.for_sym(role, engine)
|
179
|
+
([role] + role.ancestors).all? {|inner_role| @role_privs[inner_role.to_sym].blank? }
|
180
|
+
end
|
181
|
+
|
182
|
+
if options[:only_relevant_contexts]
|
183
|
+
@contexts.delete_if do |context|
|
184
|
+
@roles.all? {|role| !@role_privs[role] || !@role_privs[role].any? {|info| info[0] == context}}
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
if options[:privilege_hierarchy]
|
189
|
+
@context_privs.each do |context, privs|
|
190
|
+
privs.each do |priv|
|
191
|
+
context_lower_privs = (@privilege_hierarchy[priv] || []).
|
192
|
+
select {|p,c| c.nil? or c == context}.
|
193
|
+
collect {|p,c| p}
|
194
|
+
privs.concat(context_lower_privs).uniq!
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
render_to_string :template => 'authorization_rules/graph.dot.erb', :layout => false
|
200
|
+
end
|
201
|
+
|
202
|
+
def replay_changes (engine, users, changes)
|
203
|
+
changes.inject({}) do |memo, info|
|
204
|
+
case info[0]
|
205
|
+
when :add_privilege, :add_role
|
206
|
+
Authorization::DevelopmentSupport::AnalyzerEngine.apply_change(engine, info)
|
207
|
+
when :assign_role_to_user
|
208
|
+
user = users.find {|u| u.login == info[2]}
|
209
|
+
user.role_symbols << info[1] if user
|
210
|
+
end
|
211
|
+
(memo[info[0]] ||= Set.new) << info[1..-1]
|
212
|
+
memo
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def dot_to_svg (dot_data)
|
217
|
+
gv = IO.popen("#{Authorization.dot_path} -q -Tsvg", "w+")
|
218
|
+
gv.puts dot_data
|
219
|
+
gv.close_write
|
220
|
+
gv.read
|
221
|
+
rescue IOError, Errno::EPIPE => e
|
222
|
+
raise Exception, "Error in call to graphviz: #{e}"
|
223
|
+
end
|
224
|
+
|
225
|
+
def graph_options
|
226
|
+
{
|
227
|
+
:effective_role_privs => !params[:effective_role_privs].blank?,
|
228
|
+
:privilege_hierarchy => !params[:privilege_hierarchy].blank?,
|
229
|
+
:stacked_roles => !params[:stacked_roles].blank?,
|
230
|
+
:only_relevant_roles => !params[:only_relevant_roles].blank?,
|
231
|
+
:filter_roles => params[:filter_roles].blank? ? nil : (params[:filter_roles].is_a?(Array) ? params[:filter_roles].map(&:to_sym) : [params[:filter_roles].to_sym]),
|
232
|
+
:filter_contexts => params[:filter_contexts].blank? ? nil : params[:filter_contexts].to_sym,
|
233
|
+
:highlight_privilege => params[:highlight_privilege].blank? ? nil : params[:highlight_privilege].to_sym,
|
234
|
+
:changes => deserialize_changes(params[:changes]),
|
235
|
+
:users => params[:user_ids] && params[:user_ids].collect {|user_id| find_user_by_id(user_id)}
|
236
|
+
}
|
237
|
+
end
|
238
|
+
|
239
|
+
def deserialize_changes (changes)
|
240
|
+
if changes
|
241
|
+
changes.split(';').collect do |info|
|
242
|
+
info.split(',').collect do |info_part|
|
243
|
+
info_part[0,1] == ':' ? info_part[1..-1].to_sym : info_part
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def find_user_by_id (id)
|
250
|
+
User.find(id)
|
251
|
+
end
|
252
|
+
def find_all_users
|
253
|
+
User.all.select {|user| !user.login.blank?}
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
else
|
258
|
+
class AuthorizationRulesController < ApplicationController; end
|
259
|
+
end # activate_authorization_rules_browser?
|
@@ -0,0 +1,23 @@
|
|
1
|
+
if Authorization::activate_authorization_rules_browser?
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), %w{.. .. lib declarative_authorization maintenance})
|
4
|
+
|
5
|
+
class AuthorizationUsagesController < ApplicationController
|
6
|
+
unloadable
|
7
|
+
|
8
|
+
helper :authorization_rules
|
9
|
+
filter_access_to :all, :require => :read
|
10
|
+
# TODO set context?
|
11
|
+
|
12
|
+
def index
|
13
|
+
respond_to do |format|
|
14
|
+
format.html do
|
15
|
+
@auth_usages_by_controller = Authorization::Maintenance::Usage.usages_by_controller
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
else
|
22
|
+
class AuthorizationUsagesController < ApplicationController; end
|
23
|
+
end # activate_authorization_rules_browser?
|
@@ -0,0 +1,218 @@
|
|
1
|
+
module AuthorizationRulesHelper
|
2
|
+
def syntax_highlight (rules)
|
3
|
+
regexps = {
|
4
|
+
:constant => [/(:)(\w+)/],
|
5
|
+
:proc => ['role', 'authorization', 'privileges'],
|
6
|
+
:statement => ['has_permission_on', 'if_attribute', 'if_permitted_to', 'includes', 'privilege', 'to'],
|
7
|
+
:operator => ['is', 'contains', 'is_in', 'is_not', 'is_not_in', 'intersects'],
|
8
|
+
:special => ['user', 'true', 'false'],
|
9
|
+
:preproc => ['do', 'end', /()(=>)/, /()(\{)/, /()(\})/, /()(\[)/, /()(\])/],
|
10
|
+
:comment => [/()(#.*$)/]#,
|
11
|
+
#:privilege => [:read],
|
12
|
+
#:context => [:conferences]
|
13
|
+
}
|
14
|
+
regexps.each do |name, res|
|
15
|
+
res.each do |re|
|
16
|
+
rules.gsub!(
|
17
|
+
re.is_a?(String) ? Regexp.new("(^|[^:])\\b(#{Regexp.escape(re)})\\b") :
|
18
|
+
(re.is_a?(Symbol) ? Regexp.new("()(:#{Regexp.escape(re.to_s)})\\b") : re),
|
19
|
+
"\\1<span class=\"#{name}\">\\2</span>")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
rules
|
23
|
+
end
|
24
|
+
|
25
|
+
def policy_analysis_hints (marked_up, policy_data)
|
26
|
+
analyzer = Authorization::DevelopmentSupport::Analyzer.new(controller.authorization_engine)
|
27
|
+
analyzer.analyze(policy_data)
|
28
|
+
marked_up_by_line = marked_up.split("\n")
|
29
|
+
reports_by_line = analyzer.reports.inject({}) do |memo, report|
|
30
|
+
memo[report.line || 1] ||= []
|
31
|
+
memo[report.line || 1] << report
|
32
|
+
memo
|
33
|
+
end
|
34
|
+
reports_by_line.each do |line, reports|
|
35
|
+
text = reports.collect {|report| "#{report.type}: #{report.message}"} * " "
|
36
|
+
note = %Q{<span class="note" title="#{h text}">[i]</span>}
|
37
|
+
marked_up_by_line[line - 1] = note + marked_up_by_line[line - 1]
|
38
|
+
end
|
39
|
+
marked_up_by_line * "\n"
|
40
|
+
end
|
41
|
+
|
42
|
+
def link_to_graph (title, options = {})
|
43
|
+
type = options[:type] || ''
|
44
|
+
link_to_function title, "$$('object')[0].data = '#{url_for :action => 'index', :format => 'svg', :type => type}'"
|
45
|
+
end
|
46
|
+
|
47
|
+
def navigation
|
48
|
+
link_to("Rules", authorization_rules_path) << ' | ' <<
|
49
|
+
link_to("Change Support", change_authorization_rules_path) << ' | ' <<
|
50
|
+
link_to("Graphical view", graph_authorization_rules_path) << ' | ' <<
|
51
|
+
link_to("Usages", authorization_usages_path) #<< ' | ' <<
|
52
|
+
# 'Edit | ' <<
|
53
|
+
# link_to("XACML export", :action => 'index', :format => 'xacml')
|
54
|
+
end
|
55
|
+
|
56
|
+
def role_color (role, fill = false)
|
57
|
+
if @has_changes
|
58
|
+
if has_changed(:add_role, role)
|
59
|
+
fill ? '#ddffdd' : '#000000'
|
60
|
+
elsif has_changed(:remove_role, role)
|
61
|
+
fill ? '#ffdddd' : '#000000'
|
62
|
+
else
|
63
|
+
fill ? '#ddddff' : '#000000'
|
64
|
+
end
|
65
|
+
else
|
66
|
+
fill_colors = %w{#ffdddd #ddffdd #ddddff #ffffdd #ffddff #ddffff}
|
67
|
+
colors = %w{#dd0000 #00dd00 #0000dd #dddd00 #dd00dd #00dddd}
|
68
|
+
@@role_colors ||= {}
|
69
|
+
@@role_colors[role] ||= begin
|
70
|
+
idx = @@role_colors.length % colors.length
|
71
|
+
[colors[idx], fill_colors[idx]]
|
72
|
+
end
|
73
|
+
@@role_colors[role][fill ? 1 : 0]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def role_fill_color (role)
|
78
|
+
role_color(role, true)
|
79
|
+
end
|
80
|
+
|
81
|
+
def privilege_color (privilege, context, role)
|
82
|
+
has_changed(:add_privilege, privilege, context, role) ? '#00dd00' :
|
83
|
+
(has_changed(:remove_privilege, privilege, context, role) ? '#dd0000' :
|
84
|
+
role_color(role))
|
85
|
+
end
|
86
|
+
|
87
|
+
def human_privilege (privilege)
|
88
|
+
begin
|
89
|
+
I18n.t(privilege, :scope => [:declarative_authorization, :privilege], :raise => true)
|
90
|
+
rescue
|
91
|
+
privilege.to_s
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def human_context (context)
|
96
|
+
begin
|
97
|
+
context.to_s.classify.constantize.human_name
|
98
|
+
rescue
|
99
|
+
context.to_s
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def human_privilege_context (privilege, context)
|
104
|
+
human = [human_privilege(privilege), human_context(context)]
|
105
|
+
begin
|
106
|
+
unless I18n.t(:verb_in_front_of_object, :scope => :declarative_authorization, :raise => true)
|
107
|
+
human.reverse!
|
108
|
+
end
|
109
|
+
rescue
|
110
|
+
end
|
111
|
+
human * " "
|
112
|
+
end
|
113
|
+
|
114
|
+
def human_role (role)
|
115
|
+
Authorization::Engine.instance.title_for(role) or role.to_s
|
116
|
+
end
|
117
|
+
|
118
|
+
def describe_step (step, options = {})
|
119
|
+
options = {:with_removal => false}.merge(options)
|
120
|
+
|
121
|
+
case step[0]
|
122
|
+
when :add_privilege
|
123
|
+
dont_assign = prohibit_link(step[0,3],
|
124
|
+
"Add privilege <strong>#{h human_privilege_context(step[1], step[2])}</strong> to any role",
|
125
|
+
"Don't suggest adding #{h human_privilege_context(step[1], step[2])}.", options)
|
126
|
+
"Add privilege <strong>#{h human_privilege_context(step[1], step[2])}</strong>#{dont_assign} to role <strong>#{h human_role(step[3].to_sym)}</strong>"
|
127
|
+
when :remove_privilege
|
128
|
+
dont_remove = prohibit_link(step[0,3],
|
129
|
+
"Remove privilege <strong>#{h human_privilege_context(step[1], step[2])}</strong> from any role",
|
130
|
+
"Don't suggest removing #{h human_privilege_context(step[1], step[2])}.", options)
|
131
|
+
"Remove privilege <strong>#{h human_privilege_context(step[1], step[2])}</strong>#{dont_remove} from role <strong>#{h human_role(step[3].to_sym)}</strong>"
|
132
|
+
when :add_role
|
133
|
+
"New role <strong>#{h human_role(step[1].to_sym)}</strong>"
|
134
|
+
when :assign_role_to_user
|
135
|
+
dont_assign = prohibit_link(step[0,2],
|
136
|
+
"Assign role <strong>#{h human_role(step[1].to_sym)}</strong> to any user",
|
137
|
+
"Don't suggest assigning #{h human_role(step[1].to_sym)}.", options)
|
138
|
+
"Assign role <strong>#{h human_role(step[1].to_sym)}</strong>#{dont_assign} to <strong>#{h readable_step_info(step[2])}</strong>"
|
139
|
+
when :remove_role_from_user
|
140
|
+
dont_remove = prohibit_link(step[0,2],
|
141
|
+
"Remove role <strong>#{h human_role(step[1].to_sym)}</strong> from any user",
|
142
|
+
"Don't suggest removing #{h human_role(step[1].to_sym)}.", options)
|
143
|
+
"Remove role <strong>#{h human_role(step[1].to_sym)}</strong>#{dont_remove} from <strong>#{h readable_step_info(step[2])}</strong>"
|
144
|
+
else
|
145
|
+
step.collect {|info| readable_step_info(info) }.map {|str| h str } * ', '
|
146
|
+
end + prohibit_link(step, options[:with_removal] ? "#{escape_javascript(describe_step(step))}" : '',
|
147
|
+
"Don't suggest this action.", options)
|
148
|
+
end
|
149
|
+
|
150
|
+
def prohibit_link (step, text, title, options)
|
151
|
+
options[:with_removal] ?
|
152
|
+
link_to_function("[x]", "prohibit_action('#{serialize_action(step)}', '#{text}')",
|
153
|
+
:class => 'prohibit', :title => title) :
|
154
|
+
''
|
155
|
+
end
|
156
|
+
|
157
|
+
def readable_step_info (info)
|
158
|
+
case info
|
159
|
+
when Symbol then info.inspect
|
160
|
+
when User then info.login
|
161
|
+
else info.to_sym.inspect
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def serialize_changes (approach)
|
166
|
+
changes = approach.changes.collect {|step| step.to_a.first.is_a?(Enumerable) ? step.to_a : [step.to_a]}
|
167
|
+
changes.collect {|multi_step| multi_step.collect {|step| serialize_action(step) }}.flatten * ';'
|
168
|
+
end
|
169
|
+
|
170
|
+
def serialize_action (step)
|
171
|
+
step.collect {|info| readable_step_info(info) } * ','
|
172
|
+
end
|
173
|
+
|
174
|
+
def serialize_relevant_roles (approach)
|
175
|
+
{:filter_roles => (Authorization::DevelopmentSupport::AnalyzerEngine.relevant_roles(approach.engine, approach.users).
|
176
|
+
map(&:to_sym) + [:new_role_for_change_analyzer]).uniq}.to_param
|
177
|
+
end
|
178
|
+
|
179
|
+
def has_changed (*args)
|
180
|
+
@changes && @changes[args[0]] && @changes[args[0]].include?(args[1..-1])
|
181
|
+
end
|
182
|
+
|
183
|
+
def affected_users_count (approach)
|
184
|
+
@affected_users[approach]
|
185
|
+
end
|
186
|
+
|
187
|
+
def auth_usage_info_classes (auth_info)
|
188
|
+
classes = []
|
189
|
+
if auth_info[:controller_permissions]
|
190
|
+
if auth_info[:controller_permissions][0]
|
191
|
+
classes << "catch-all" if auth_info[:controller_permissions][0].actions.include?(:all)
|
192
|
+
classes << "default-privilege" unless auth_info[:controller_permissions][0].privilege
|
193
|
+
classes << "default-context" unless auth_info[:controller_permissions][0].context
|
194
|
+
classes << "no-attribute-check" unless auth_info[:controller_permissions][0].attribute_check
|
195
|
+
end
|
196
|
+
else
|
197
|
+
classes << "unprotected"
|
198
|
+
end
|
199
|
+
classes * " "
|
200
|
+
end
|
201
|
+
|
202
|
+
def auth_usage_info_title (auth_info)
|
203
|
+
titles = []
|
204
|
+
if auth_usage_info_classes(auth_info) =~ /unprotected/
|
205
|
+
titles << "No filter_access_to call protects this action"
|
206
|
+
end
|
207
|
+
if auth_usage_info_classes(auth_info) =~ /no-attribute-check/
|
208
|
+
titles << "Action is not protected with attribute check"
|
209
|
+
end
|
210
|
+
if auth_usage_info_classes(auth_info) =~ /default-privilege/
|
211
|
+
titles << "Privilege set automatically from action name by :all rule"
|
212
|
+
end
|
213
|
+
if auth_usage_info_classes(auth_info) =~ /default-context/
|
214
|
+
titles << "Context set automatically from controller name by filter_access_to call without :context option"
|
215
|
+
end
|
216
|
+
titles * ". "
|
217
|
+
end
|
218
|
+
end
|