right_on 0.3.0 → 0.4.0

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.
@@ -0,0 +1,51 @@
1
+ module RightOn
2
+ class Rule
3
+ def self.rule_for(right)
4
+ self.new(right).call
5
+ end
6
+
7
+ def initialize(right)
8
+ @right = right
9
+ end
10
+
11
+ def call
12
+ validate!
13
+
14
+ CanCan::Rule.new(can?, action, subject, conditions, nil)
15
+ end
16
+
17
+ private
18
+
19
+ def validate!
20
+ fail RightOn::Error, 'must specify an action' unless @right.action.present?
21
+ end
22
+
23
+ def can?
24
+ @right.can
25
+ end
26
+
27
+ def action
28
+ @right.action.to_sym
29
+ end
30
+
31
+ def subject
32
+ model_class || @right.subject
33
+ end
34
+
35
+ def conditions
36
+ model_class ? @right.conditions : nil
37
+ end
38
+
39
+ def model_class
40
+ return nil unless @right.subject.present?
41
+
42
+ begin
43
+ model_class = self.class.const_get(@right.subject)
44
+ rescue NameError
45
+ model_class = Class
46
+ end
47
+
48
+ return model_class if model_class.ancestors.include?(ActiveRecord::Base)
49
+ end
50
+ end
51
+ end
@@ -1,3 +1,3 @@
1
1
  module RightOn
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -18,8 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency 'activerecord', '>= 3.2.0'
22
- spec.add_dependency 'activesupport', '>= 3.2.0'
21
+ spec.add_dependency 'cancancan'
22
+ spec.add_dependency 'activerecord', '>= 4.0.0'
23
+ spec.add_dependency 'activesupport', '>= 4.0.0'
23
24
  spec.add_dependency 'input_reader', '~> 0.0'
24
25
  spec.add_development_dependency 'bundler', '~> 1.3'
25
26
  spec.add_development_dependency 'rake'
@@ -27,6 +28,7 @@ Gem::Specification.new do |spec|
27
28
  spec.add_development_dependency 'coverage-kit'
28
29
  spec.add_development_dependency 'simplecov-rcov'
29
30
  spec.add_development_dependency 'coveralls'
31
+ spec.add_development_dependency 'rubocop'
30
32
  spec.add_development_dependency 'sqlite3'
31
33
  spec.add_development_dependency 'travis'
32
34
  end
