authorizy 0.1.0 → 0.3.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,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/expectations'
4
+
5
+ RSpec::Matchers.define :be_authorized do |controller, action, params: {}, session: {}|
6
+ match do |user|
7
+ parameters = params.merge(controller: controller, action: action)
8
+
9
+ access?(user, parameters, session)
10
+ end
11
+
12
+ match_when_negated do |user|
13
+ parameters = params.merge(controller: controller, action: action)
14
+
15
+ !access?(user, parameters, session)
16
+ end
17
+
18
+ failure_message do |user|
19
+ maybe_params_or_session("expected #{user.class}##{user.id} to be authorized in #{data}", params, session)
20
+ end
21
+
22
+ failure_message_when_negated do |user|
23
+ maybe_params_or_session("expected #{user.class}##{user.id} not to be authorized in #{data}", params, session)
24
+ end
25
+
26
+ private
27
+
28
+ def access?(user, params, session)
29
+ cop = Authorizy.config.cop.new(user, params, session)
30
+
31
+ Authorizy::Core.new(user, params, session, cop: cop).access?
32
+ end
33
+
34
+ def maybe_params_or_session(message, params, session)
35
+ message += ", params: #{params}" if params.present?
36
+ message += ", session: #{session}" if session.present?
37
+
38
+ message
39
+ end
40
+
41
+ def data
42
+ %(controller: "#{expected[0]}", action: "#{expected[1]}")
43
+ end
44
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Authorizy
4
- VERSION = '0.1.0'
4
+ VERSION = '0.3.0'
5
5
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Authorizy::BaseCop, '#access?' do
4
- subject(:cop) { described_class.new('current_user', 'params', 'session', 'controller', 'action') }
4
+ let!(:params) { { 'controller' => 'controller', 'action' => 'action' } }
5
+ let(:cop) { described_class.new('current_user', params, 'session') }
5
6
 
6
7
  it 'returns false as default' do
7
8
  expect(cop.access?).to be(false)
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Authorizy::Config, '#aliases' do
4
- subject(:config) { described_class.new }
4
+ let!(:config) { described_class.new }
5
5
 
6
6
  it 'has default value and can receive a new one' do
7
- expect(subject.aliases).to eq({})
7
+ expect(config.aliases).to eq({})
8
8
 
9
9
  config.aliases = 'value'
10
10
 
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Authorizy::Config, '#cop' do
4
- subject(:config) { described_class.new }
4
+ let!(:config) { described_class.new }
5
5
 
6
6
  it 'has default value and can receive a new one' do
7
- expect(subject.cop).to eq(Authorizy::BaseCop)
7
+ expect(config.cop).to eq(Authorizy::BaseCop)
8
8
 
9
9
  config.cop = 'value'
10
10
 
@@ -1,29 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Authorizy::Config, '#current_user' do
4
- subject(:config) { described_class.new }
4
+ let!(:config) { described_class.new }
5
5
 
6
6
  context 'when uses default value' do
7
7
  context 'when context responds to current_user' do
8
8
  let!(:context) { OpenStruct.new(current_user: 'user') }
9
9
 
10
10
  it 'is called' do
11
- expect(subject.current_user.call(context)).to eq('user')
11
+ expect(config.current_user.call(context)).to eq('user')
12
12
  end
13
13
  end
14
14
 
15
15
  context 'when context does not respond to current_user' do
16
16
  let!(:context) { 'context' }
17
17
 
18
- it 'returns nil' do
19
- expect(subject.current_user.call(context)).to be(nil)
20
- end
18
+ it { expect(config.current_user.call(context)).to be(nil) }
21
19
  end
22
20
  end
23
21
 
24
22
  context 'when uses custom value' do
25
23
  it 'executes what you want' do
26
- config.current_user = -> (context) { context[:value] }
24
+ config.current_user = ->(context) { context[:value] }
27
25
 
