rubycs-declarative_authorization 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +70 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +9 -0
- data/Rakefile +43 -0
- data/app/controllers/authorization_rules_controller.rb +114 -0
- data/app/controllers/authorization_usages_controller.rb +23 -0
- data/app/helpers/authorization_rules_helper.rb +100 -0
- data/app/views/authorization_rules/graph.dot.erb +49 -0
- data/app/views/authorization_rules/graph.html.erb +39 -0
- data/app/views/authorization_rules/index.html.erb +16 -0
- data/app/views/authorization_usages/index.html.erb +45 -0
- data/authorization_rules.dist.rb +20 -0
- data/config/locales/en.declarative_authorization.yml +35 -0
- data/config/locales/ro.declarative_authorization.yml +35 -0
- data/config/routes.rb +6 -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 +578 -0
- data/lib/declarative_authorization/authorization_rules_analyzer.rb +138 -0
- data/lib/declarative_authorization/helper.rb +56 -0
- data/lib/declarative_authorization/in_controller.rb +343 -0
- data/lib/declarative_authorization/in_model.rb +125 -0
- data/lib/declarative_authorization/maintenance.rb +174 -0
- data/lib/declarative_authorization/obligation_scope.rb +292 -0
- data/lib/declarative_authorization/rails_legacy.rb +14 -0
- data/lib/declarative_authorization/reader.rb +430 -0
- data/test/authorization_rules_analyzer_test.rb +123 -0
- data/test/authorization_test.rb +779 -0
- data/test/controller_test.rb +361 -0
- data/test/dsl_reader_test.rb +157 -0
- data/test/helper_test.rb +133 -0
- data/test/maintenance_test.rb +15 -0
- data/test/model_test.rb +1143 -0
- data/test/schema.sql +53 -0
- data/test/test_helper.rb +99 -0
- metadata +97 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
|
2
|
+
** RELEASE 0.3 (April 20, 2009) **
|
3
|
+
|
4
|
+
* New option :join_by for has_permission_on to allow AND'ing of statements in one has_permission_on block [sb]
|
5
|
+
|
6
|
+
* Allow using_access_control to be called directly on ActiveRecord::Base, globally enabling model security [sb]
|
7
|
+
|
8
|
+
* New operator: intersects_with, comparing two Enumerables in if_attribute [sb]
|
9
|
+
|
10
|
+
* Improved if_permitted_to syntax: if the attribute is left out, permissions are checked on for the current object [sb]
|
11
|
+
|
12
|
+
* Added #has_role_with_hierarchy? method to retrieve explicit and calculated roles [jeremyf]
|
13
|
+
|
14
|
+
* Added a simple rules analyzer to help improve authorization rules [sb]
|
15
|
+
|
16
|
+
* Gemified plugin. Needed to restructure the lib path contents [sb]
|
17
|
+
|
18
|
+
* Added handling of Authorization::AuthorizationInController::ClassMethods.filter_access_to parameters that are of the form [:show, :update] instead of just :show, :update. [jeremyf]
|
19
|
+
|
20
|
+
* Added authorization usage helper for checking filter_access_to usage in controllers [sb]
|
21
|
+
|
22
|
+
* Added a authorization rules browser. See README for more information [sb]
|
23
|
+
|
24
|
+
* Added Model.using_access_control? to check if a model has model security activated [sb]
|
25
|
+
|
26
|
+
* Changed Authorization::ObligationScope#map_table_alias_for [Brian Langenfeld]
|
27
|
+
* Fixed to prevent bad aliases from being produced.
|
28
|
+
|
29
|
+
* Changed Authorization::Attribute#validate? [Brian Langenfeld]
|
30
|
+
* Encountering a nil value when evaluating an attribute now raises a NilAttributeValueError, instead of an AuthorizationError. We leave it to the caller to decide what to do about it.
|
31
|
+
|
32
|
+
* Changed Authorization::Engine#permit! [Brian Langenfeld]
|
33
|
+
* We now convert incoming privileges to symbols (e.g. 'read' is made equivalent to :read). This ensures the privileges will match those defined in the authorization rules file.
|
34
|
+
* The method now properly infers context when checking against an association (e.g. user.posts). We do this by leveraging ActiveRecord builder method 'new' to instantiate a proper object we can work with.
|
35
|
+
* When testing rules for positive results (via Authorization::Attribute#validate?), we now rescue NilAttributeValueError exceptions, simply causing the rule to return a negative result (instead of barfing).
|
36
|
+
|
37
|
+
* Changed Authorization::ObligationScope#rebuild_join_options! [Brian Langenfeld]
|
38
|
+
* If we're dealing with multiple obligations we have to check (i.e. ones that result in OR'd conditions), we now use :include instead of :joins for our generated scope. This does seem like a kludge, but until ActiveRecord scopes support unions (for checking obligations individually and consolidating the results), we don't have much choice. Something to revisit later, for sure.
|
39
|
+
|
40
|
+
** RELEASE 0.2 (February 2, 2009) **
|
41
|
+
|
42
|
+
* added negative operators: is_not, not_in, does_not_contain [sb]
|
43
|
+
|
44
|
+
* changed user.roles to user.role_symbols to reduce interferance with associations [sb]
|
45
|
+
|
46
|
+
* Ruby 1.9 and Rails 2.3 compatibility [sb]
|
47
|
+
|
48
|
+
* if_permitted_to for has_permission_on blocks for DRYer auth rules [sb]
|
49
|
+
|
50
|
+
* ObligationScope rewrite of query rewriting [Brian Langenfeld]
|
51
|
+
|
52
|
+
* changed exception hierarchy to begin at StandardError [sb]
|
53
|
+
|
54
|
+
* :is_in operator [sb]
|
55
|
+
|
56
|
+
* added has_role? helper [sb]
|
57
|
+
|
58
|
+
* made plugin thread-safe [sb]
|
59
|
+
|
60
|
+
* added maintenance and test helpers [sb]
|
61
|
+
|
62
|
+
* changed default permission denied response to 403 Forbidden [sb]
|
63
|
+
|
64
|
+
* descriptions for titles and roles [sb]
|
65
|
+
|
66
|
+
* fixed for PostgreSQL [Mark Mansour]
|
67
|
+
|
68
|
+
* improved DSL syntax: allow for array of contexts in has_permission_on [sb]
|
69
|
+
|
70
|
+
** RELEASE 0.1 (August 22, 2008) **
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 [name of plugin creator]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
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,114 @@
|
|
1
|
+
if Authorization::activate_authorization_rules_browser?
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), %w{.. .. lib declarative_authorization authorization_rules_analyzer})
|
4
|
+
|
5
|
+
begin
|
6
|
+
# for nice auth_rules output:
|
7
|
+
require "parse_tree"
|
8
|
+
require "parse_tree_extensions"
|
9
|
+
require "ruby2ruby"
|
10
|
+
rescue LoadError; end
|
11
|
+
|
12
|
+
class AuthorizationRulesController < ApplicationController
|
13
|
+
unloadable
|
14
|
+
|
15
|
+
filter_access_to :all, :require => :read
|
16
|
+
def index
|
17
|
+
respond_to do |format|
|
18
|
+
format.html do
|
19
|
+
@auth_rules_script = File.read("#{RAILS_ROOT}/config/authorization_rules.rb")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def graph
|
25
|
+
if params[:format] == "svg"
|
26
|
+
render :text => dot_to_svg(auth_to_dot(graph_options)),
|
27
|
+
:content_type => "image/svg+xml"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def auth_to_dot (options = {})
|
33
|
+
options = {
|
34
|
+
:effective_role_privs => true,
|
35
|
+
:privilege_hierarchy => false,
|
36
|
+
:only_relevant_contexts => true,
|
37
|
+
:filter_roles => nil,
|
38
|
+
:filter_contexts => nil,
|
39
|
+
:highlight_privilege => nil
|
40
|
+
}.merge(options)
|
41
|
+
|
42
|
+
@highlight_privilege = options[:highlight_privilege]
|
43
|
+
@roles = authorization_engine.roles
|
44
|
+
@roles = @roles.select {|r| r == options[:filter_roles] } if options[:filter_roles]
|
45
|
+
@role_hierarchy = authorization_engine.role_hierarchy
|
46
|
+
@privilege_hierarchy = authorization_engine.privilege_hierarchy
|
47
|
+
|
48
|
+
@contexts = authorization_engine.auth_rules.
|
49
|
+
collect {|ar| ar.contexts.to_a}.flatten.uniq
|
50
|
+
@contexts = @contexts.select {|c| c == options[:filter_contexts] } if options[:filter_contexts]
|
51
|
+
@context_privs = {}
|
52
|
+
@role_privs = {}
|
53
|
+
authorization_engine.auth_rules.each do |auth_rule|
|
54
|
+
@role_privs[auth_rule.role] ||= []
|
55
|
+
auth_rule.contexts.
|
56
|
+
select {|c| options[:filter_contexts].nil? or c == options[:filter_contexts]}.
|
57
|
+
each do |context|
|
58
|
+
@context_privs[context] ||= []
|
59
|
+
@context_privs[context] += auth_rule.privileges.to_a
|
60
|
+
@context_privs[context].uniq!
|
61
|
+
@role_privs[auth_rule.role] += auth_rule.privileges.collect {|p| [context, p, auth_rule.attributes.empty?, auth_rule.to_long_s]}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
if options[:effective_role_privs]
|
66
|
+
@roles.each do |role|
|
67
|
+
@role_privs[role] ||= []
|
68
|
+
(@role_hierarchy[role] || []).each do |lower_role|
|
69
|
+
@role_privs[role].concat(@role_privs[lower_role]).uniq!
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
if options[:only_relevant_contexts]
|
75
|
+
@contexts.delete_if {|context| @roles.all? {|role| !@role_privs[role] || !@role_privs[role].any? {|info| info[0] == context}}}
|
76
|
+
end
|
77
|
+
|
78
|
+
if options[:privilege_hierarchy]
|
79
|
+
@context_privs.each do |context, privs|
|
80
|
+
privs.each do |priv|
|
81
|
+
context_lower_privs = (@privilege_hierarchy[priv] || []).
|
82
|
+
select {|p,c| c.nil? or c == context}.
|
83
|
+
collect {|p,c| p}
|
84
|
+
privs.concat(context_lower_privs).uniq!
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
render_to_string :template => 'authorization_rules/graph.dot.erb', :layout => false
|
90
|
+
end
|
91
|
+
|
92
|
+
def dot_to_svg (dot_data)
|
93
|
+
gv = IO.popen("#{Authorization.dot_path} -q -Tsvg", "w+")
|
94
|
+
gv.puts dot_data
|
95
|
+
gv.close_write
|
96
|
+
gv.read
|
97
|
+
rescue IOError, Errno::EPIPE => e
|
98
|
+
raise Exception, "#{I18n.t(:error_in_call_to_graphviz, :scope => [:declarative_authorization])}: #{e}"
|
99
|
+
end
|
100
|
+
|
101
|
+
def graph_options
|
102
|
+
{
|
103
|
+
:effective_role_privs => !params[:effective_role_privs].blank?,
|
104
|
+
:privilege_hierarchy => !params[:privilege_hierarchy].blank?,
|
105
|
+
:filter_roles => params[:filter_roles].blank? ? nil : params[:filter_roles].to_sym,
|
106
|
+
:filter_contexts => params[:filter_contexts].blank? ? nil : params[:filter_contexts].to_sym,
|
107
|
+
:highlight_privilege => params[:highlight_privilege].blank? ? nil : params[:highlight_privilege].to_sym
|
108
|
+
}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
else
|
113
|
+
class AuthorizationRulesController < ApplicationController; end
|
114
|
+
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,100 @@
|
|
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', 'includes', 'privilege', 'to'],
|
7
|
+
:operator => ['is', 'contains'],
|
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::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] ||= []
|
31
|
+
memo[report.line] << report
|
32
|
+
memo
|
33
|
+
end
|
34
|
+
reports_by_line.each do |line, reports|
|
35
|
+
note = %Q{<span class="note" title="#{reports.first.type}: #{reports.first.message}">[i]</span>}
|
36
|
+
marked_up_by_line[line - 1] = note + marked_up_by_line[line - 1]
|
37
|
+
end
|
38
|
+
marked_up_by_line * "\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
def link_to_graph (title, options = {})
|
42
|
+
type = options[:type] || ''
|
43
|
+
link_to_function title, "$$('object')[0].data = '#{url_for :action => 'index', :format => 'svg', :type => type}'"
|
44
|
+
end
|
45
|
+
|
46
|
+
def navigation
|
47
|
+
link_to(I18n.t(:rules, :scope => [:declarative_authorization]), authorization_rules_path) << ' | ' <<
|
48
|
+
link_to(I18n.t(:graphical_view, :scope => [:declarative_authorization]), graph_authorization_rules_path) << ' | ' <<
|
49
|
+
link_to(I18n.t(:usages, :scope => [:declarative_authorization]), authorization_usages_path) #<< ' | ' <<
|
50
|
+
# 'Edit | ' <<
|
51
|
+
# link_to("XACML export", :action => 'index', :format => 'xacml')
|
52
|
+
end
|
53
|
+
|
54
|
+
def role_color (role, fill = false)
|
55
|
+
fill_colors = %w{#ffdddd #ddffdd #ddddff #ffffdd #ffddff #ddffff}
|
56
|
+
colors = %w{#dd0000 #00dd00 #0000dd #dddd00 #dd00dd #00dddd}
|
57
|
+
@@role_colors ||= {}
|
58
|
+
@@role_colors[role] ||= begin
|
59
|
+
idx = @@role_colors.length % colors.length
|
60
|
+
[colors[idx], fill_colors[idx]]
|
61
|
+
end
|
62
|
+
@@role_colors[role][fill ? 1 : 0]
|
63
|
+
end
|
64
|
+
|
65
|
+
def role_fill_color (role)
|
66
|
+
role_color(role, true)
|
67
|
+
end
|
68
|
+
|
69
|
+
def auth_usage_info_classes (auth_info)
|
70
|
+
classes = []
|
71
|
+
if auth_info[:controller_permissions]
|
72
|
+
if auth_info[:controller_permissions][0]
|
73
|
+
classes << "catch-all" if auth_info[:controller_permissions][0].actions.include?(:all)
|
74
|
+
classes << "default-privilege" unless auth_info[:controller_permissions][0].privilege
|
75
|
+
classes << "default-context" unless auth_info[:controller_permissions][0].context
|
76
|
+
classes << "no-attribute-check" unless auth_info[:controller_permissions][0].attribute_check
|
77
|
+
end
|
78
|
+
else
|
79
|
+
classes << "unprotected"
|
80
|
+
end
|
81
|
+
classes * " "
|
82
|
+
end
|
83
|
+
|
84
|
+
def auth_usage_info_title (auth_info)
|
85
|
+
titles = []
|
86
|
+
if auth_usage_info_classes(auth_info) =~ /unprotected/
|
87
|
+
titles << I18n.t(:no_filter_access_to_call_protects_this_action, :scope => [:declarative_authorization])
|
88
|
+
end
|
89
|
+
if auth_usage_info_classes(auth_info) =~ /no-attribute-check/
|
90
|
+
titles << I18n.t(:action_is_not_protected_with_attribute_check, :scope => [:declarative_authorization])
|
91
|
+
end
|
92
|
+
if auth_usage_info_classes(auth_info) =~ /default-privilege/
|
93
|
+
titles << I18n.t(:privilege_set_automatically_from_action_name_by_all_rule, :scope => [:declarative_authorization])
|
94
|
+
end
|
95
|
+
if auth_usage_info_classes(auth_info) =~ /default-context/
|
96
|
+
titles << I18n.t(:context_set_automatically_from_controller_name_by_filter_access_to_call_without_context_option, :scope => [:declarative_authorization])
|
97
|
+
end
|
98
|
+
titles * ". "
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
digraph rules {
|
3
|
+
compound = true
|
4
|
+
edge [arrowhead=open]
|
5
|
+
node [shape=box,fontname="sans-serif",fontsize="16"]
|
6
|
+
fontname="sans-serif";fontsize="16"
|
7
|
+
ranksep = "0.3"
|
8
|
+
//concentrate = true
|
9
|
+
rankdir = TB
|
10
|
+
{
|
11
|
+
node [shape=ellipse,style=filled]
|
12
|
+
//rank = source
|
13
|
+
<% @roles.each do |role| %>
|
14
|
+
"<%= role.inspect %>" [fillcolor="<%= role_fill_color(role) %>"]
|
15
|
+
// ,URL="javascript:set_filter({roles: '<%= role %>'})"
|
16
|
+
<% end %>
|
17
|
+
<% @roles.each do |role| %>
|
18
|
+
<% (@role_hierarchy[role] || []).each do |lower_role| %>
|
19
|
+
"<%= role.inspect %>" -> "<%= lower_role.inspect %>" [constraint=false,arrowhead=empty]
|
20
|
+
<% end %>
|
21
|
+
<% end %>
|
22
|
+
}
|
23
|
+
|
24
|
+
<% @contexts.each do |context| %>
|
25
|
+
subgraph cluster_<%= context %> {
|
26
|
+
label = "<%= context.inspect %>"
|
27
|
+
style=filled; fillcolor="#eeeeee"
|
28
|
+
node[fillcolor=white,style=filled]
|
29
|
+
<% (@context_privs[context] || []).each do |priv| %>
|
30
|
+
<%= priv %>_<%= context %> [label="<%= priv.inspect %>"<%= ',fontcolor="#ff0000"' if @highlight_privilege == priv %>]
|
31
|
+
<% end %>
|
32
|
+
<% (@context_privs[context] || []).each do |priv| %>
|
33
|
+
<% (@privilege_hierarchy[priv] || []).
|
34
|
+
select {|p,c| (c.nil? or c == context) and @context_privs[context].include?(p)}.
|
35
|
+
each do |lower_priv, c| %>
|
36
|
+
<%= priv %>_<%= context %> -> <%= lower_priv %>_<%= context %> [arrowhead=empty]
|
37
|
+
<% end %>
|
38
|
+
<% end %>
|
39
|
+
//read_conferences -> update_conferences [style=invis]
|
40
|
+
//create_conferences -> delete_conferences [style=invis]
|
41
|
+
}
|
42
|
+
<% end %>
|
43
|
+
|
44
|
+
<% @roles.each do |role| %>
|
45
|
+
<% (@role_privs[role] || []).each do |context, privilege, unconditionally, attribute_string| %>
|
46
|
+
"<%= role.inspect %>" -> <%= privilege %>_<%= context %> [color="<%= role_color(role) %>", minlen=3<%= ", arrowhead=opendot, URL=\"javascript:\", edgetooltip=\"#{attribute_string.gsub('"','')}\"" unless unconditionally %>]
|
47
|
+
<% end %>
|
48
|
+
<% end %>
|
49
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<h1><%= I18n.t(:authorization_rules_graph, :scope => [:declarative_authorization]) %></h1>
|
2
|
+
<p><%= I18n.t(:currently_active_rules_in_this_application, :scope => [:declarative_authorization]) %></p>
|
3
|
+
<p><%= navigation %></p>
|
4
|
+
|
5
|
+
<% javascript_tag do %>
|
6
|
+
function update_graph (form) {
|
7
|
+
base_url = "<%= url_for :format => 'svg' %>";
|
8
|
+
$('graph').data = base_url + '?' + form.serialize();
|
9
|
+
}
|
10
|
+
|
11
|
+
function set_filter (filter) {
|
12
|
+
for (f in filter) {
|
13
|
+
var select = $("filter_" + f);
|
14
|
+
if (select) {
|
15
|
+
var opt = select.down("option[value='"+ filter[f] + "']");
|
16
|
+
if (opt) {
|
17
|
+
opt.selected = true;
|
18
|
+
update_graph(select.form);
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
<% end %>
|
24
|
+
<p>
|
25
|
+
<% form_tag do %>
|
26
|
+
<%#= link_to_graph I18n.t(:rules, :scope => [:declarative_authorization]) %>
|
27
|
+
<%#= link_to_graph I18n.t(:privilege_hierarchy, :scope => [:declarative_authorization]), :type => 'priv_hierarchy' %>
|
28
|
+
|
29
|
+
<%= select_tag "filter_roles", options_for_select([[I18n.t(:all_rules, :scope => [:declarative_authorization]),'']] + controller.authorization_engine.roles.map(&:to_s).sort), :onchange => 'update_graph(this.form)' %>
|
30
|
+
<%= select_tag "filter_contexts", options_for_select([[I18n.t(:all_contexts, :scope => [:declarative_authorization]),'']] + controller.authorization_engine.auth_rules.collect {|ar| ar.contexts.to_a}.flatten.uniq.map(&:to_s).sort), :onchange => 'update_graph(this.form)' %>
|
31
|
+
<%= check_box_tag "effective_role_privs", "1", false, :onclick => 'update_graph(this.form)' %> <%= label_tag "effective_role_privs", I18n.t(:effective_privileges, :scope => [:declarative_authorization]) %>
|
32
|
+
<%= check_box_tag "privilege_hierarchy", "1", false, :onclick => 'update_graph(this.form)' %> <%= label_tag "privilege_hierarchy", I18n.t(:show_full_privilege_hierarchy, :scope => [:declarative_authorization]) %>
|
33
|
+
<% end %>
|
34
|
+
</p>
|
35
|
+
<div style="margin: 1em;border:1px solid #ccc;max-width:95%">
|
36
|
+
<object id="graph" data="<%= url_for :format => 'svg' %>" type="image/svg+xml" style="max-width:100%"/>
|
37
|
+
</div>
|
38
|
+
<%= button_to_function I18n.t(:zoom_in, :scope => [:declarative_authorization]), '$("graph").style.maxWidth = "";$(this).toggle();$(this).next().toggle()' %>
|
39
|
+
<%= button_to_function I18n.t(:zoom_out, :scope => [:declarative_authorization]), '$("graph").style.maxWidth = "100%";$(this).toggle();$(this).previous().toggle()', :style => 'display:none' %>
|