zeiv-declarative_authorization 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +189 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +632 -0
  5. data/Rakefile +53 -0
  6. data/app/controllers/authorization_rules_controller.rb +258 -0
  7. data/app/controllers/authorization_usages_controller.rb +22 -0
  8. data/app/helpers/authorization_rules_helper.rb +218 -0
  9. data/app/views/authorization_rules/_change.erb +58 -0
  10. data/app/views/authorization_rules/_show_graph.erb +44 -0
  11. data/app/views/authorization_rules/_suggestions.erb +48 -0
  12. data/app/views/authorization_rules/change.html.erb +169 -0
  13. data/app/views/authorization_rules/graph.dot.erb +68 -0
  14. data/app/views/authorization_rules/graph.html.erb +47 -0
  15. data/app/views/authorization_rules/index.html.erb +17 -0
  16. data/app/views/authorization_usages/index.html.erb +36 -0
  17. data/authorization_rules.dist.rb +20 -0
  18. data/config/routes.rb +20 -0
  19. data/garlic_example.rb +20 -0
  20. data/init.rb +5 -0
  21. data/lib/declarative_authorization.rb +19 -0
  22. data/lib/declarative_authorization/adapters/active_record.rb +13 -0
  23. data/lib/declarative_authorization/adapters/active_record/base_extensions.rb +0 -0
  24. data/lib/declarative_authorization/adapters/active_record/obligation_scope_builder.rb +0 -0
  25. data/lib/declarative_authorization/authorization.rb +798 -0
  26. data/lib/declarative_authorization/development_support/analyzer.rb +261 -0
  27. data/lib/declarative_authorization/development_support/change_analyzer.rb +253 -0
  28. data/lib/declarative_authorization/development_support/change_supporter.rb +620 -0
  29. data/lib/declarative_authorization/development_support/development_support.rb +243 -0
  30. data/lib/declarative_authorization/helper.rb +68 -0
  31. data/lib/declarative_authorization/in_controller.rb +703 -0
  32. data/lib/declarative_authorization/in_model.rb +188 -0
  33. data/lib/declarative_authorization/maintenance.rb +210 -0
  34. data/lib/declarative_authorization/obligation_scope.rb +361 -0
  35. data/lib/declarative_authorization/rails_legacy.rb +22 -0
  36. data/lib/declarative_authorization/railsengine.rb +6 -0
  37. data/lib/declarative_authorization/reader.rb +546 -0
  38. data/lib/generators/authorization/install/install_generator.rb +77 -0
  39. data/lib/generators/authorization/rules/rules_generator.rb +14 -0
  40. data/lib/generators/authorization/rules/templates/authorization_rules.rb +27 -0
  41. data/lib/tasks/authorization_tasks.rake +89 -0
  42. data/test/authorization_test.rb +1124 -0
  43. data/test/controller_filter_resource_access_test.rb +575 -0
  44. data/test/controller_test.rb +480 -0
  45. data/test/database.yml +3 -0
  46. data/test/dsl_reader_test.rb +178 -0
  47. data/test/helper_test.rb +247 -0
  48. data/test/maintenance_test.rb +46 -0
  49. data/test/model_test.rb +2008 -0
  50. data/test/schema.sql +56 -0
  51. data/test/test_helper.rb +255 -0
  52. metadata +95 -0