28
26
  expect(config.current_user.call({ value: 'value' })).to eq('value')
29
27
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Authorizy::Config, '#dependencies' do
4
- subject(:config) { described_class.new }
4
+ let!(:config) { described_class.new }
5
5
 
6
6
  it 'has default value and can receive a new one' do
7
- expect(subject.dependencies).to eq({})
7
+ expect(config.dependencies).to eq({})
8
8
 
9
9
  config.dependencies = 'value'
10
10
 
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Authorizy::Config, '#field' do
4
+ let!(:config) { described_class.new }
5
+
6
+ context 'when uses default value' do
7
+ context 'when current_user responds to authorizy' do
8
+ let!(:current_user) { OpenStruct.new(authorizy: { permissions: [%i[users index]] }) }
9
+
10
+ it 'is called' do
11
+ expect(config.field.call(current_user)).to eq(permissions: [%i[users index]])
12
+ end
13
+ end
14
+
15
+ context 'when current_user does not respond to field' do
16
+ let!(:current_user) { nil }
17
+
18
+ it { expect(config.field.call(current_user)).to eq({}) }
19
+ end
20
+ end
21
+
22
+ context 'when uses custom value' do
23
+ it 'executes what you want' do
24
+ config.field = ->(current_user) { current_user[:value] }
25
+
26
+ expect(config.field.call({ value: 'value' })).to eq('value')
27
+ end
28
+ end
29
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  RSpec.describe Authorizy::Config do
4
4
  it 'starts with a default cop' do
5
- expect(subject.cop).to eq(Authorizy::BaseCop)
5
+ expect(described_class.new.cop).to eq(Authorizy::BaseCop)
6
6
  end
7
7
  end
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Authorizy::Config, '#redirect_url' do
4
- subject(:config) { described_class.new }
4
+ let!(:config) { described_class.new }
5
5
 
6
6
  context 'when uses default value' do
7
7
  context 'when context responds to root_url' do
8
8
  let!(:context) { OpenStruct.new(root_url: '/root') }
9
9
 
10
10
  it 'is called' do
11
- expect(subject.redirect_url.call(context)).to eq('/root')
11
+ expect(config.redirect_url.call(context)).to eq('/root')
12
12
  end
13
13
  end
14
14
 
@@ -16,14 +16,14 @@ RSpec.describe Authorizy::Config, '#redirect_url' do
16
16
  let!(:context) { 'context' }
17
17
 
18
18
  it 'returns just a slash' do
19
- expect(subject.redirect_url.call(context)).to eq('/')
19
+ expect(config.redirect_url.call(context)).to eq('/')
20
20
  end
21
21
  end
22
22
  end
23
23
 
24
24
  context 'when uses custom value' do
25
25
  it 'executes what you want' do
26
- config.redirect_url = -> (context) { context[:value] }
26
+ config.redirect_url = ->(context) { context[:value] }
27
27
 
28
28
  expect(config.redirect_url.call({ value: 'value' })).to eq('value')
29
29
  end
@@ -5,7 +5,6 @@ require 'support/models/empty_cop'
5
5
  require 'support/controllers/dummy_controller'
6
6
 
7
7
  RSpec.describe DummyController, '#authorizy', type: :controller do
8
- let!(:parameters) { ActionController::Parameters.new(key: 'value', controller: 'dummy', action: 'action') }
9
8
  let!(:user) { User.new }
10
9
 
11
10
  context 'when cop responds to the controller name' do
@@ -30,7 +29,7 @@ RSpec.describe DummyController, '#authorizy', type: :controller do
30
29
  end
31
30
  end
32
31
 
33
- context 'when cop responds to the controller name' do
32
+ context 'when cop does not respond to the controller name' do
34
33
  it 'denies the access' do
35
34
  config_mock(cop: EmptyCop, current_user: user) do
36
35
  get :action
@@ -3,13 +3,14 @@
3
3
  require 'support/models/authorizy_cop'
