g5_authenticatable 0.7.5 → 0.8.0.beta1
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.
- checksums.yaml +4 -4
- data/app/models/g5_authenticatable/user.rb +8 -0
- data/app/policies/g5_authenticatable/base_policy.rb +5 -1
- data/app/policies/g5_updatable/client_policy.rb +10 -9
- data/app/policies/g5_updatable/location_policy.rb +40 -0
- data/app/policies/g5_updatable/selectable_client_policy.rb +38 -0
- data/lib/g5_authenticatable/version.rb +1 -1
- data/spec/dummy/config/application.rb +2 -0
- data/spec/policies/client_policy_spec.rb +34 -32
- data/spec/policies/location_policy_spec.rb +65 -0
- data/spec/policies/selectable_client_policy_spec.rb +82 -0
- metadata +10 -6
- data/spec/policies/post_policy_spec.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e740b6fbbb4a9876775c1e76db296562d6283bd6
|
4
|
+
data.tar.gz: 8c9d75eb84818206367591faeac2f675f2616769
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fdd634b6c2ed9e3f7dfd75a0d11e4a9ea8deac800f88a154a8e76651650c75e776e0ccc9f7b13a39941ede01c44201987aea1450605bc3569e1739cf9d1696d7
|
7
|
+
data.tar.gz: f1a47879f8b0d9f5af31a53f5740b14bb016a1849ff65f30fbe08ee70466c1882fd2cb304c8d1debdfc40cafccc292dcac650be2d2207d01facbfb054cab1573
|
@@ -37,10 +37,18 @@ module G5Authenticatable
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
+
def selectable_clients
|
41
|
+
G5Updatable::SelectableClientPolicy::Scope.new(self, G5Updatable::Client).resolve
|
42
|
+
end
|
43
|
+
|
40
44
|
def clients
|
41
45
|
G5Updatable::ClientPolicy::Scope.new(self, G5Updatable::Client).resolve
|
42
46
|
end
|
43
47
|
|
48
|
+
def locations
|
49
|
+
G5Updatable::LocationPolicy::Scope.new(self, G5Updatable::Location).resolve
|
50
|
+
end
|
51
|
+
|
44
52
|
private
|
45
53
|
|
46
54
|
def self.extended_auth_attributes(auth_data)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class G5Authenticatable::BasePolicy
|
2
2
|
attr_reader :user, :record
|
3
3
|
|
4
|
-
def initialize(user, record)
|
4
|
+
def initialize(user, record=nil)
|
5
5
|
@user = user
|
6
6
|
@record = record
|
7
7
|
end
|
@@ -53,6 +53,10 @@ class G5Authenticatable::BasePolicy
|
|
53
53
|
scope.none
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
def has_global_role?
|
58
|
+
G5Authenticatable::BasePolicy.new(user, G5Updatable::Client).has_global_role?
|
59
|
+
end
|
56
60
|
end
|
57
61
|
|
58
62
|
def super_admin?
|
@@ -1,22 +1,23 @@
|
|
1
|
+
# Clients defined by this policy are ones for whom the user has access at the client level. This means that either
|
2
|
+
# they have a global role or that have a specific client role.
|
1
3
|
module G5Updatable
|
2
4
|
class ClientPolicy < G5Authenticatable::BasePolicy
|
3
5
|
class Scope < G5Authenticatable::BasePolicy::BaseScope
|
4
6
|
|
5
7
|
def resolve
|
6
8
|
return scope.all if has_global_role?
|
7
|
-
|
9
|
+
client_with_roles
|
8
10
|
end
|
9
11
|
|
10
|
-
|
11
|
-
G5Authenticatable::Role
|
12
|
-
.joins('INNER JOIN g5_updatable_clients ON g5_updatable_clients.id = g5_authenticatable_roles.resource_id')
|
13
|
-
.joins('INNER JOIN g5_authenticatable_users_roles ON g5_authenticatable_roles.id = g5_authenticatable_users_roles.role_id')
|
14
|
-
.where('g5_authenticatable_roles.resource_type = ? and g5_authenticatable_users_roles.user_id = ?', G5Updatable::Client.name, user.id)
|
15
|
-
end
|
12
|
+
private
|
16
13
|
|
17
|
-
def
|
18
|
-
|
14
|
+
def client_with_roles
|
15
|
+
G5Updatable::Client
|
16
|
+
.joins('INNER JOIN g5_authenticatable_roles as r ON r.resource_id = g5_updatable_clients.id')
|
17
|
+
.joins('INNER JOIN g5_authenticatable_users_roles as ur ON r.id = ur.role_id')
|
18
|
+
.where('r.resource_type = ? and ur.user_id = ?', G5Updatable::Client.name, user.id)
|
19
19
|
end
|
20
|
+
|
20
21
|
end
|
21
22
|
|
22
23
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# The policy will resolve to all locations that a user has access. This includes locations that a user has roles for
|
2
|
+
# but also those locations for which a user has a client role. Global roles grant access to ALL locations.
|
3
|
+
module G5Updatable
|
4
|
+
class LocationPolicy < G5Authenticatable::BasePolicy
|
5
|
+
class Scope < G5Authenticatable::BasePolicy::BaseScope
|
6
|
+
|
7
|
+
def resolve
|
8
|
+
locations_from_client_location_roles
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def location_roles
|
14
|
+
G5Authenticatable::Role
|
15
|
+
.joins('INNER JOIN g5_updatable_locations as l ON l.id = g5_authenticatable_roles.resource_id')
|
16
|
+
.joins('INNER JOIN g5_authenticatable_users_roles as ur ON g5_authenticatable_roles.id = ur.role_id')
|
17
|
+
.where('g5_authenticatable_roles.resource_type = ? and ur.user_id = ?',
|
18
|
+
G5Updatable::Location.name, user.id)
|
19
|
+
end
|
20
|
+
|
21
|
+
def locations_from_client_roles
|
22
|
+
G5Updatable::Location
|
23
|
+
.joins('INNER JOIN g5_updatable_clients as c on g5_updatable_locations.client_uid=c.uid')
|
24
|
+
.joins('INNER JOIN g5_authenticatable_roles as r on r.resource_id=c.id')
|
25
|
+
.joins('INNER JOIN g5_authenticatable_users_roles as ur on r.id=ur.role_id')
|
26
|
+
.where('ur.user_id=?',user.id)
|
27
|
+
.where('r.resource_type=?', G5Updatable::Client.name)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def locations_from_client_location_roles
|
32
|
+
return scope.all if has_global_role?
|
33
|
+
location_ids = locations_from_client_roles.map(&:id) | location_roles.map(&:resource_id)
|
34
|
+
G5Updatable::Location.where(id: location_ids)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Policy to define which clients are show to users to select. This includes all clients for whom a user only
|
2
|
+
# has a location scoped role. Clients defined by this policy are not necessarily granted view permissions at the client
|
3
|
+
# level.
|
4
|
+
module G5Updatable
|
5
|
+
class SelectableClientPolicy < G5Authenticatable::BasePolicy
|
6
|
+
class Scope < G5Authenticatable::BasePolicy::BaseScope
|
7
|
+
|
8
|
+
def resolve
|
9
|
+
return clients_from_client_and_location_roles
|
10
|
+
end
|
11
|
+
|
12
|
+
def client_roles
|
13
|
+
G5Authenticatable::Role
|
14
|
+
.joins('INNER JOIN g5_updatable_clients as c ON c.id = g5_authenticatable_roles.resource_id')
|
15
|
+
.joins('INNER JOIN g5_authenticatable_users_roles as ur ON g5_authenticatable_roles.id = ur.role_id')
|
16
|
+
.where('g5_authenticatable_roles.resource_type = ? and ur.user_id = ?', G5Updatable::Client.name, user.id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def clients_from_client_and_location_roles
|
20
|
+
return scope.all if has_global_role?
|
21
|
+
client_ids = clients_from_location_roles.map(&:id) | client_roles.map(&:resource_id)
|
22
|
+
G5Updatable::Client.where(id: client_ids)
|
23
|
+
end
|
24
|
+
|
25
|
+
def clients_from_location_roles
|
26
|
+
G5Updatable::Client
|
27
|
+
.joins('INNER JOIN g5_updatable_locations as l on l.client_uid=g5_updatable_clients.uid')
|
28
|
+
.joins('INNER JOIN g5_authenticatable_roles as r on l.id=r.resource_id')
|
29
|
+
.joins('INNER JOIN g5_authenticatable_users_roles as ur on r.id=ur.role_id')
|
30
|
+
.where('r.resource_type = ? and ur.user_id = ?',
|
31
|
+
G5Updatable::Location.name, user.id)
|
32
|
+
.group('g5_updatable_clients.id')
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -16,44 +16,46 @@ describe G5Updatable::ClientPolicy do
|
|
16
16
|
let!(:client_2) { FactoryGirl.create(:g5_updatable_client) }
|
17
17
|
let!(:client_3) { FactoryGirl.create(:g5_updatable_client) }
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
19
|
+
describe '.resolve' do
|
20
|
+
|
21
|
+
subject { G5Updatable::ClientPolicy::Scope.new(user, G5Updatable::Client).resolve }
|
22
|
+
|
23
|
+
context 'with global role' do
|
24
|
+
before { user.add_role :admin }
|
25
|
+
it 'returns all clients' do
|
26
|
+
expect(subject.length).to eq(3)
|
27
|
+
expect(subject).to include(client_1)
|
28
|
+
expect(subject).to include(client_2)
|
29
|
+
expect(subject).to include(client_3)
|
30
|
+
end
|
28
31
|
end
|
29
|
-
end
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
context 'with client role' do
|
34
|
+
before { user.add_role(:admin, client_1) }
|
35
|
+
it 'returns a single client' do
|
36
|
+
expect(subject.length).to eq(1)
|
37
|
+
expect(subject).to include(client_1)
|
38
|
+
end
|
36
39
|
end
|
37
|
-
end
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
41
|
+
context 'with many client roles' do
|
42
|
+
before do
|
43
|
+
user.add_role(:admin, client_1)
|
44
|
+
user.add_role(:admin, client_2)
|
45
|
+
user.add_role(:admin, client_3)
|
46
|
+
end
|
47
|
+
it 'returns all assigned clients' do
|
48
|
+
expect(subject.length).to eq(3)
|
49
|
+
expect(subject).to include(client_1)
|
50
|
+
expect(subject).to include(client_2)
|
51
|
+
expect(subject).to include(client_3)
|
52
|
+
end
|
50
53
|
end
|
51
|
-
end
|
52
54
|
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
context 'with no role' do
|
56
|
+
it 'returns no clients' do
|
57
|
+
expect(subject.length).to eq(0)
|
58
|
+
end
|
56
59
|
end
|
57
60
|
end
|
58
|
-
|
59
61
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe G5Updatable::LocationPolicy do
|
4
|
+
subject(:policy) { described_class }
|
5
|
+
|
6
|
+
let(:user) { FactoryGirl.create(:g5_authenticatable_user) }
|
7
|
+
let(:user2) { FactoryGirl.create(:g5_authenticatable_user) }
|
8
|
+
|
9
|
+
let!(:client_1) { FactoryGirl.create(:g5_updatable_client) }
|
10
|
+
let!(:client_2) { FactoryGirl.create(:g5_updatable_client) }
|
11
|
+
|
12
|
+
let!(:location_1) { FactoryGirl.create(:g5_updatable_location, client: client_1) }
|
13
|
+
let!(:location_2) { FactoryGirl.create(:g5_updatable_location, client: client_1) }
|
14
|
+
|
15
|
+
let!(:location_3) { FactoryGirl.create(:g5_updatable_location, client: client_2) }
|
16
|
+
let!(:location_4) { FactoryGirl.create(:g5_updatable_location, client: client_2) }
|
17
|
+
|
18
|
+
before do
|
19
|
+
user.roles = []
|
20
|
+
user.save!
|
21
|
+
user2.add_role(:viewer, location_1)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '.resolve' do
|
25
|
+
subject { G5Updatable::LocationPolicy::Scope.new(user, G5Updatable::Location).resolve }
|
26
|
+
|
27
|
+
context 'with global role' do
|
28
|
+
before { user.add_role :admin }
|
29
|
+
it 'returns all locations' do
|
30
|
+
expect(subject.length).to eq(4)
|
31
|
+
expect(subject).to include(location_1)
|
32
|
+
expect(subject).to include(location_2)
|
33
|
+
expect(subject).to include(location_3)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'with location role' do
|
38
|
+
before { user.add_role(:admin, location_1) }
|
39
|
+
it 'returns a single location' do
|
40
|
+
expect(subject.length).to eq(1)
|
41
|
+
expect(subject).to include(location_1)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with many client roles' do
|
46
|
+
before do
|
47
|
+
user.add_role(:admin, location_1)
|
48
|
+
user.add_role(:admin, location_2)
|
49
|
+
user.add_role(:admin, location_3)
|
50
|
+
end
|
51
|
+
it 'returns all assigned clients' do
|
52
|
+
expect(subject.length).to eq(3)
|
53
|
+
expect(subject).to include(location_1)
|
54
|
+
expect(subject).to include(location_2)
|
55
|
+
expect(subject).to include(location_3)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'with no role' do
|
60
|
+
it 'returns no locations' do
|
61
|
+
expect(subject.length).to eq(0)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe G5Updatable::SelectableClientPolicy do
|
4
|
+
subject(:policy) { described_class }
|
5
|
+
|
6
|
+
let(:user) { FactoryGirl.create(:g5_authenticatable_user) }
|
7
|
+
let(:user2) { FactoryGirl.create(:g5_authenticatable_user) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
user.roles = []
|
11
|
+
user.save!
|
12
|
+
user2.add_role(:viewer, client_1)
|
13
|
+
end
|
14
|
+
|
15
|
+
let!(:client_1) { FactoryGirl.create(:g5_updatable_client) }
|
16
|
+
let!(:client_2) { FactoryGirl.create(:g5_updatable_client) }
|
17
|
+
let!(:client_3) { FactoryGirl.create(:g5_updatable_client) }
|
18
|
+
|
19
|
+
describe '.resolve' do
|
20
|
+
subject { G5Updatable::SelectableClientPolicy::Scope.new(user, G5Updatable::Client).resolve }
|
21
|
+
|
22
|
+
let!(:location_1) { FactoryGirl.create(:g5_updatable_location, client: client_1) }
|
23
|
+
let!(:location_2) { FactoryGirl.create(:g5_updatable_location, client: client_1) }
|
24
|
+
|
25
|
+
let!(:location_3) { FactoryGirl.create(:g5_updatable_location, client: client_2) }
|
26
|
+
let!(:location_4) { FactoryGirl.create(:g5_updatable_location, client: client_2) }
|
27
|
+
|
28
|
+
context 'with global role' do
|
29
|
+
before { user.add_role :admin }
|
30
|
+
it 'returns all clients' do
|
31
|
+
expect(subject.length).to eq(3)
|
32
|
+
expect(subject).to include(client_1)
|
33
|
+
expect(subject).to include(client_2)
|
34
|
+
expect(subject).to include(client_3)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'with role for location and for client that location belongs to' do
|
39
|
+
before do
|
40
|
+
user.add_role :admin, location_1
|
41
|
+
user.add_role :admin, client_1
|
42
|
+
end
|
43
|
+
it 'returns 1 client' do
|
44
|
+
expect(subject.length).to eq(1)
|
45
|
+
expect(subject).to include(client_1)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with role for location and client that location does not belong to' do
|
50
|
+
before do
|
51
|
+
user.add_role :admin, location_1
|
52
|
+
user.add_role :admin, client_2
|
53
|
+
end
|
54
|
+
it 'returns 1 client' do
|
55
|
+
expect(subject.length).to eq(2)
|
56
|
+
expect(subject).to include(client_1)
|
57
|
+
expect(subject).to include(client_2)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with a client role' do
|
62
|
+
before do
|
63
|
+
user.add_role :admin, client_2
|
64
|
+
end
|
65
|
+
it 'returns 1 client' do
|
66
|
+
expect(subject.length).to eq(1)
|
67
|
+
expect(subject).to include(client_2)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'with a location role' do
|
72
|
+
before do
|
73
|
+
user.add_role :admin, location_1
|
74
|
+
end
|
75
|
+
it 'returns 1 client' do
|
76
|
+
expect(subject.length).to eq(1)
|
77
|
+
expect(subject).to include(client_1)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: g5_authenticatable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- maeve
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-02-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: devise_g5_authenticatable
|
@@ -126,6 +126,8 @@ files:
|
|
126
126
|
- app/models/g5_authenticatable/user.rb
|
127
127
|
- app/policies/g5_authenticatable/base_policy.rb
|
128
128
|
- app/policies/g5_updatable/client_policy.rb
|
129
|
+
- app/policies/g5_updatable/location_policy.rb
|
130
|
+
- app/policies/g5_updatable/selectable_client_policy.rb
|
129
131
|
- app/services/g5_authenticatable/impersonate_sessionable.rb
|
130
132
|
- app/views/g5_authenticatable/error/auth_error.html.erb
|
131
133
|
- app/views/layouts/g5_authenticatable/application.html.erb
|
@@ -236,7 +238,8 @@ files:
|
|
236
238
|
- spec/models/post_spec.rb
|
237
239
|
- spec/policies/application_policy_spec.rb
|
238
240
|
- spec/policies/client_policy_spec.rb
|
239
|
-
- spec/policies/
|
241
|
+
- spec/policies/location_policy_spec.rb
|
242
|
+
- spec/policies/selectable_client_policy_spec.rb
|
240
243
|
- spec/requests/default_role_authorization_spec.rb
|
241
244
|
- spec/requests/grape_api_spec.rb
|
242
245
|
- spec/requests/rails_api_spec.rb
|
@@ -266,9 +269,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
266
269
|
version: '0'
|
267
270
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
268
271
|
requirements:
|
269
|
-
- - "
|
272
|
+
- - ">"
|
270
273
|
- !ruby/object:Gem::Version
|
271
|
-
version:
|
274
|
+
version: 1.3.1
|
272
275
|
requirements: []
|
273
276
|
rubyforge_project:
|
274
277
|
rubygems_version: 2.2.2
|
@@ -357,7 +360,8 @@ test_files:
|
|
357
360
|
- spec/models/post_spec.rb
|
358
361
|
- spec/policies/application_policy_spec.rb
|
359
362
|
- spec/policies/client_policy_spec.rb
|
360
|
-
- spec/policies/
|
363
|
+
- spec/policies/location_policy_spec.rb
|
364
|
+
- spec/policies/selectable_client_policy_spec.rb
|
361
365
|
- spec/requests/default_role_authorization_spec.rb
|
362
366
|
- spec/requests/grape_api_spec.rb
|
363
367
|
- spec/requests/rails_api_spec.rb
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe PostPolicy do
|
4
|
-
subject(:policy) { described_class }
|
5
|
-
|
6
|
-
let(:record) { FactoryGirl.create(:post) }
|
7
|
-
|
8
|
-
permissions :index? do
|
9
|
-
it_behaves_like 'a super_admin authorizer'
|
10
|
-
end
|
11
|
-
|
12
|
-
permissions :show? do
|
13
|
-
it_behaves_like 'a super_admin authorizer'
|
14
|
-
end
|
15
|
-
|
16
|
-
permissions :new? do
|
17
|
-
it_behaves_like 'a super_admin authorizer'
|
18
|
-
end
|
19
|
-
|
20
|
-
permissions :create? do
|
21
|
-
it_behaves_like 'a super_admin authorizer'
|
22
|
-
end
|
23
|
-
|
24
|
-
permissions :edit? do
|
25
|
-
it_behaves_like 'a super_admin authorizer'
|
26
|
-
end
|
27
|
-
|
28
|
-
permissions :update? do
|
29
|
-
it_behaves_like 'a super_admin authorizer'
|
30
|
-
end
|
31
|
-
|
32
|
-
permissions :destroy? do
|
33
|
-
it_behaves_like 'a super_admin authorizer'
|
34
|
-
end
|
35
|
-
end
|