ghart-declarative_authorization 0.3.2.4
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 +83 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +510 -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 +187 -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 +152 -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 +634 -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 +597 -0
- data/lib/declarative_authorization/in_model.rb +159 -0
- data/lib/declarative_authorization/maintenance.rb +182 -0
- data/lib/declarative_authorization/obligation_scope.rb +308 -0
- data/lib/declarative_authorization/rails_legacy.rb +14 -0
- data/lib/declarative_authorization/reader.rb +441 -0
- data/test/authorization_test.rb +827 -0
- data/test/controller_filter_resource_access_test.rb +394 -0
- data/test/controller_test.rb +386 -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 +1308 -0
- data/test/schema.sql +54 -0
- data/test/test_helper.rb +118 -0
- metadata +106 -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.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,187 @@
|
|
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 describe_step (step, options = {})
|
88
|
+
options = {:with_removal => false}.merge(options)
|
89
|
+
|
90
|
+
case step[0]
|
91
|
+
when :add_privilege
|
92
|
+
dont_assign = prohibit_link(step[0,3],
|
93
|
+
"Add privilege <strong>#{h step[1].to_sym.inspect} #{h step[2].to_sym.inspect}</strong> to any role",
|
94
|
+
"Don't suggest adding #{h step[1].to_sym.inspect} #{h step[2].to_sym.inspect}.", options)
|
95
|
+
"Add privilege <strong>#{h step[1].inspect} #{h step[2].inspect}</strong>#{dont_assign} to role <strong>#{h step[3].to_sym.inspect}</strong>"
|
96
|
+
when :remove_privilege
|
97
|
+
dont_remove = prohibit_link(step[0,3],
|
98
|
+
"Remove privilege <strong>#{h step[1].to_sym.inspect} #{h step[2].to_sym.inspect}</strong> from any role",
|
99
|
+
"Don't suggest removing #{h step[1].to_sym.inspect} #{h step[2].to_sym.inspect}.", options)
|
100
|
+
"Remove privilege <strong>#{h step[1].inspect} #{h step[2].inspect}</strong>#{dont_remove} from role <strong>#{h step[3].to_sym.inspect}</strong>"
|
101
|
+
when :add_role
|
102
|
+
"New role <strong>#{h step[1].to_sym.inspect}</strong>"
|
103
|
+
when :assign_role_to_user
|
104
|
+
dont_assign = prohibit_link(step[0,2],
|
105
|
+
"Assign role <strong>#{h step[1].to_sym.inspect}</strong> to any user",
|
106
|
+
"Don't suggest assigning #{h step[1].to_sym.inspect}.", options)
|
107
|
+
"Assign role <strong>#{h step[1].to_sym.inspect}</strong>#{dont_assign} to <strong>#{h readable_step_info(step[2])}</strong>"
|
108
|
+
when :remove_role_from_user
|
109
|
+
dont_remove = prohibit_link(step[0,2],
|
110
|
+
"Remove role <strong>#{h step[1].to_sym.inspect}</strong> from any user",
|
111
|
+
"Don't suggest removing #{h step[1].to_sym.inspect}.", options)
|
112
|
+
"Remove role <strong>#{h step[1].to_sym.inspect}</strong>#{dont_remove} from <strong>#{h readable_step_info(step[2])}</strong>"
|
113
|
+
else
|
114
|
+
step.collect {|info| readable_step_info(info) }.map {|str| h str } * ', '
|
115
|
+
end + prohibit_link(step, options[:with_removal] ? "#{escape_javascript(describe_step(step))}" : '',
|
116
|
+
"Don't suggest this action.", options)
|
117
|
+
end
|
118
|
+
|
119
|
+
def prohibit_link (step, text, title, options)
|
120
|
+
options[:with_removal] ?
|
121
|
+
link_to_function("[x]", "prohibit_action('#{serialize_action(step)}', '#{text}')",
|
122
|
+
:class => 'prohibit', :title => title) :
|
123
|
+
''
|
124
|
+
end
|
125
|
+
|
126
|
+
def readable_step_info (info)
|
127
|
+
case info
|
128
|
+
when Symbol then info.inspect
|
129
|
+
when User then info.login
|
130
|
+
else info.to_sym.inspect
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def serialize_changes (approach)
|
135
|
+
changes = approach.changes.collect {|step| step.to_a.first.is_a?(Enumerable) ? step.to_a : [step.to_a]}
|
136
|
+
changes.collect {|multi_step| multi_step.collect {|step| serialize_action(step) }}.flatten * ';'
|
137
|
+
end
|
138
|
+
|
139
|
+
def serialize_action (step)
|
140
|
+
step.collect {|info| readable_step_info(info) } * ','
|
141
|
+
end
|
142
|
+
|
143
|
+
def serialize_relevant_roles (approach)
|
144
|
+
{:filter_roles => (Authorization::DevelopmentSupport::AnalyzerEngine.relevant_roles(approach.engine, approach.users).
|
145
|
+
map(&:to_sym) + [:new_role_for_change_analyzer]).uniq}.to_param
|
146
|
+
end
|
147
|
+
|
148
|
+
def has_changed (*args)
|
149
|
+
@changes && @changes[args[0]] && @changes[args[0]].include?(args[1..-1])
|
150
|
+
end
|
151
|
+
|
152
|
+
def affected_users_count (approach)
|
153
|
+
@affected_users[approach]
|
154
|
+
end
|
155
|
+
|
156
|
+
def auth_usage_info_classes (auth_info)
|
157
|
+
classes = []
|
158
|
+
if auth_info[:controller_permissions]
|
159
|
+
if auth_info[:controller_permissions][0]
|
160
|
+
classes << "catch-all" if auth_info[:controller_permissions][0].actions.include?(:all)
|
161
|
+
classes << "default-privilege" unless auth_info[:controller_permissions][0].privilege
|
162
|
+
classes << "default-context" unless auth_info[:controller_permissions][0].context
|
163
|
+
classes << "no-attribute-check" unless auth_info[:controller_permissions][0].attribute_check
|
164
|
+
end
|
165
|
+
else
|
166
|
+
classes << "unprotected"
|
167
|
+
end
|
168
|
+
classes * " "
|
169
|
+
end
|
170
|
+
|
171
|
+
def auth_usage_info_title (auth_info)
|
172
|
+
titles = []
|
173
|
+
if auth_usage_info_classes(auth_info) =~ /unprotected/
|
174
|
+
titles << "No filter_access_to call protects this action"
|
175
|
+
end
|
176
|
+
if auth_usage_info_classes(auth_info) =~ /no-attribute-check/
|
177
|
+
titles << "Action is not protected with attribute check"
|
178
|
+
end
|
179
|
+
if auth_usage_info_classes(auth_info) =~ /default-privilege/
|
180
|
+
titles << "Privilege set automatically from action name by :all rule"
|
181
|
+
end
|
182
|
+
if auth_usage_info_classes(auth_info) =~ /default-context/
|
183
|
+
titles << "Context set automatically from controller name by filter_access_to call without :context option"
|
184
|
+
end
|
185
|
+
titles * ". "
|
186
|
+
end
|
187
|
+
end
|