4
4
 
5
5
  RSpec.describe AuthorizyCop do
6
- subject(:cop) { described_class.new('current_user', 'params', 'session', 'controller', 'action') }
6
+ let!(:params) { { controller: 'controller', action: 'action' } }
7
+ let(:cop) { described_class.new('current_user', params, 'session') }
7
8
 
8
9
  it 'adds private attributes readers' do
9
- expect(cop.get_action).to eq('action')
10
- expect(cop.get_controller).to eq('controller')
11
- expect(cop.get_current_user).to eq('current_user')
12
- expect(cop.get_params).to eq('params')
13
- expect(cop.get_session).to eq('session')
10
+ expect(cop.fetch_action).to eq('action')
11
+ expect(cop.fetch_controller).to eq('controller')
12
+ expect(cop.fetch_current_user).to eq('current_user')
13
+ expect(cop.fetch_params).to eq(controller: 'controller', action: 'action')
14
+ expect(cop.fetch_session).to eq('session')
14
15
  end
15
16
  end
@@ -5,7 +5,6 @@ require 'support/models/empty_cop'
5
5
  require 'support/controllers/admin/dummy_controller'
6
6
 
7
7
  RSpec.describe Admin::DummyController, '#authorizy', type: :controller do
8
- let!(:parameters) { ActionController::Parameters.new(key: 'value', controller: 'admin/users', action: 'action') }
9
8
  let!(:user) { User.new }
10
9
 
11
10
  context 'when cop responds to the controller name' do
@@ -30,7 +29,7 @@ RSpec.describe Admin::DummyController, '#authorizy', type: :controller do
30
29
  end
31
30
  end
32
31
 
33
- context 'when cop responds to the controller name' do
32
+ context 'when cop does not respond to the controller name' do
34
33
  it 'denies the access' do
35
34
  config_mock(cop: EmptyCop, current_user: user) do
36
35
  get :action
@@ -1,137 +1,181 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Authorizy::Core, '#access?' do
4
- context 'when permissions is in session as string' do
4
+ context 'when cop#access? returns true' do
5
+ let!(:cop) { OpenStruct.new(access?: true) }
5
6
  let!(:current_user) { User.new }
6
- let!(:params) { { 'action' => 'create', 'controller' => 'controller' } }
7
- let!(:session) { { 'permissions' => [{ 'action' => 'create', 'controller' => 'controller' }] } }
7
+ let!(:params) { { action: 'any', controller: 'any' } }
8
+ let!(:session) { {} }
8
9
 
9
- it 'uses the session value skipping the user fetch' do
10
- expect(described_class.new(current_user, params, session).access?).to be(true)
10
+ it 'is authorized based in the cop response' do
11
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(true)
11
12
  end
12
13
  end
13
14
 
14
- context 'when permissions is not in session' do
15
- subject(:authorizy) { described_class.new(current_user, params, session) }
16
-
17
- let!(:current_user) { User.new(authorizy: { permissions: [{ action: 'create', controller: 'match' }] }) }
18
- let!(:params) { { 'action' => 'create', 'controller' => 'match' } }
15
+ context 'when permissions is in the current user' do
16
+ let!(:cop) { OpenStruct.new(access?: false) }
17
+ let!(:current_user) { User.new(authorizy: { permissions: [%w[controller create]] }) }
18
+ let!(:params) { { controller: 'controller', action: 'create' } }
19
19
  let!(:session) { {} }
20
20
 
21
- it 'fetches the permission from user' do
22
- expect(authorizy.access?).to be(true)
21
+ it 'is authorized based on the user permissions' do
22
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(true)
23
23
  end
24
24
  end
25
25
 
26
26
  context 'when session has no permission nor the user' do
27
- subject(:authorizy) { described_class.new(current_user, params, session) }
28
-
27
+ let!(:cop) { OpenStruct.new(access?: false) }
29
28
  let!(:current_user) { User.new }
