stffn-declarative_authorization 0.3.0 → 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 (35) hide show
  1. data/CHANGELOG +9 -0
  2. data/README.rdoc +22 -6
  3. data/app/controllers/authorization_rules_controller.rb +135 -14
  4. data/app/helpers/authorization_rules_helper.rb +96 -13
  5. data/app/views/authorization_rules/_change.erb +49 -0
  6. data/app/views/authorization_rules/_show_graph.erb +37 -0
  7. data/app/views/authorization_rules/_suggestion.erb +9 -0
  8. data/app/views/authorization_rules/_suggestions.erb +24 -0
  9. data/app/views/authorization_rules/change.html.erb +124 -0
  10. data/app/views/authorization_rules/graph.dot.erb +23 -4
  11. data/app/views/authorization_rules/graph.html.erb +1 -0
  12. data/app/views/authorization_rules/index.html.erb +3 -2
  13. data/app/views/authorization_usages/index.html.erb +2 -11
  14. data/config/routes.rb +2 -1
  15. data/lib/declarative_authorization/authorization.rb +87 -35
  16. data/lib/declarative_authorization/development_support/analyzer.rb +252 -0
  17. data/lib/declarative_authorization/development_support/change_analyzer.rb +253 -0
  18. data/lib/declarative_authorization/development_support/change_supporter.rb +578 -0
  19. data/lib/declarative_authorization/development_support/development_support.rb +243 -0
  20. data/lib/declarative_authorization/helper.rb +6 -2
  21. data/lib/declarative_authorization/in_controller.rb +254 -26
  22. data/lib/declarative_authorization/in_model.rb +27 -2
  23. data/lib/declarative_authorization/maintenance.rb +22 -8
  24. data/lib/declarative_authorization/obligation_scope.rb +14 -9
  25. data/lib/declarative_authorization/reader.rb +10 -2
  26. data/test/authorization_test.rb +44 -0
  27. data/test/controller_filter_resource_access_test.rb +385 -0
  28. data/test/controller_test.rb +14 -6
  29. data/test/helper_test.rb +21 -0
  30. data/test/maintenance_test.rb +26 -0
  31. data/test/model_test.rb +28 -0
  32. data/test/test_helper.rb +14 -1
  33. metadata +15 -5
  34. data/lib/declarative_authorization/authorization_rules_analyzer.rb +0 -138
  35. data/test/authorization_rules_analyzer_test.rb +0 -123
@@ -2,12 +2,8 @@ require File.join(File.dirname(__FILE__), 'test_helper.rb')
2
2
 
3
3
 
4
4
  class LoadMockObject < MockDataObject
5
- def self.find(*args)
6
- new :id => args[0]
7
- end
8
5
  end
9
6
 
10
-
11
7
  ##################
12
8
  class SpecificMocksController < MocksController
13
9
  filter_access_to :test_action, :require => :test, :context => :permissions
@@ -26,7 +22,6 @@ end
26
22
  class BasicControllerTest < ActionController::TestCase
27
23
  tests SpecificMocksController
28
24
 
29
-
30
25
  def test_filter_access_to_receiving_an_explicit_array
31
26
  reader = Authorization::Reader::DSLReader.new
32
27
 
@@ -153,6 +148,20 @@ class BasicControllerTest < ActionController::TestCase
153
148
  @controller.send(:instance_variable_get, :"@load_mock_object")
154
149
  assert @controller.authorized?
155
150
  end
151
+
152
+ def test_permitted_to_without_context
153
+ reader = Authorization::Reader::DSLReader.new
154
+ reader.parse %{
155
+ authorization do
156
+ role :test_role do
157
+ has_permission_on :specific_mocks, :to => :test
158
+ end
159
+ end
160
+ }
161
+ @controller.current_user = MockUser.new(:test_role)
162
+ @controller.authorization_engine = Authorization::Engine.new(reader)
163
+ assert @controller.permitted_to?(:test)
164
+ end
156
165
  end
157
166
 
158
167
 