@@ -0,0 +1,53 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rdoc/task'
4
+
5
+ desc 'Default: run unit tests against all versions.'
6
+ task :default => 'bundles:test'
7
+
8
+ def run_for_bundles cmd
9
+ Dir['gemfiles/*.gemfile'].each do |gemfile|
10
+ puts "\n#{gemfile}: #{cmd}"
11
+ ENV['BUNDLE_GEMFILE'] = gemfile
12
+ system(cmd)
13
+ end
14
+ end
15
+
16
+ task 'bundles:install' do
17
+ run_for_bundles 'bundle install'
18
+ end
19
+ task 'bundles:update' do
20
+ run_for_bundles 'bundle update'
21
+ end
22
+ task 'bundles:test' do
23
+ run_for_bundles 'bundle exec rake test'
24
+ end
25
+
26
+ desc 'Test the authorization plugin.'
27
+ Rake::TestTask.new(:test) do |t|
28
+ t.libs << 'lib' << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = true
31
+ end
32
+
33
+ desc 'Generate documentation for the authorization plugin.'
34
+ Rake::RDocTask.new(:rdoc) do |rdoc|
35
+ rdoc.rdoc_dir = 'rdoc'
36
+ rdoc.title = 'Authorization'
37
+ rdoc.options << '--line-numbers' << '--inline-source'
38
+ rdoc.options << '--charset' << 'utf-8'
39
+ rdoc.rdoc_files.include('README.rdoc')
40
+ rdoc.rdoc_files.include('CHANGELOG')
41
+ rdoc.rdoc_files.include('lib/**/*.rb')
42
+ end
43
+
44
+ # load up garlic if it's here
45
+ if File.directory?(File.join(File.dirname(__FILE__), 'garlic'))
46
+ require File.join(File.dirname(__FILE__), 'garlic/lib/garlic_tasks')
47
+ require File.join(File.dirname(__FILE__), 'garlic')
48
+ end
49
+
50
+ desc "clone the garlic repo (for running ci tasks)"
51
+ task :get_garlic do
52
+ sh "git clone git://github.com/ianwhite/garlic.git garlic"
53
+ end
@@ -0,0 +1,258 @@
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
+
16
+ filter_access_to :all, :require => :read
17
+ def index
18
+ respond_to do |format|
19
+ format.html do
20
+ @auth_rules_script = File.read("#{::Rails.root}/config/authorization_rules.rb")
21
+ end
22
+ end
23
+ end
24
+
25
+ def graph
26
+ if params[:format] == "svg"
27
+ render :text => dot_to_svg(auth_to_dot(graph_options)),
28
+ :content_type => "image/svg+xml"
29
+ end
30
+ end
31
+
32
+ def change
33
+ @users = find_all_users
34
+ @users.sort! {|a, b| a.login <=> b.login }
35
+
36
+ @privileges = authorization_engine.auth_rules.collect {|rule| rule.privileges.to_a}.flatten.uniq
37
+ @privileges = @privileges.collect do |priv|
38
+ priv = Authorization::DevelopmentSupport::AnalyzerEngine::Privilege.for_sym(priv, authorization_engine)
39
+ ([priv] + priv.descendants + priv.ancestors).map(&:to_sym)
40
+ end.flatten.uniq
41
+ @privileges.sort_by {|priv| priv.to_s}
42
+ @privilege = params[:privilege].to_sym rescue @privileges.first
43
+ @contexts = authorization_engine.auth_rules.collect {|rule| rule.contexts.to_a}.flatten.uniq
44
+ @context = params[:context].to_sym rescue @contexts.first
45
+
46
+ respond_to do |format|
47
+ format.html
48
+ format.js do
49
+ render :partial => 'change'
50
+ end
51
+ end
52
+ end
53
+
54
+ def suggest_change
55
+ users_permission = params[:user].inject({}) do |memo, (user_id, data)|
56
+ if data[:permission] != "undetermined"
57
+ begin
58
+ memo[find_user_by_id(user_id)] = (data[:permission] == 'yes')
59
+ rescue ActiveRecord::NotFound
60
+ end
61
+ end
62
+ memo
63
+ end
64
+
65
+ prohibited_actions = (params[:prohibited_action] || []).collect do |spec|
66
+ deserialize_changes(spec).flatten
67
+ end
68
+
69
+ analyzer = Authorization::DevelopmentSupport::ChangeSupporter.new(authorization_engine)
70
+
71
+ privilege = params[:privilege].to_sym
72
+ context = params[:context].to_sym
73
+ all_users = User.all
74
+ @context = context
75
+ @approaches = analyzer.find_approaches_for(:users => all_users, :prohibited_actions => prohibited_actions) do
76
+ users.each_with_index do |user, idx|
77
+ unless users_permission[all_users[idx]].nil?
78
+ args = [privilege, {:context => context, :user => user}]
79
+ assert(users_permission[all_users[idx]] ? permit?(*args) : !permit?(*args))
80
+ end
81
+ end
82
+ end
83
+
84
+ @affected_users = @approaches.each_with_object({}) do |approach, memo|
85
+ memo[approach] = approach.affected_users(authorization_engine, all_users, privilege, context).length
86
+ end
87
+ max_affected_users = @affected_users.values.max
88
+ if params[:affected_users]
89
+ @approaches = @approaches.sort_by do |approach|
90
+ affected_users_count = @affected_users[approach]
91
+ if params[:affected_users] == "many"
92
+ #approach.weight.to_f / [affected_users_count, 0.1].min
93
+ approach.weight + (max_affected_users - affected_users_count) * 10
94
+ else
95
+ #approach.weight * affected_users_count
96
+ approach.weight + affected_users_count * 10
97
+ end
98
+ end
99
+ end
100
+
101
+ @grouped_approaches = analyzer.group_approaches(@approaches)
102
+
103
+ respond_to do |format|
104
+ format.js do
105
+ render :partial => 'suggestions'
106
+ end
107
+ end
108
+ end
109
+
110
+ private
111
+ def auth_to_dot (options = {})
112
+ options = {
113
+ :effective_role_privs => true,
114
+ :privilege_hierarchy => false,
115
+ :stacked_roles => false,
116
+ :only_relevant_contexts => true,
117
+ :only_relevant_roles => false,
118
+ :filter_roles => nil,
119
+ :filter_contexts => nil,
120
+ :highlight_privilege => nil,
121
+ :changes => nil,
122
+ :users => nil
123
+ }.merge(options)
124
+
125
+ @has_changes = options[:changes] && !options[:changes].empty?
126
+ @highlight_privilege = options[:highlight_privilege]
127
+ @stacked_roles = options[:stacked_roles]
128
+
129
+ @users = options[:users]
130
+
131
+ engine = authorization_engine.clone
132
+ @changes = replay_changes(engine, @users, options[:changes]) if options[:changes]
133
+
134
+ options[:filter_roles] ||= @users.collect {|user| user.role_symbols}.flatten.uniq if options[:only_relevant_roles] and @users
135
+
136
+ filter_roles_flattened = nil
137
+ if options[:filter_roles]
138
+ filter_roles_flattened = options[:filter_roles].collect do |role_sym|
139
+ Authorization::DevelopmentSupport::AnalyzerEngine::Role.for_sym(role_sym, engine).
140
+ ancestors.map(&:to_sym) + [role_sym]
141
+ end.flatten.uniq
142
+ end
143
+
144
+ @roles = engine.roles
145
+ @roles = @roles.select {|r| filter_roles_flattened.include?(r) } if options[:filter_roles]
146
+ @role_hierarchy = engine.role_hierarchy
147
+ @privilege_hierarchy = engine.privilege_hierarchy
148
+
149
+ @contexts = engine.auth_rules.
150
+ collect {|ar| ar.contexts.to_a}.flatten.uniq
151
+ @contexts = @contexts.select {|c| c == options[:filter_contexts] } if options[:filter_contexts]
152
+ @context_privs = {}
153
+ @role_privs = {}
154
+ engine.auth_rules.each do |auth_rule|
155
+ @role_privs[auth_rule.role] ||= []
156
+ auth_rule.contexts.
157
+ select {|c| options[:filter_contexts].nil? or c == options[:filter_contexts]}.
158
+ each do |context|
159
+ @context_privs[context] ||= []
160
+ @context_privs[context] += auth_rule.privileges.to_a
161
+ @context_privs[context].uniq!
162
+ @role_privs[auth_rule.role] += auth_rule.privileges.collect {|p| [context, p, auth_rule.attributes.empty?, auth_rule.to_long_s]}
163
+ end
164
+ end
165
+
166
+ if options[:effective_role_privs]
167
+ @roles.each do |role|
168
+ role = Authorization::DevelopmentSupport::AnalyzerEngine::Role.for_sym(role, engine)
169
+ @role_privs[role.to_sym] ||= []
170
+ role.ancestors.each do |lower_role|
171
+ @role_privs[role.to_sym].concat(@role_privs[lower_role.to_sym]).uniq!
172
+ end
173
+ end
174
+ end
175
+
176
+ @roles.delete_if do |role|
177
+ role = Authorization::DevelopmentSupport::AnalyzerEngine::Role.for_sym(role, engine)
178
+ ([role] + role.ancestors).all? {|inner_role| @role_privs[inner_role.to_sym].blank? }
179
+ end
180
+
181
+ if options[:only_relevant_contexts]
182
+ @contexts.delete_if do |context|
183
+ @roles.all? {|role| !@role_privs[role] || !@role_privs[role].any? {|info| info[0] == context}}
184
+ end
185
+ end
186
+
187
+ if options[:privilege_hierarchy]
188
+ @context_privs.each do |context, privs|
189
+ privs.each do |priv|
190
+ context_lower_privs = (@privilege_hierarchy[priv] || []).
191
+ select {|p,c| c.nil? or c == context}.
192
+ collect {|p,c| p}
193
+ privs.concat(context_lower_privs).uniq!
194
+ end
195
+ end
196
+ end
197
+
198
+ render_to_string :template => 'authorization_rules/graph.dot.erb', :layout => false
199
+ end
200
+
201
+ def replay_changes (engine, users, changes)
202
+ changes.inject({}) do |memo, info|
203
+ case info[0]
204
+ when :add_privilege, :add_role
205
+ Authorization::DevelopmentSupport::AnalyzerEngine.apply_change(engine, info)
206
+ when :assign_role_to_user
207
+ user = users.find {|u| u.login == info[2]}
208
+ user.role_symbols << info[1] if user
209
+ end
210
+ (memo[info[0]] ||= Set.new) << info[1..-1]
211
+ memo
212
+ end
213
+ end
214
+
215
+ def dot_to_svg (dot_data)
216
+ gv = IO.popen("#{Authorization.dot_path} -q -Tsvg", "w+")
217
+ gv.puts dot_data
218
+ gv.close_write
219
+ gv.read
220
+ rescue IOError, Errno::EPIPE => e
221
+ raise Exception, "Error in call to graphviz: #{e}"
222
+ end
223
+
224
+ def graph_options
225
+ {
226
+ :effective_role_privs => !params[:effective_role_privs].blank?,
227
+ :privilege_hierarchy => !params[:privilege_hierarchy].blank?,
228
+ :stacked_roles => !params[:stacked_roles].blank?,
229
+ :only_relevant_roles => !params[:only_relevant_roles].blank?,
230
+ :filter_roles => params[:filter_roles].blank? ? nil : (params[:filter_roles].is_a?(Array) ? params[:filter_roles].map(&:to_sym) : [params[:filter_roles].to_sym]),
231
+ :filter_contexts => params[:filter_contexts].blank? ? nil : params[:filter_contexts].to_sym,
232
+ :highlight_privilege => params[:highlight_privilege].blank? ? nil : params[:highlight_privilege].to_sym,
233
+ :changes => deserialize_changes(params[:changes]),
234
+ :users => params[:user_ids] && params[:user_ids].collect {|user_id| find_user_by_id(user_id)}
235
+ }
236
+ end
237
+
238
+ def deserialize_changes (changes)
239
+ if changes
240
+ changes.split(';').collect do |info|
241
+ info.split(',').collect do |info_part|
242
+ info_part[0,1] == ':' ? info_part[1..-1].to_sym : info_part
243
+ end
244
+ end
245
+ end
246
+ end
247
+
248
+ def find_user_by_id (id)
249
+ User.find(id)
250
+ end
251
+ def find_all_users
252
+ User.all.select {|user| !user.login.blank?}
253
+ end
254
+ end
255
+
256
+ else
257
+ class AuthorizationRulesController < ApplicationController; end
258
+ end # activate_authorization_rules_browser?
@@ -0,0 +1,22 @@
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
+
7
+ helper :authorization_rules
8
+ filter_access_to :all, :require => :read
9
+ # TODO set context?
10
+
11
+ def index
12
+ respond_to do |format|
13
+ format.html do
14
+ @auth_usages_by_controller = Authorization::Maintenance::Usage.usages_by_controller
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ else
21
+ class AuthorizationUsagesController < ApplicationController; end
22
+ 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', /()(=&gt;)/, /()(\{)/, /()(\})/, /()(\[)/, /()(\])/],
10
+ :comment => [/()(#.*$)/]#,
11
+ #:privilege => [:read],
12
+ #:context => [:conferences]
13
+ }
14
+ regexps.each do |name, res|
15
+ res.each do |re|
16
+ rules = 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").html_safe
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