30
- let!(:params) { { 'action' => 'create', 'controller' => 'match' } }
29
+ let!(:params) { { controller: 'match', action: 'create' } }
31
30
  let!(:session) { {} }
32
31
 
33
- it { expect(authorizy.access?).to be(false) }
32
+ it 'does not authorize' do
33
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(false)
34
+ end
34
35
  end
35
36
 
36
37
  context 'when cop does not respond to controller' do
37
- subject(:authorizy) { described_class.new(current_user, params, session) }
38
-
39
- let!(:cop) { instance_double('Authorizy.config.cop') }
38
+ let!(:cop) { instance_double('Authorizy::BaseCop', access?: false) }
40
39
  let!(:current_user) { User.new }
41
- let!(:params) { { 'action' => 'create', 'controller' => 'missing' } }
40
+ let!(:params) { { action: 'create', controller: 'missing' } }
42
41
  let!(:session) { {} }
43
42
 
44
- before do
45
- allow(Authorizy.config.cop).to receive(:new)
46
- .with(current_user, params, session, 'missing', 'create')
47
- .and_return(cop)
48
-
49
- allow(cop).to receive(:respond_to?).with('missing').and_return(false)
50
- end
51
-
52
43
  it 'does not authorize via cop' do
53
- expect(authorizy.access?).to be(false)
44
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(false)
54
45
  end
55
46
  end
56
47
 
57
48
  context 'when cop responds to controller' do
58
- subject(:authorizy) { described_class.new(current_user, params, session) }
59
-
60
- let!(:cop) { instance_double('Authorizy.config.cop') }
61
49
  let!(:current_user) { User.new }
62
- let!(:params) { { 'action' => 'create', 'controller' => 'match' } }
50
+ let!(:params) { { controller: 'admin/controller', action: 'create' } }
63
51
  let!(:session) { {} }
64
52
 
65
- before do
66
- allow(Authorizy.config.cop).to receive(:new)
67
- .with(current_user, params, session, 'match', 'create')
68
- .and_return(cop)
69
-
70
- allow(cop).to receive(:respond_to?).with('match').and_return(true)
71
- end
72
-
73
53
  context 'when cop does not release the access' do
74
- it 'continues trying via session and so user permissions' do
75
- allow(cop).to receive(:public_send).with('match').and_return(false)
54
+ let!(:cop) do
55
+ Class.new(Authorizy::BaseCop) do
56
+ def access?
57
+ false
58
+ end
59
+
60
+ def admin__controller
61
+ false
62
+ end
63
+ end.new(current_user, params, session)
64
+ end
76
65
 
77
- expect(authorizy.access?).to be(false)
66
+ it 'is not authorized by cop' do
67
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(false)
78
68
  end
79
69
  end
80
70
 
81
71
  context 'when cop releases the access' do
82
- it 'skips session and user permission return true to the access' do
83
- allow(cop).to receive(:public_send).with('match').and_return(true)
72
+ let!(:cop) do
73
+ Class.new(Authorizy::BaseCop) do
74
+ def access?
75
+ false
76
+ end
77
+
78
+ def admin__controller
79
+ true
80
+ end
81
+ end.new(current_user, params, session)
82
+ end
84
83
 
85
- expect(authorizy.access?).to be(true)
84
+ it 'is authorized by the cop' do
85
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(true)
86
86
  end
87
87
  end
88
- end
89
88
 
90
- context 'when controller is given' do
91
- subject(:authorizy) { described_class.new(current_user, params, session, controller: 'controller') }
89
+ context 'when cop return nil' do
90
+ let!(:cop) do
91
+ Class.new(Authorizy::BaseCop) do
92
+ def access?
93
+ false
94
+ end
95
+
96
+ def admin__controller
97
+ nil
98
+ end
99
+ end.new(current_user, params, session)
100
+ end
92
101
 