@@ -358,4 +367,3 @@ class HierachicalControllerTest < ActionController::TestCase
358
367
  assert !@controller.authorized?
359
368
  end
360
369
  end
361
-
data/test/helper_test.rb CHANGED
@@ -63,6 +63,27 @@ class HelperTest < ActionController::TestCase
63
63
  assert permitted_to?(:show, :mocks)
64
64
  assert !permitted_to?(:show, mock_2)
65
65
  end
66
+
67
+ def test_permit_with_object_and_context
68
+ reader = Authorization::Reader::DSLReader.new
69
+ reader.parse %{
70
+ authorization do
71
+ role :test_role do
72
+ has_permission_on :other_mocks do
73
+ to :show
74
+ if_attribute :test_attr => is {user.test_attr}
75
+ end
76
+ end
77
+ end
78
+ }
79
+ user = MockUser.new(:test_role, :test_attr => 1)
80
+ mock = MockDataObject.new(:test_attr => 1)
81
+ mock_2 = MockDataObject.new(:test_attr => 2)
82
+ request!(user, :action, reader)
83
+
84
+ assert permitted_to?(:show, mock, :context => :other_mocks)
85
+ assert !permitted_to?(:show, mock_2, :context => :other_mocks)
86
+ end
66
87
 
67
88
  def test_has_role
68
89
  reader = Authorization::Reader::DSLReader.new
@@ -12,4 +12,30 @@ class MaintenanceTest < Test::Unit::TestCase
12
12
  include?(usage_test_controller)
13
13
  end
14
14
 
15
+ def test_without_access_control
16
+ reader = Authorization::Reader::DSLReader.new
17
+ reader.parse %{
18
+ authorization do
19
+ role :test_role do
20
+ has_permission_on :permissions, :to => :test
21
+ end
22
+ end
23
+ }
24
+ engine = Authorization::Engine.new(reader)
25
+ assert !engine.permit?(:test_2, :context => :permissions,
26
+ :user => MockUser.new(:test_role))
27
+ Authorization::Maintenance::without_access_control do
28
+ assert engine.permit?(:test_2, :context => :permissions,
29
+ :user => MockUser.new(:test_role))
30
+ end
31
+ Authorization::Maintenance::without_access_control do
32
+ Authorization::Maintenance::without_access_control do
33
+ assert engine.permit?(:test_2, :context => :permissions,
34
+ :user => MockUser.new(:test_role))
35
+ end
36
+ assert engine.permit?(:test_2, :context => :permissions,
37
+ :user => MockUser.new(:test_role))
38
+ end
39
+ end
40
+
15
41
  end
data/test/model_test.rb CHANGED
@@ -168,6 +168,34 @@ class ModelTest < Test::Unit::TestCase
168
168
  TestModel.delete_all
169
169
  end
170
170
 
171
+ def test_named_scope_with_is_nil
172
+ reader = Authorization::Reader::DSLReader.new
173
+ reader.parse %{
174
+ authorization do
175
+ role :test_role do
176
+ has_permission_on :test_models, :to => :read do
177
+ if_attribute :content => nil
178
+ end
179
+ end
180
+ role :test_role_not_nil do
181
+ has_permission_on :test_models, :to => :read do
182
+ if_attribute :content => is_not { nil }
183
+ end
184
+ end
185
+ end
186
+ }
187
+ Authorization::Engine.instance(reader)
188
+
189
+ test_model_1 = TestModel.create!
190
+ test_model_2 = TestModel.create! :content => "Content"
191
+
192
+ assert_equal test_model_1, TestModel.with_permissions_to(:read,
193
+ :context => :test_models, :user => MockUser.new(:test_role)).first
194
+ assert_equal test_model_2, TestModel.with_permissions_to(:read,
195
+ :context => :test_models, :user => MockUser.new(:test_role_not_nil)).first
196
+ TestModel.delete_all
197
+ end
198
+
171
199
  def test_named_scope_with_not_is
172
200
  reader = Authorization::Reader::DSLReader.new
