uhees-declarative_authorization 0.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.
Files changed (42) hide show
  1. data/CHANGELOG +77 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +490 -0
  4. data/Rakefile +43 -0
  5. data/app/controllers/authorization_rules_controller.rb +235 -0
  6. data/app/controllers/authorization_usages_controller.rb +23 -0
  7. data/app/helpers/authorization_rules_helper.rb +183 -0
  8. data/app/views/authorization_rules/_change.erb +49 -0
  9. data/app/views/authorization_rules/_show_graph.erb +37 -0
  10. data/app/views/authorization_rules/_suggestion.erb +9 -0
  11. data/app/views/authorization_rules/_suggestions.erb +24 -0
  12. data/app/views/authorization_rules/change.html.erb +124 -0
  13. data/app/views/authorization_rules/graph.dot.erb +68 -0
  14. data/app/views/authorization_rules/graph.html.erb +40 -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 +7 -0
  19. data/garlic_example.rb +20 -0
  20. data/init.rb +5 -0
  21. data/lib/declarative_authorization.rb +15 -0
  22. data/lib/declarative_authorization/authorization.rb +630 -0
  23. data/lib/declarative_authorization/development_support/analyzer.rb +252 -0
  24. data/lib/declarative_authorization/development_support/change_analyzer.rb +253 -0
  25. data/lib/declarative_authorization/development_support/change_supporter.rb +578 -0
  26. data/lib/declarative_authorization/development_support/development_support.rb +243 -0
  27. data/lib/declarative_authorization/helper.rb +60 -0
  28. data/lib/declarative_authorization/in_controller.rb +367 -0
  29. data/lib/declarative_authorization/in_model.rb +150 -0
  30. data/lib/declarative_authorization/maintenance.rb +188 -0
  31. data/lib/declarative_authorization/obligation_scope.rb +297 -0
  32. data/lib/declarative_authorization/rails_legacy.rb +14 -0
  33. data/lib/declarative_authorization/reader.rb +438 -0
  34. data/test/authorization_test.rb +823 -0
  35. data/test/controller_test.rb +418 -0
  36. data/test/dsl_reader_test.rb +157 -0
  37. data/test/helper_test.rb +154 -0
  38. data/test/maintenance_test.rb +41 -0
  39. data/test/model_test.rb +1171 -0
  40. data/test/schema.sql +53 -0
  41. data/test/test_helper.rb +103 -0
  42. metadata +104 -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,235 @@
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 {|priv| Authorization::DevelopmentSupport::AnalyzerEngine::Privilege.for_sym(priv, authorization_engine).descendants.map(&:to_sym) }.flatten.uniq
39
+ @privileges.sort_by {|priv| priv.to_s}
40
+ @privilege = params[:privilege].to_sym rescue @privileges.first
41
+ @contexts = authorization_engine.auth_rules.collect {|rule| rule.contexts.to_a}.flatten.uniq
42
+ @context = params[:context].to_sym rescue @contexts.first
43
+
44
+ respond_to do |format|
45
+ format.html
46
+ format.js do
47
+ render :partial => 'change'
48
+ end
49
+ end
50
+ end
51
+
52
+ def suggest_change
53
+ users_permission = params[:user].inject({}) do |memo, (user_id, data)|
54
+ if data[:permission] != "undetermined"
55
+ begin
56
+ memo[find_user_by_id(user_id)] = (data[:permission] == 'yes')
57
+ rescue ActiveRecord::NotFound
58
+ end
59
+ end
60
+ memo
61
+ end
62
+
63
+ prohibited_actions = (params[:prohibited_action] || []).collect do |spec|
64
+ deserialize_changes(spec).flatten
65
+ end
66
+
67
+ users_keys = users_permission.keys
68
+ analyzer = Authorization::DevelopmentSupport::ChangeSupporter.new(authorization_engine)
69
+
70
+ privilege = params[:privilege].to_sym
71
+ context = params[:context].to_sym
72
+ @context = context
73
+ @approaches = analyzer.find_approaches_for(:users => users_keys, :prohibited_actions => prohibited_actions) do
74
+ users.each_with_index do |user, idx|
75
+ args = [privilege, {:context => context, :user => user}]
76
+ assert(users_permission[users_keys[idx]] ? permit?(*args) : !permit?(*args))
77
+ end
78
+ end
79
+
80
+ respond_to do |format|
81
+ format.js do
82
+ render :partial => 'suggestions'
83
+ end
84
+ end
85
+ end
86
+
87
+ private
88
+ def auth_to_dot (options = {})
89
+ options = {
90
+ :effective_role_privs => true,
91
+ :privilege_hierarchy => false,
92
+ :stacked_roles => false,
93
+ :only_relevant_contexts => true,
94
+ :only_relevant_roles => false,
95
+ :filter_roles => nil,
96
+ :filter_contexts => nil,
97
+ :highlight_privilege => nil,
98
+ :changes => nil,
99
+ :users => nil
100
+ }.merge(options)
101
+
102
+ @has_changes = options[:changes] && !options[:changes].empty?
103
+ @highlight_privilege = options[:highlight_privilege]
104
+ @stacked_roles = options[:stacked_roles]
105
+
106
+ @users = options[:users]
107
+
108
+ engine = authorization_engine.clone
109
+ @changes = replay_changes(engine, @users, options[:changes]) if options[:changes]
110
+
111
+ options[:filter_roles] ||= @users.collect {|user| user.role_symbols}.flatten.uniq if options[:only_relevant_roles] and @users
112
+
113
+ filter_roles_flattened = nil
114
+ if options[:filter_roles]
115
+ filter_roles_flattened = options[:filter_roles].collect do |role_sym|
116
+ Authorization::DevelopmentSupport::AnalyzerEngine::Role.for_sym(role_sym, engine).
117
+ ancestors.map(&:to_sym) + [role_sym]
118
+ end.flatten.uniq
119
+ end
120
+
121
+ @roles = engine.roles
122
+ @roles = @roles.select {|r| filter_roles_flattened.include?(r) } if options[:filter_roles]
123
+ @role_hierarchy = engine.role_hierarchy
124
+ @privilege_hierarchy = engine.privilege_hierarchy
125
+
126
+ @contexts = engine.auth_rules.
127
+ collect {|ar| ar.contexts.to_a}.flatten.uniq
128
+ @contexts = @contexts.select {|c| c == options[:filter_contexts] } if options[:filter_contexts]
129
+ @context_privs = {}
130
+ @role_privs = {}
131
+ engine.auth_rules.each do |auth_rule|
132
+ @role_privs[auth_rule.role] ||= []
133
+ auth_rule.contexts.
134
+ select {|c| options[:filter_contexts].nil? or c == options[:filter_contexts]}.
135
+ each do |context|
136
+ @context_privs[context] ||= []
137
+ @context_privs[context] += auth_rule.privileges.to_a
138
+ @context_privs[context].uniq!
139
+ @role_privs[auth_rule.role] += auth_rule.privileges.collect {|p| [context, p, auth_rule.attributes.empty?, auth_rule.to_long_s]}
140
+ end
141
+ end
142
+
143
+ if options[:effective_role_privs]
144
+ @roles.each do |role|
145
+ role = Authorization::DevelopmentSupport::AnalyzerEngine::Role.for_sym(role, engine)
146
+ @role_privs[role.to_sym] ||= []
147
+ role.ancestors.each do |lower_role|
148
+ @role_privs[role.to_sym].concat(@role_privs[lower_role.to_sym]).uniq!
149
+ end
150
+ end
151
+ end
152
+
153
+ @roles.delete_if do |role|
154
+ role = Authorization::DevelopmentSupport::AnalyzerEngine::Role.for_sym(role, engine)
155
+ ([role] + role.ancestors).all? {|inner_role| @role_privs[inner_role.to_sym].blank? }
156
+ end
157
+
158
+ if options[:only_relevant_contexts]
159
+ @contexts.delete_if do |context|
160
+ @roles.all? {|role| !@role_privs[role] || !@role_privs[role].any? {|info| info[0] == context}}
161
+ end
162
+ end
163
+
164
+ if options[:privilege_hierarchy]
165
+ @context_privs.each do |context, privs|
166
+ privs.each do |priv|
167
+ context_lower_privs = (@privilege_hierarchy[priv] || []).
168
+ select {|p,c| c.nil? or c == context}.
169
+ collect {|p,c| p}
170
+ privs.concat(context_lower_privs).uniq!
171
+ end
172
+ end
173
+ end
174
+
175
+ render_to_string :template => 'authorization_rules/graph.dot.erb', :layout => false
176
+ end
177
+
178
+ def replay_changes (engine, users, changes)
179
+ changes.inject({}) do |memo, info|
180
+ case info[0]
181
+ when :add_privilege, :add_role
182
+ Authorization::DevelopmentSupport::AnalyzerEngine.apply_change(engine, info)
183
+ when :assign_role_to_user
184
+ user = users.find {|u| u.login == info[2]}
185
+ user.role_symbols << info[1] if user
186
+ end
187
+ (memo[info[0]] ||= Set.new) << info[1..-1]
188
+ memo
189
+ end
190
+ end
191
+
192
+ def dot_to_svg (dot_data)
193
+ gv = IO.popen("#{Authorization.dot_path} -q -Tsvg", "w+")
194
+ gv.puts dot_data
195
+ gv.close_write
196
+ gv.read
197
+ rescue IOError, Errno::EPIPE => e
198
+ raise Exception, "Error in call to graphviz: #{e}"
199
+ end
200
+
201
+ def graph_options
202
+ {
203
+ :effective_role_privs => !params[:effective_role_privs].blank?,
204
+ :privilege_hierarchy => !params[:privilege_hierarchy].blank?,
205
+ :stacked_roles => !params[:stacked_roles].blank?,
206
+ :only_relevant_roles => !params[:only_relevant_roles].blank?,
207
+ :filter_roles => params[:filter_roles].blank? ? nil : (params[:filter_roles].is_a?(Array) ? params[:filter_roles].map(&:to_sym) : [params[:filter_roles].to_sym]),
208
+ :filter_contexts => params[:filter_contexts].blank? ? nil : params[:filter_contexts].to_sym,
209
+ :highlight_privilege => params[:highlight_privilege].blank? ? nil : params[:highlight_privilege].to_sym,
210
+ :changes => deserialize_changes(params[:changes]),
211
+ :users => params[:user_ids] && params[:user_ids].collect {|user_id| find_user_by_id(user_id)}
212
+ }
213
+ end
214
+
215
+ def deserialize_changes (changes)
216
+ if changes
217
+ changes.split(';').collect do |info|
218
+ info.split(',').collect do |info_part|
219
+ info_part[0,1] == ':' ? info_part[1..-1].to_sym : info_part
220
+ end
221
+ end
222
+ end
223
+ end
224
+
225
+ def find_user_by_id (id)
226
+ User.find(id)
227
+ end
228
+ def find_all_users
229
+ User.all.select {|user| !user.login.blank?}
230
+ end
231
+ end
232
+
233
+ else
234
+ class AuthorizationRulesController < ApplicationController; end
235
+ 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,183 @@
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.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 Supporter", 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 => 'unimportant', :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 auth_usage_info_classes (auth_info)
153
+ classes = []
154
+ if auth_info[:controller_permissions]
155
+ if auth_info[:controller_permissions][0]
156
+ classes << "catch-all" if auth_info[:controller_permissions][0].actions.include?(:all)
157
+ classes << "default-privilege" unless auth_info[:controller_permissions][0].privilege
158
+ classes << "default-context" unless auth_info[:controller_permissions][0].context
159
+ classes << "no-attribute-check" unless auth_info[:controller_permissions][0].attribute_check
160
+ end
161
+ else
162
+ classes << "unprotected"
163
+ end
164
+ classes * " "
165
+ end
166
+
167
+ def auth_usage_info_title (auth_info)
168
+ titles = []
169
+ if auth_usage_info_classes(auth_info) =~ /unprotected/
170
+ titles << "No filter_access_to call protects this action"
171
+ end
172
+ if auth_usage_info_classes(auth_info) =~ /no-attribute-check/
173
+ titles << "Action is not protected with attribute check"
174
+ end
175
+ if auth_usage_info_classes(auth_info) =~ /default-privilege/
176
+ titles << "Privilege set automatically from action name by :all rule"
177
+ end
178
+ if auth_usage_info_classes(auth_info) =~ /default-context/
179
+ titles << "Context set automatically from controller name by filter_access_to call without :context option"
180
+ end
181
+ titles * ". "
182
+ end
183
+ end