@@ -0,0 +1,29 @@
1
+ require 'active_support/all'
2
+ require 'cancan/ability'
3
+ require 'right_on/error'
4
+ require 'right_on/rule'
5
+ require 'right_on/ability'
6
+ require 'spec_helper'
7
+
8
+ describe RightOn::Ability do
9
+ describe 'private #add_rule_for' do
10
+ subject(:ability) {
11
+ class TestAbility
12
+ include RightOn::Ability
13
+ end
14
+
15
+ TestAbility.new
16
+ }
17
+ let(:right) {
18
+ double(name: 'Do Something', can: true, action: 'action', subject: 'subject', conditions: {})
19
+ }
20
+
21
+ before do
22
+ ability.send(:add_rule_for, right)
23
+ end
24
+
25
+ it 'should add a rule to the ability' do
26
+ expect(ability.send(:rules).count).to eq(1)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ RightOn.rights_yaml 'db/rights_roles.yml'
4
+
5
+ describe RightOn::ByGroup do
6
+ let(:rights) { Bootstrap.various_rights_with_actions }
7
+
8
+ it 'should identify correct groups' do
9
+ rights # load rights
10
+ expect(RightOn::ByGroup.rights).to eq(
11
+ 'general' => [
12
+ rights[:models],
13
+ rights[:models_index],
14
+ rights[:models_view],
15
+ rights[:models_change]
16
+ ],
17
+ 'admin' => [
18
+ rights[:users]
19
+ ]
20
+ )
21
+ end
22
+ end
@@ -0,0 +1,134 @@
1
+ require 'active_support/all'
2
+ require 'action_controller'
3
+ require 'cancan/ability'
4
+ require 'cancan/controller_additions'
5
+ require 'cancan/exceptions'
6
+ require 'cancan/rule'
7
+ require 'right_on/ability'
8
+ require 'right_on/controller_additions'
9
+ require 'right_on/error'
10
+ require 'right_on/rule'
11
+ require 'active_record'
12
+ require 'spec_helper'
13
+
14
+ # Mock this so we don't need to include active record
15
+ module RightOn
16
+ class Right
17
+ def self.where(args)
18
+ end
19
+ end
20
+ end
21
+
22
+ describe RightOn::ControllerAdditions do
23
+ let(:rule_override) { false }
24
+ before do
25
+ allow(RightOn::Right).to receive(:where).and_return(double(exists?: rule_override))
26
+ end
27
+
28
+ subject(:controller) {
29
+ class Ability
30
+ include RightOn::Ability
31
+
32
+ def initialize(user)
33
+
34
+ end
35
+ end
36
+
37
+ class Controller < ActionController::Base
38
+ include RightOn::ControllerAdditions
39
+
40
+ def rights_from
41
+ nil
42
+ end
43
+
44
+ private
45
+
46
+ def params
47
+ { controller: 'controller', action: 'action' }
48
+ end
49
+
50
+ def current_user
51
+ nil
52
+ end
53
+ end
54
+
55
+ Controller.new
56
+ }
57
+
58
+ describe 'private #authorize_action!' do
59
+ context 'when the ability has a matching rule' do
60
+ let(:right) {
61
+ double(name: 'Do Something', can: true, action: 'access', subject: 'controller#action', conditions: {})
62
+ }
63
+
64
+ before do
65
+ controller.send(:current_ability).send(:add_rule_for, right)
66
+ end
67
+
68
+ it 'should grant access to controller#action' do
69
+ expect{controller.send(:authorize_action!)}.to_not(
70
+ raise_error(CanCan::AccessDenied, 'You are not authorized to access this page.'))
71
+ end
72
+ end
73
+
74
+ context 'when the ability does not have a matching rule' do
75
+ let(:right) {
76
+ double(name: 'Do Something', can: true, action: 'access', subject: 'controller#other_action', conditions: {})
77
+ }
78
+
79
+ before do
80
+ controller.send(:current_ability).send(:add_rule_for, right)
81
+ end
82
+
83
+ it 'should grant access to controller#action' do
84
+ expect{controller.send(:authorize_action!)}.to(
85
+ raise_error(CanCan::AccessDenied, 'You are not authorized to access this page.'))
86
+ end
87
+ end
88
+
89
+ context 'when the ability has a specific rule overriding the general rule' do
90
+ let(:rule_override) { true }
91
+ let(:right) {
92
+ double(name: 'Generic', can: true, action: 'access', subject: 'controller', conditions: {})
93
+ }
94
+
95
+ before do
96
+ controller.send(:current_ability).send(:add_rule_for, right)
97
+ end
98
+
99
+ it 'should not grant access to controller#action' do
100
+ expect{controller.send(:authorize_action!)}.to(
101
+ raise_error(CanCan::AccessDenied, 'You are not authorized to access this page.'))
102
+ end
103
+ end
104
+ end
105
+
106
+ describe 'private #authorize_action!' do
107
+ let(:controller) {
108
+ class Controller < ActionController::Base
109
+ def rights_from
110
+ :other_controller
111
+ end
112
+
113
+ private
114
+
115
+ def params
116
+ { controller: 'controller', action: 'action' }
117
+ end
118
+
119
+ def current_user
120
+ nil
121
+ end
122
+ end
123
+
124
+ Controller.new
125
+ }
126
+
127
+ context 'when rights from is a symbol' do
128
+ specify do
129
+ expect{controller.send(:authorize_action!)}.to(
130
+ raise_error(CanCan::AccessDenied, 'You are not authorized to access this page.'))
131
+ end
132
+ end
133
+ end
134
+ end
@@ -5,9 +5,8 @@ describe RightOn::PermissionDeniedResponse do
5
5
  let(:params) { { controller: 'users' } }