173
201
  reader.parse %{
data/test/test_helper.rb CHANGED
@@ -41,12 +41,21 @@ class MockDataObject
41
41
  def self.table_name
42
42
  "mocks"
43
43
  end
44
+
45
+ def self.find(*args)
46
+ raise "Couldn't find #{self.name} with id #{args[0].inspect}" unless args[0]
47
+ new :id => args[0]
48
+ end
44
49
  end
45
50
 
46
51
  class MockUser < MockDataObject
47
52
  def initialize (*roles)
48
53
  options = roles.last.is_a?(::Hash) ? roles.pop : {}
49
- super(options.merge(:role_symbols => roles))
54
+ super(options.merge(:role_symbols => roles, :login => hash))
55
+ end
56
+
57
+ def initialize_copy (other)
58
+ @role_symbols = @role_symbols.clone
50
59
  end
51
60
  end
52
61
 
@@ -66,6 +75,10 @@ class MocksController < ActionController::Base
66
75
  end
67
76
  end
68
77
  end
78
+
79
+ def self.define_resource_actions
80
+ define_action_methods :index, :show, :edit, :update, :new, :create, :destroy
81
+ end
69
82
 
70
83
  def logger (*args)
71
84
  Class.new do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stffn-declarative_authorization
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steffen Bartsch
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-08 00:00:00 -07:00
12
+ date: 2009-05-16 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -43,8 +43,13 @@ files:
43
43
  - app/helpers/authorization_rules_helper.rb
44
44
  - app/views/authorization_usages/index.html.erb
45
45
  - app/views/authorization_rules/index.html.erb
46
+ - app/views/authorization_rules/_show_graph.erb
47
+ - app/views/authorization_rules/_change.erb
48
+ - app/views/authorization_rules/_suggestions.erb
46
49
  - app/views/authorization_rules/graph.dot.erb
50
+ - app/views/authorization_rules/change.html.erb
47
51
  - app/views/authorization_rules/graph.html.erb
52
+ - app/views/authorization_rules/_suggestion.erb
48
53
  - config/routes.rb
49
54
  - lib/declarative_authorization.rb
50
55
  - lib/declarative_authorization/in_controller.rb
@@ -53,7 +58,10 @@ files:
53
58
  - lib/declarative_authorization/obligation_scope.rb
54
59
  - lib/declarative_authorization/in_model.rb
55
60
  - lib/declarative_authorization/helper.rb
56
- - lib/declarative_authorization/authorization_rules_analyzer.rb
61
+ - lib/declarative_authorization/development_support/analyzer.rb
62
+ - lib/declarative_authorization/development_support/change_analyzer.rb
63
+ - lib/declarative_authorization/development_support/change_supporter.rb
64
+ - lib/declarative_authorization/development_support/development_support.rb
57
65
  - lib/declarative_authorization/authorization.rb
58
66
  - lib/declarative_authorization/maintenance.rb
59
67
  - test/authorization_test.rb
@@ -61,12 +69,14 @@ files:
61
69
  - test/maintenance_test.rb
62
70
  - test/model_test.rb
63
71
  - test/controller_test.rb
72
+ - test/development_support
64
73
  - test/helper_test.rb
65
74
  - test/dsl_reader_test.rb
75
+ - test/controller_filter_resource_access_test.rb
66
76
  - test/test_helper.rb
67
- - test/authorization_rules_analyzer_test.rb
68
77
  has_rdoc: true
69
78
  homepage: http://github.com/stffn/declarative_authorization
79
+ licenses:
70
80
  post_install_message:
71
81
  rdoc_options: []
72
82
 
@@ -87,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
97
  requirements: []
88
98
 
89
99
  rubyforge_project:
90
- rubygems_version: 1.2.0
100
+ rubygems_version: 1.3.5
91
101
  signing_key:
92
102
  specification_version: 2
93
103
  summary: declarative_authorization is a Rails plugin for authorization based on readable authorization rules.
@@ -1,138 +0,0 @@
1
- begin
2
- require "ruby_parser"
3
- #require "parse_tree"
4
- #require "parse_tree_extensions"
5
- require "sexp_processor"
6
- rescue LoadError
7
- raise "Authorization::Analyzer requires ruby_parser gem"
8
- end
9
-
10
- module Authorization
11
-
12
- class Analyzer
13
- attr_reader :engine
14
-
15
- def initialize (engine)
16
- @engine = engine
17
- end
18
-
19
- def analyze (rules)
20
- sexp_array = RubyParser.new.parse(rules)
21
- #sexp_array = ParseTree.translate(rules)
22
- @reports = []
23
- [MergeableRulesProcessor].each do |parser|
24
- parser.new(self).analyze(sexp_array)
25
- end
26
- #p @reports
27
- end
28
-
29
- def reports
30
- @reports or raise "No rules analyzed!"
31
- end
32
-
33
- class GeneralAuthorizationProcessor < SexpProcessor
34
- def initialize(analyzer)
35
- super()
36
- self.auto_shift_type = true
37
- self.require_empty = false
38
- self.strict = false
39
- @analyzer = analyzer
40
- end
41
-
42
- def analyze (sexp_array)
43
- process(sexp_array)
44
- analyze_rules
45
- end
46
-
47
- def analyze_rules
48
- # to be implemented by specific processor
49
- end
50
-
51
- def process_iter (exp)
52
- s(:iter, process(exp.shift), process(exp.shift), process(exp.shift))
53
- end
54
-
55
- def process_arglist (exp)
56
- s(exp.collect {|inner_exp| process(inner_exp).shift})
57
- end
58
-
59
- def process_hash (exp)
60
- s(Hash[*exp.collect {|inner_exp| process(inner_exp).shift}])
61
- end
62
-
63
- def process_lit (exp)
64
- s(exp.shift)
65
- end
66
- end
67
-
68
- class MergeableRulesProcessor < GeneralAuthorizationProcessor
69
- def analyze_rules
70
- if @has_permission
71
- #p @has_permission
72
- permissions_by_context_and_rules = @has_permission.inject({}) do |memo, permission|
73
- key = [permission[:context], permission[:rules]]
74
- memo[key] ||= []
75
- memo[key] << permission
76
- memo
77
- end
78
-
79
- permissions_by_context_and_rules.each do |key, rules|
80
- if rules.length > 1
81
- rule_lines = rules.collect {|rule| rule[:line] }
82
- rules.each do |rule|
83
- @analyzer.reports << Report.new(:mergeable_rules, "", rule[:line],
84
- "Similar rules already in line(s) " +
85
- rule_lines.reject {|l| l == rule[:line] } * ", ")
86
- end
87
- end
88
- end
89
- end
90
- end
91
-
92
- def process_call (exp)
93
- klass = exp.shift
94
- name = exp.shift
95
- case name
96
- when :role
97
- analyze_rules
98
- @has_permission = []
99
- s(:call, klass, name)
100
- when :has_permission_on
101
- arglist_line = exp[0].line
102
- arglist = process(exp.shift).shift
103
- context = arglist.shift
104
- args_hash = arglist.shift
105
- @has_permission << {
106
- :context => context,
107
- :rules => [],
108
- :privilege => args_hash && args_hash[:to],
109
- # a hack: call exp line seems to be wrong
110
- :line => arglist_line
111
- }
112
- s(:call, klass, name)
113
- when :to
114
- @has_permission.last[:privilege] = process(exp.shift).shift if @has_permission
115
- s(:call, klass, name)
116
- when :if_attribute
117
- @in_if_attribute = true
118
- rules = process(exp.shift).shift
119
- @has_permission.last[:rules] << rules if @has_permission
120
- @in_if_attribute = false
121
- s(:call, klass, name)
122
- else
123
- s(:call, klass, name, process(exp.shift))
124
- end
125
- end
126
- end
127
-
128
- class Report
129
- attr_reader :type, :filename, :line, :message
130
- def initialize (type, filename, line, msg)
131
- @type = type
132
- @filename = filename
133
- @line = line
134
- @message = msg
135
- end
136
- end
137
- end
138
- end
@@ -1,123 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper.rb')
2
- require File.join(File.dirname(__FILE__), %w{.. lib declarative_authorization authorization_rules_analyzer})
3
-
4
- class AuthorizationRulesAnalyzerTest < Test::Unit::TestCase
5
-
6
- def test_analyzing_complex_rules
7
- assert_nothing_raised do
8
- engine, analyzer = engine_analyzer_for %{
9
- authorization do
10
- role :guest do
11
- has_permission_on :conferences, :to => :read do
12
- if_attribute :published => true
13
- end
14
- has_permission_on :talks, :to => :read do
15
- if_permitted_to :read, :conference
16
- end
17
- has_permission_on :users, :to => :create
18
- has_permission_on :authorization_rules, :to => :read
19
- has_permission_on :authorization_usages, :to => :read
20
- end
21
-
22
- role :user do
23
- includes :guest
24
- has_permission_on :conference_attendees, :to => :create do
25
- if_attribute :user => is {user},
26
- :conference => { :published => true }
27
- end
28
- has_permission_on :conference_attendees, :to => :delete do
29
- if_attribute :user => is {user},
30
- :conference => { :attendees => contains {user} }
31
- end
32
- has_permission_on :talk_attendees, :to => :create do
33
- if_attribute :talk => { :conference => { :attendees => contains {user} }}
34
- end
35
- has_permission_on :talk_attendees, :to => :delete do
36
- if_attribute :user => is {user}
37
- end
38
- end
39
-
40
- role :conference_organizer do
41
- has_permission_on :conferences do
42
- to :manage
43
- # if...
44
- end
45
- has_permission_on [:conference_attendees, :talks, :talk_attendees], :to => :manage
46
- end
47
-
48
- role :admin do
49
- has_permission_on [:conferences, :users, :talks], :to => :manage
50
- has_permission_on :authorization_rules, :to => :read
51
- has_permission_on :authorization_usages, :to => :read
52
- end
53
- end
54
-
55
- privileges do
56
- privilege :manage, :includes => [:create, :read, :update, :delete]
57
- privilege :read, :includes => [:index, :show]
58
- privilege :create, :includes => :new
59
- privilege :update, :includes => :edit
60
- privilege :delete, :includes => :destroy
61
- end
62
- }
63
- end
64
- end
65
-
66
- def test_mergeable_rules_without_constraints
67
- engine, analyzer = engine_analyzer_for %{
68
- authorization do
69
- role :test_role do
70
- has_permission_on :permissions, :to => :test
71
- has_permission_on :permissions, :to => :test2
72
- end
73
- end
74
- }
75
-
76
- report = analyzer.reports.find {|report| report.type == :mergeable_rules}
77
- assert report
78
- assert_equal 4, report.line
79
- end
80
-
81
- def test_mergeable_rules_with_in_block_to
82
- assert_nothing_raised do
83
- engine, analyzer = engine_analyzer_for %{
84
- authorization do
85
- role :test_role do
86
- has_permission_on :permissions do
87
- to :test
88
- end
89
- end
90
- end
91
- }
92
- end
93
- end
94
-
95
- def test_no_mergeable_rules_with_constraints
96
- engine, analyzer = engine_analyzer_for %{
97
- authorization do
98
- role :test_role do
99
- has_permission_on :permissions, :to => :test do
100
- if_attribute :some_attr => is {bla}
101
- end
102
- has_permission_on :permissions, :to => :test2 do
103
- if_attribute :some_attr_2 => is {bla}
104
- end
105
- end
106
- end
107
- }
108
-
109
- assert !analyzer.reports.find {|report| report.type == :mergeable_rules}
110
- end
111
-
112
- protected
113
- def engine_analyzer_for (rules)
114
- reader = Authorization::Reader::DSLReader.new
115
- reader.parse rules
116
- engine = Authorization::Engine.new(reader)
117
-
118
- analyzer = Authorization::Analyzer.new(engine)
119
- analyzer.analyze rules
120
-
121
- [engine, analyzer]
122
- end
123
- end