93
- let!(:current_user) { User.new }
94
- let!(:params) { { 'action' => 'action', 'controller' => 'ignored' } }
95
- let!(:session) { { 'permissions' => [{ 'action' => 'action', 'controller' => 'controller' }] } }
102
+ it 'is converted to false' do
103
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(false)
104
+ end
105
+ end
106
+
107
+ context 'when cop return empty' do
108
+ let!(:cop) do
109
+ Class.new(Authorizy::BaseCop) do
110
+ def access?
111
+ false
112
+ end
113
+
114
+ def admin__controller
115
+ ''
116
+ end
117
+ end.new(current_user, params, session)
118
+ end
96
119
 
97
- it 'uses the given controller over the one on params' do
98
- expect(authorizy.access?).to be(true)
120
+ it 'is converted to false' do
121
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(false)
122
+ end
99
123
  end
100
- end
101
124
 
102
- context 'when action is given' do
103
- subject(:authorizy) { described_class.new(current_user, params, session, action: 'action') }
125
+ context 'when cop return nothing' do
126
+ let!(:cop) do
127
+ Class.new(Authorizy::BaseCop) do
128
+ def access?
129
+ false
130
+ end
104
131
 
105
- let!(:current_user) { User.new }
106
- let!(:params) { { 'action' => 'ignored', 'controller' => 'controller' } }
107
- let!(:session) { { 'permissions' => [{ 'action' => 'action', 'controller' => 'controller' }] } }
132
+ def admin__controller; end
133
+ end.new(current_user, params, session)
134
+ end
108
135
 
109
- it 'uses the given action over the one on params' do
110
- expect(authorizy.access?).to be(true)
136
+ it 'is converted to false' do
137
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(false)
138
+ end
139
+ end
140
+
141
+ context 'when cop return true as string' do
142
+ let!(:cop) do
143
+ Class.new(Authorizy::BaseCop) do
144
+ def access?
145
+ false
146
+ end
147
+
148
+ def admin__controller
149
+ 'true'
150
+ end
151
+ end.new(current_user, params, session)
152
+ end
153
+
154
+ it 'is converted to false' do
155
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(false)
156
+ end
111
157
  end
112
158
  end
113
159
 
114
160
  context 'when user has the controller permission but not action' do
115
- subject(:authorizy) { described_class.new(current_user, params, session) }
116
-
161
+ let!(:cop) { instance_double('Authorizy::BaseCop', access?: false) }
117
162
  let!(:current_user) { User.new }
118
- let!(:params) { { 'action' => 'action', 'controller' => 'controller' } }
119
- let!(:session) { { 'permissions' => [{ 'action' => 'miss', 'controller' => 'controller' }] } }
163
+ let!(:params) { { controller: 'controller', action: 'action' } }
164
+ let!(:session) { { permissions: [%w[controller miss]] } }
120
165
 
121
- it 'cannot access' do
122
- expect(authorizy.access?).to be(false)
166
+ it 'is not authorized' do
167
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(false)
123
168
  end
124
169
  end
125
170
 
126
171
  context 'when user has the action permission but not controller' do
127
- subject(:authorizy) { described_class.new(current_user, params, session) }
128
-
172
+ let!(:cop) { instance_double('Authorizy::BaseCop', access?: false) }
129
173
  let!(:current_user) { User.new }
130
- let!(:params) { { 'action' => 'action', 'controller' => 'controller' } }
131
- let!(:session) { { 'permissions' => [{ 'action' => 'create', 'controller' => 'miss' }] } }
174
+ let!(:params) { { controller: 'controller', action: 'action' } }
175
+ let!(:session) { { permissions: [%w[miss action]] } }
132
176
 
133
- it 'cannot access' do
134
- expect(authorizy.access?).to be(false)
177
+ it 'is not authorized' do
178
+ expect(described_class.new(current_user, params, session, cop: cop).access?).to be(false)
135
179
  end
136
180
  end
137
181
  end