6
6
  subject { RightOn::PermissionDeniedResponse.new(params, controller_action_options) }
7
7
 
8
- let(:allowed) {
9
- double(name: 'create_user', allowed?: true, roles: [double(title: 'Users')])
10
- }
8
+ let(:create_user_right) { double(name: 'create_user', allowed?: true, roles: [double(title: 'Users')]) }
9
+ let(:allowed) { double(allowed?: true) }
11
10
  let(:denied) { double(allowed?: false) }
12
11
 
13
12
  let(:no_right_for_page) {
@@ -17,12 +16,13 @@ describe RightOn::PermissionDeniedResponse do
17
16
  let(:no_roles_for_page) { 'N/A (as no right is assigned for this action)' }
18
17
 
19
18
  before do
20
- stub_const 'RightOn::Right', double(all: [right])
19
+ stub_const 'RightOn::RightAllowed', double(new: right_allowed)
20
+ stub_const 'RightOn::Right', double(all: [create_user_right])
21
21
  end
22
22
 
23
23
  context '#text_message' do
24
24
  context 'when right exists' do
25
- let(:right) { allowed }
25
+ let(:right_allowed) { allowed }
26
26
 
27
27
  specify {
28
28
  expect(subject.text_message).to eq(
@@ -35,14 +35,14 @@ describe RightOn::PermissionDeniedResponse do
35
35
  end
36
36
 
37
37
  context 'when right not allowed' do
38
- let(:right) { denied }
38
+ let(:right_allowed) { denied }
39
39
  specify { expect(subject.text_message).to eq no_right_for_page }
40
40
  end
41
41
  end
42
42
 
43
43
  context '#to_json' do
44
44
  context 'when right exists' do
45
- let(:right) { allowed }
45
+ let(:right_allowed) { allowed }
46
46
  specify {
47
47
  expect(subject.to_json).to eq(
48
48
  error: 'Permission Denied',
@@ -53,7 +53,7 @@ describe RightOn::PermissionDeniedResponse do
53
53
  end
54
54
 
55
55
  context 'when right allowed' do
56
- let(:right) { denied }
56
+ let(:right_allowed) { denied }
57
57
  specify {
58
58
  expect(subject.to_json).to eq(
59
59
  error: 'Permission Denied',
@@ -0,0 +1,89 @@
1
+ require 'active_record'
2
+ require 'active_support/cache/memory_store'
3
+ require 'right_on/right'
4
+ require 'right_on/right_allowed'
5
+ require 'spec_helper'
6
+ require 'support/bootstrap'
7
+
8
+ describe RightOn::RightAllowed do
9
+ def right_double(name)
10
+ default_attrs = { id: rand(1_000_000), action: nil }
11
+ double default_attrs.merge(Bootstrap.build_right_attrs(name))
12
+ end
13
+
14
+ let(:cache) { ActiveSupport::Cache::MemoryStore.new }
15
+
16
+ before do
17
+ stub_const 'Rails', double(cache: cache)
18
+ RightOn::RightAllowed.clear_cache
19
+ stub_const 'RightOn::Right', double(all: all)
20
+ end
21
+
22
+ context 'for simple case with one controller right' do
23
+ let(:all) { [users] }
24
+ let(:users) { right_double('users') }
25
+
26
+ subject { RightOn::RightAllowed.new('users', action).allowed?(users) }
27
+
28
+ context 'index action' do
29
+ let(:action) { 'index' }
30
+ it { is_expected.to be true }
31
+ end
32
+
33
+ context 'edit action' do
34
+ let(:action) { 'edit' }
35
+ it { is_expected.to be true }
36
+ end
37
+
38
+ context 'hello action' do
39
+ let(:action) { 'hello' }
40
+ it { is_expected.to be true }
41
+ end
42
+ end
43
+
44
+ context 'for complex rights' do
45
+ let(:all) { [other, index, change, view] }
46
+
47
+ let(:index_action) { RightOn::RightAllowed.new('models', 'index') }
48
+ let(:edit_action) { RightOn::RightAllowed.new('models', 'edit') }
49
+ let(:hello_action) { RightOn::RightAllowed.new('models', 'hello') }
50
+
51
+ let(:other) { right_double('models') }
52
+ let(:index) { right_double('models#index') }
53
+ let(:change) { right_double('models#change') }
54
+ let(:view) { right_double('models#view') }
55
+
56
+ context 'index action' do
57
+ specify do
58
+ # as specific action exists
59
+ expect(index_action.allowed?(other)).to eq false
60
+
61
+ expect(index_action.allowed?(index)).to eq true
62
+ expect(index_action.allowed?(view)).to eq true
63
+ expect(index_action.allowed?(change)).to eq true
64
+ end
65
+ end
66
+
67
+ context 'edit action' do
68
+ specify do
69
+ # as specific action exists
70
+ expect(edit_action.allowed?(other)).to eq false
71
+
72
+ expect(edit_action.allowed?(index)).to eq false
73
+ expect(edit_action.allowed?(view)).to eq false
74
+ expect(edit_action.allowed?(change)).to eq true
75
+ end
76
+ end
77
+
78
+ context 'hello action' do
79
+ specify do
80
+ # as hello isn't defined
81
+ expect(hello_action.allowed?(other)).to eq true
82
+
83
+ expect(hello_action.allowed?(index)).to eq false
84
+ expect(hello_action.allowed?(view)).to eq false
85
+ expect(hello_action.allowed?(change)).to eq false
86
+ end
87
+ end
88
+ end
89
+ end
@@ -1,139 +1,86 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe User do
4
- let(:basic_user) { User.where(name: 'basic').first }
5
- let(:admin_user) { User.where(name: 'admin').first }
6
-
7
- before do
8
- Bootstrap.reset_database
9
- end
10
-
11
- it 'should compare privileges' do
12
- expect(admin_user.has_privileges_of?(basic_user)).to eq true
13
- expect(basic_user.has_privileges_of?(admin_user)).to eq false
14
- end
15
- end
16
-
17
3
  describe RightOn::Right do
18
- before do
19
- RightOn::Right.delete_all
20
- Model.delete_all
21
-
22
- @model = Model.create!(:name => 'Test')
23
-
24
- @users = RightOn::Right.create!(:name => 'users', :controller => 'users')
25
- @other = RightOn::Right.create!(:name => 'models', :controller => 'models')
26
- @index = RightOn::Right.create!(:name => 'models#index', :controller => 'models', :action => 'index')
27
- @change = RightOn::Right.create!(:name => 'models#change', :controller => 'models', :action => 'change')
28
- @view = RightOn::Right.create!(:name => 'models#view', :controller => 'models', :action => 'view')
29
- end
4
+ let(:rights) { Bootstrap.various_rights_with_actions }
5
+ let(:users) { rights[:users] }
6
+ let(:other) { rights[:models] }
7
+ let(:index) { rights[:models_index] }
8
+ let(:change) { rights[:models_change] }
9
+ let(:view) { rights[:models_view] }
30
10
 
31
11
  it 'should display nicely with sensible_name and to_s' do
32
- expect(@other.to_s).to eq 'models'
33
- expect(@index.to_s).to eq 'models#index'
34
-
35
- expect(@other.sensible_name).to eq 'Models'
36
- expect(@index.sensible_name).to eq 'Models - Index'
37
- end
12
+ expect(other.to_s).to eq 'models'
13
+ expect(index.to_s).to eq 'models#index'
38
14
 
39
- it 'should identify correct groups' do
40
- expect(RightOn::Right.by_groups).to eq(
41
- 'general' => [@other, @index, @view, @change],
42
- 'admin' => [@users]
43
- )
44
- end
45
-
46
- it 'should determine if it is allowed based on context' do
47
- index_action = {:controller => 'models', :action => 'index'}
48
- edit_action = {:controller => 'models', :action => 'edit'}
49
- hello_action = {:controller => 'models', :action => 'hello'}
50
-
51
- expect(@users.allowed?(:controller => 'users', :action => 'index')).to eq true
52
- expect(@users.allowed?(:controller => 'users', :action => 'edit' )).to eq true
53
- expect(@users.allowed?(:controller => 'users', :action => 'hello')).to eq true
54
-
55
- expect(@other.allowed?(index_action)).to eq false # as specific action exists
56
- expect(@other.allowed?(edit_action )).to eq false # as specific action exists
57
- expect(@other.allowed?(hello_action)).to eq true # as hello isn't defined
58
-
59
- expect(@index.allowed?(index_action)).to eq true
60
- expect(@index.allowed?(edit_action )).to eq false
61
- expect(@index.allowed?(hello_action)).to eq false
62
-
63
- expect(@view.allowed?(index_action)).to eq true
64
- expect(@view.allowed?(edit_action )).to eq false
65
- expect(@view.allowed?(hello_action)).to eq false
66
-
67
- expect(@change.allowed?(index_action)).to eq true
68
- expect(@change.allowed?(edit_action )).to eq true
69
- expect(@change.allowed?(hello_action)).to eq false
15
+ expect(other.sensible_name).to eq 'Models'
16
+ expect(index.sensible_name).to eq 'Models - Index'
70
17
  end
71
18
  end
72
19
 
73
- describe RightOn::Right, "when created" do
74
- it "should validate presence of name" do
20
+ describe RightOn::Right, 'when created' do
21
+ it 'should validate presence of name' do
75
22
  subject.valid?
76
23
  expect(subject.errors[:name]).to_not be_blank
77
24
  end
78
25
  end
79
26
 
80
- describe RightOn::Right, "with a name and controller" do
27
+ describe RightOn::Right, 'with a name and controller' do
81
28
  before do
82
- @new_right = RightOn::Right.new(:name => "tickets", :controller => "tickets")
29
+ @new_right = RightOn::Right.new(name: 'tickets', controller: 'tickets')
83
30
  @new_right.save!
84
31
  end
85
32
 
86
- it "should create a new right" do
87
- expect(@new_right.name).to eq "tickets"
88
- expect(@new_right.controller).to eq "tickets"
33
+ it 'should create a new right' do
34
+ expect(@new_right.name).to eq 'tickets'
35
+ expect(@new_right.controller).to eq 'tickets'
89
36
  expect(@new_right.save).to eq true
90
37
  end
91
38
 
92
39
  end
93
40
 
94
- describe RightOn::Right, "with a name, controller and action" do
41
+ describe RightOn::Right, 'with a name, controller and action' do
95
42
  before do
96
- @new_right = RightOn::Right.new(:name => "tickets@destroy", :controller => "tickets", :action => "destroy")
43
+ @new_right = RightOn::Right.new(name: 'tickets@destroy', controller: 'tickets', action: 'destroy')
97
44
  end
98
45
 
99
- it "should create a new right" do
100
- expect(@new_right.name).to eq "tickets@destroy"
101
- expect(@new_right.controller).to eq "tickets"
102
- expect(@new_right.action).to eq "destroy"
46
+ it 'should create a new right' do
47
+ expect(@new_right.name).to eq 'tickets@destroy'
48
+ expect(@new_right.controller).to eq 'tickets'
49
+ expect(@new_right.action).to eq 'destroy'
103
50
  expect(@new_right.save).to eq true
104
51
  end
105
52
  end
106
53
 
107
- describe RightOn::Right, "with only a name" do
54
+ describe RightOn::Right, 'with only a name' do
108
55
  before do
109
- @new_right = RightOn::Right.new(:name => "tickets2")
56
+ @new_right = RightOn::Right.new(name: 'tickets2')
110
57
  end
111
58
 
112
- it "should create a new right" do
59
+ it 'should create a new right' do
113
60
  expect(@new_right.save).to eq true
114
61
  end
115
62
  end
116
63
 
117
- describe RightOn::Right, "with the same name" do
64
+ describe RightOn::Right, 'with the same name' do
118
65
  before do
119
- @old_right = RightOn::Right.new(:name => "tickets3", :controller => "tickets")
66
+ @old_right = RightOn::Right.new(name: 'tickets3', controller: 'tickets')
120
67
  @old_right.save!
121
- @new_right = RightOn::Right.new(:name => "tickets3", :controller => "tickets")
68
+ @new_right = RightOn::Right.new(name: 'tickets3', controller: 'tickets')
122
69
  end
123
70
 
124
- it "should not create a new right" do
71
+ it 'should not create a new right' do
125
72
  expect(@new_right.save).to eq false
126
73
  end
127
74
  end
128
75
 
129
- describe RightOn::Role, "can have many rights" do
130
- let(:role1) { RightOn::Role.new(:title => 'role 1') }
76
+ describe RightOn::Role, 'can have many rights' do
77
+ let(:role1) { RightOn::Role.new(title: 'role 1') }
131
78
 
132
79
  specify { expect(role1.to_s).to eq 'Role 1' }
133
80
 
134
81
  context 'when assigned rights' do
135
- let(:right1) { RightOn::Right.create!(:name => 'right 1') }
136
- let(:right2) { RightOn::Right.create!(:name => 'right 2') }
82
+ let(:right1) { RightOn::Right.create!(name: 'right 1') }
83
+ let(:right2) { RightOn::Right.create!(name: 'right 2') }
137
84
 
138
85
  before do
139
86
  role1.save!
@@ -146,45 +93,10 @@ describe RightOn::Role, "can have many rights" do
146
93
  right2.destroy
147
94
  end
148
95
 
149
- it "should have and belong to many" do
96
+ it 'should have and belong to many' do
150
97
  expect(role1.rights.size).to eq 2
151
98
  expect(right1.roles.size).to eq 1
152
99
  expect(right2.roles.size).to eq 1
153
100
  end
154
101
  end
155
102
  end
156
-
157
- describe 'when checking accessibility to a controller' do
158
-
159
- let(:test_controller_right) { RightOn::Right.new(name: 'test', controller: 'test') }
160
- let(:user) { double(rights: [test_controller_right]) }
161
- let(:controller) { 'test' }
162
- let(:action) { 'index' }
163
- let(:params) { {controller: 'test', action: 'index'} }
164
-
165
- before do
166
- stub_const 'TestController', double(current_user: user, params: params)
167
- TestController.extend RightOn::ActionControllerExtensions
168
- allow(TestController).to receive(:rights_from).and_return(nil)
169
- end
170
-
171
- specify { expect(TestController.access_allowed?(controller)).to be_truthy }
172
- specify { expect(TestController.access_allowed?('other')).to be_falsey }
173
- specify { expect(TestController.access_allowed_to_controller?(controller)).to be_truthy }
174
- specify { expect(TestController.access_allowed_to_controller?('other')).to be_falsey }
175
-
176
- describe 'when inheriting rights' do
177
- let(:controller) { 'test_inherited' }
178
-
179
- before do
180
- stub_const 'TestInheritedController', double(current_user: user, params: params)
181
- TestInheritedController.extend RightOn::ActionControllerExtensions
182
- allow(TestInheritedController).to receive(:rights_from).and_return(:test)
183
- end
184
-
185
- specify { expect(TestInheritedController.access_allowed?(controller)).to be_falsey }
186
- specify { expect(TestInheritedController.access_allowed?('other')).to be_falsey }
187
- specify { expect(TestInheritedController.access_allowed_to_controller?(controller)).to be_truthy }
188
- specify { expect(TestInheritedController.access_allowed_to_controller?('other')).to be_falsey }
189
- end
190
- end