g5_authenticatable 0.7.3 → 0.7.4.beta.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f56baf7ccaaf8080ddb8287e138495c535a7b5c0
4
- data.tar.gz: feecc8d4ec69a2985e6ee769a0b0bb20614e30a4
3
+ metadata.gz: 33d905c7e18808b53851712ddc45868931d5d535
4
+ data.tar.gz: e44568c0480ef175f21a8c72bbd80906af680a37
5
5
  SHA512:
6
- metadata.gz: 5e14a0afcdb5e18630e445914817541d0df7cadc7f55cb0e877b489f129b865aa3130e202d04bc349044aa84e4ad78b61653fc6ff36b5f6d178caae85073d7ec
7
- data.tar.gz: f2cffe7568ac42aae42e3f71f8942224109ef6c8855717e96658bb8f487c08aa76c12ad8c7f8937672024b859a12bf72ca74647b2cbcb9227ce8f78255a63911
6
+ metadata.gz: 4ab02a3e351aab389dec36767a86eb52d7a079c0331be53902b8fd09c06bf2b23583f1cdd80903d7fc9041ca017ecaab8cd755d4682e891aa3ba2d495cb243d9
7
+ data.tar.gz: c8343d576b235a766eccd483a366f4574076fc3d41f949b2f065c1b6dc84b3daa8b59861f6f0c8f8b5f255f0eb09808c28547d89cd2fc08c3a74d3ec9a1cffea
data/CHANGELOG.md CHANGED
@@ -1,7 +1,21 @@
1
+ ## v0.7.4.beta.1 (2015-12-07)
2
+
3
+ * Adds Impersonate (Assume) Devise Strategy and Concern to handle access to session stored values
4
+ * Handles the ability and rules to impersonate a user providing his unique ID
5
+ * Adds the UID from the session and request to be used by the Auth Workflow when present
6
+
1
7
  ## v0.7.3 (2015-11-30)
2
8
  * Upgrade to devise_g5_authenticatable to fix regression bug https://github.com/G5/devise_g5_authenticatable/pull/23
3
9
  * Upgrade to omniauth_g5 to fix regression bug https://github.com/G5/omniauth-g5/pull/10
4
10
 
11
+ ## v0.7.2 (2015-06-23)
12
+
13
+ * Removed pinned g5_updatalbe version from 0.6.0 to > 0.6.0
14
+
15
+ ## v0.7.1 (2015-06-08)
16
+
17
+ * Fixed bug when listing clients
18
+
5
19
  ## v0.7.0 (2015-06-04)
6
20
 
7
21
  * Add convenience methods to `G5Authenticatable::User`, as well as a
@@ -15,13 +15,11 @@ module G5Authenticatable
15
15
  user.assign_attributes(extended_auth_attributes(auth_data))
16
16
  user.update_roles_from_auth(auth_data)
17
17
  end
18
-
19
18
  user
20
19
  end
21
20
 
22
21
  def self.find_and_update_for_g5_oauth(auth_data)
23
22
  user = super(auth_data)
24
-
25
23
  if user
26
24
  user.update_attributes(extended_auth_attributes(auth_data))
27
25
  user.update_roles_from_auth(auth_data)
@@ -33,17 +31,7 @@ module G5Authenticatable
33
31
  def update_roles_from_auth(auth_data)
34
32
  roles.clear
35
33
  auth_data.extra.roles.each do |role|
36
- if(role.type == 'GLOBAL')
37
- add_role(role.name)
38
- else
39
- begin
40
- the_class = Object.const_get(role.type)
41
- resource = the_class.where(urn: role.urn).first
42
- add_role(role.name, resource)
43
- rescue => e
44
- Rails.logger.error(e)
45
- end
46
- end
34
+ role.type == 'GLOBAL' ? add_role(role.name) : add_scoped_role(role)
47
35
  end
48
36
  end
49
37
 
@@ -52,17 +40,24 @@ module G5Authenticatable
52
40
  end
53
41
 
54
42
  private
43
+
55
44
  def self.extended_auth_attributes(auth_data)
56
- {
45
+ h = {
57
46
  first_name: auth_data.info.first_name,
58
47
  last_name: auth_data.info.last_name,
59
48
  phone_number: auth_data.info.phone,
60
49
  title: auth_data.extra.title,
61
50
  organization_name: auth_data.extra.organization_name
62
51
  }
52
+ auth_data.uid.present? ? h.merge!(uid: auth_data.uid) : h
63
53
  end
64
54
 
65
-
66
-
55
+ def add_scoped_role(role)
56
+ the_class = Object.const_get(role.type)
57
+ resource = the_class.where(urn: role.urn).first
58
+ add_role(role.name, resource)
59
+ rescue => e
60
+ Rails.logger.error(e)
61
+ end
67
62
  end
68
63
  end
@@ -0,0 +1,83 @@
1
+ module G5Authenticatable
2
+ module ImpersonateSessionable
3
+ extend ActiveSupport::Concern
4
+
5
+ def impersonation_user?
6
+ impersonation_user.present?
7
+ end
8
+
9
+ def impersonation_user
10
+ user_by_uid(impersonate_admin_uid)
11
+ end
12
+
13
+ def user_to_impersonate
14
+ user_by_uid(impersonating_user_uid)
15
+ end
16
+
17
+ def clear_impersonation_keys
18
+ impersonate_admin_uid = nil
19
+ impersonating_user_uid = nil
20
+ impersonating_user_callback_url = nil
21
+ end
22
+
23
+ # Checks if the user by param is able to impersonate the second user by param
24
+ def check_impersonation_access?(user_impersonating, resource)
25
+ able_to_impersonate?(user_impersonating, resource)
26
+ end
27
+
28
+ private
29
+
30
+ def able_to_impersonate?(user_impersonating, resource)
31
+ return false unless user_impersonating.present? && resource.present?
32
+ if user_impersonating.has_role?(:super_admin) ||
33
+ (user_impersonating.has_role?(:admin) && !resource.has_role?(:super_admin))
34
+ true
35
+ else
36
+ false
37
+ end
38
+ end
39
+
40
+ def user_by_uid(uid)
41
+ G5Authenticatable::User.find_by_uid(uid)
42
+ rescue ActiveRecord::RecordNotFound
43
+ nil
44
+ end
45
+
46
+ # Let's just keep this key secret. you know.. for security reasons.
47
+ IMPERSONATE_SESSION_KEY = 'devise.g5_authenticatable.Xf1eP3hCjC'
48
+ IMPERSONATING_USER_SESSION_KEY = 'devise.g5_authenticatable.Zk35J5adER'
49
+ IMPERSONATING_USER_SESSION_CALLBACK_URL = 'devise.g5_authenticatable.callcbak_url'
50
+
51
+ def impersonate_admin_uid
52
+ request.env['rack.session'][IMPERSONATE_SESSION_KEY]
53
+ end
54
+
55
+ def impersonate_admin_uid=(uid)
56
+ request.env['rack.session'][IMPERSONATE_SESSION_KEY] = uid
57
+ end
58
+
59
+ def impersonate_admin_uid?
60
+ request.env['rack.session'] && request.env['rack.session'][IMPERSONATE_SESSION_KEY].present?
61
+ end
62
+
63
+ def impersonating_user_uid
64
+ request.env['rack.session'][IMPERSONATING_USER_SESSION_KEY]
65
+ end
66
+
67
+ def impersonating_user_uid=(uid)
68
+ request.env['rack.session'][IMPERSONATING_USER_SESSION_KEY] = uid
69
+ end
70
+
71
+ def impersonating_user_uid?
72
+ request.env['rack.session'] && request.env['rack.session'][IMPERSONATING_USER_SESSION_KEY].present?
73
+ end
74
+
75
+ def impersonating_user_callback_url
76
+ request.env['rack.session'][IMPERSONATING_USER_SESSION_CALLBACK_URL] || ''
77
+ end
78
+
79
+ def impersonating_user_callback_url=(callback_url)
80
+ request.env['rack.session'][IMPERSONATING_USER_SESSION_CALLBACK_URL] = callback_url
81
+ end
82
+ end
83
+ end
@@ -237,6 +237,8 @@ Devise.setup do |config|
237
237
  #
238
238
  config.warden do |manager|
239
239
  # Add custom warden configuration here
240
+ manager.strategies.add(:impersonate_strategy, Devise::Strategies::ImpersonateStrategy)
241
+ manager.default_strategies(:scope => :user).unshift :impersonate_strategy
240
242
  end
241
243
 
242
244
 
@@ -0,0 +1,31 @@
1
+ require 'devise/strategies/authenticatable'
2
+ require 'devise/strategies/base'
3
+
4
+ module Devise
5
+ module Strategies
6
+ class ImpersonateStrategy < Authenticatable
7
+ include ::G5Authenticatable::ImpersonateSessionable
8
+
9
+ # Prevents unauthorized users to impersonate another user when visiting the correct URL
10
+ def valid?
11
+ allowed = user_to_impersonate.present? &&
12
+ able_to_impersonate?(impersonation_user, user_to_impersonate)
13
+ return allowed if allowed
14
+ clear_impersonation_keys
15
+ true
16
+ rescue # Safety net
17
+ clear_impersonation_keys
18
+ false
19
+ end
20
+
21
+ def authenticate!
22
+ if user_to_impersonate.present?
23
+ success!(user_to_impersonate)
24
+ else
25
+ clear_impersonation_keys
26
+ fail('You do not have sufficient access to this account')
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
21
  spec.require_paths = ['lib']
22
22
 
23
- spec.add_dependency 'devise_g5_authenticatable', '~> 0.2.3'
23
+ spec.add_dependency 'devise_g5_authenticatable', '~> 0.2.4.beta'
24
24
  spec.add_dependency 'omniauth-g5', '~> 0.3.1'
25
25
  spec.add_dependency 'g5_authenticatable_api', '~> 0.4.1'
26
26
  spec.add_dependency 'rolify', '~> 4.0'
@@ -1,7 +1,6 @@
1
1
  module G5Authenticatable
2
2
  module Test
3
3
  module ControllerHelpers
4
-
5
4
  def login_user(user)
6
5
  @request.env["devise.mapping"] = Devise.mappings[:user]
7
6
  sign_in user
@@ -10,14 +9,35 @@ module G5Authenticatable
10
9
  def logout_user(user)
11
10
  sign_out(user)
12
11
  end
13
-
14
12
  end
15
13
  end
16
14
  end
17
15
 
18
16
  shared_context 'auth controller', auth_controller: true do
19
- include G5Authenticatable::Test::ControllerHelpers
20
17
  let(:user) { FactoryGirl.create(:g5_authenticatable_user) }
18
+ include_context 'authorization controller'
19
+ end
20
+
21
+ shared_context 'super admin auth controller' do
22
+ let(:user) do
23
+ user = FactoryGirl.create(:g5_authenticatable_user)
24
+ user.add_role(:super_admin)
25
+ user
26
+ end
27
+ include_context 'authorization controller'
28
+ end
29
+
30
+ shared_context 'admin auth controller' do
31
+ let(:user) do
32
+ user = FactoryGirl.create(:g5_authenticatable_user)
33
+ user.add_role(:admin)
34
+ user
35
+ end
36
+ include_context 'authorization controller'
37
+ end
38
+
39
+ shared_context 'authorization controller' do
40
+ include G5Authenticatable::Test::ControllerHelpers
21
41
 
22
42
  before do
23
43
  stub_valid_access_token(user.g5_access_token)
@@ -28,9 +48,7 @@ shared_context 'auth controller', auth_controller: true do
28
48
  end
29
49
 
30
50
  shared_examples 'a secure controller' do
31
-
32
51
  controller do
33
-
34
52
  before_filter :authenticate_user!
35
53
 
36
54
  def index
@@ -38,26 +56,22 @@ shared_examples 'a secure controller' do
38
56
  end
39
57
  end
40
58
 
41
- context "without an authenticated user" do
42
-
43
- it "should be redirected" do
59
+ context 'without an authenticated user' do
60
+ it 'should be redirected' do
44
61
  get :index
45
62
  expect(response).to redirect_to('/g5_auth/users/sign_in')
46
63
  end
47
-
48
64
  end
49
65
 
50
66
  context 'with an authenticated user', :auth_controller do
51
-
52
67
  it 'should be successful' do
53
68
  get :index
54
69
  expect(response.body).to eq('content')
55
70
  end
56
-
57
71
  end
58
72
  end
59
73
 
60
74
  RSpec.configure do |config|
61
- config.include Devise::TestHelpers, :type => :controller
75
+ config.include Devise::TestHelpers, type: :controller
62
76
  config.include G5Authenticatable::Test::ControllerHelpers, type: :controller
63
77
  end
@@ -1,3 +1,3 @@
1
1
  module G5Authenticatable
2
- VERSION = '0.7.3'
2
+ VERSION = '0.7.4.beta.1'
3
3
  end
@@ -67,7 +67,6 @@ describe G5Authenticatable::User do
67
67
  OmniAuth::AuthHash.new(
68
68
  {
69
69
  'provider' => new_user_attributes[:provider],
70
- 'uid' => new_user_attributes[:uid],
71
70
  'info' => {
72
71
  'email' => new_user_attributes[:email],
73
72
  'name' => "#{new_user_attributes[:first_name]} #{new_user_attributes[:last_name]}",
@@ -84,7 +83,7 @@ describe G5Authenticatable::User do
84
83
  'title' => new_user_attributes[:title],
85
84
  'organization_name' => new_user_attributes[:organization_name],
86
85
  'roles' => [
87
- {'name' => new_role_attributes[:name], 'type' => 'GLOBAL', 'urn' => nil}
86
+ { 'name' => new_role_attributes[:name], 'type' => 'GLOBAL', 'urn' => nil }
88
87
  ],
89
88
  'raw_info' => {}
90
89
  }
@@ -95,7 +94,24 @@ describe G5Authenticatable::User do
95
94
  let(:new_role_attributes) { FactoryGirl.attributes_for(:g5_authenticatable_role) }
96
95
 
97
96
  context 'when there is auth data in the session' do
98
- let(:session) { {'omniauth.auth' => auth_data} }
97
+ let(:session) do
98
+ { 'omniauth.auth' => auth_data }
99
+ end
100
+
101
+ context 'with UID' do
102
+ before do
103
+ auth_data['uid'] = new_user_attributes[:uid]
104
+ end
105
+ it 'should set the uid from the session data' do
106
+ expect(new_user.uid).to eq(new_user_attributes[:uid])
107
+ end
108
+ end
109
+
110
+ context 'without UID' do
111
+ it "won't set the uid from the session data" do
112
+ expect(new_user.uid).to be_nil
113
+ end
114
+ end
99
115
 
100
116
  it 'should initialize a new user' do
101
117
  expect(new_user).to be_a_new_record
@@ -109,10 +125,6 @@ describe G5Authenticatable::User do
109
125
  expect(new_user.provider).to eq(new_user_attributes[:provider])
110
126
  end
111
127
 
112
- it 'should set the uid from the session data' do
113
- expect(new_user.uid).to eq(new_user_attributes[:uid])
114
- end
115
-
116
128
  it 'should set the email from the session data' do
117
129
  expect(new_user.email).to eq(new_user_attributes[:email])
118
130
  end
@@ -210,7 +222,7 @@ describe G5Authenticatable::User do
210
222
  'title' => updated_attributes[:title],
211
223
  'organization_name' => updated_attributes[:organization_name],
212
224
  'roles' => [
213
- {name: updated_role_name, type: 'GLOBAL', urn: nil}
225
+ { name: updated_role_name, type: 'GLOBAL', urn: nil }
214
226
  ],
215
227
  'raw_info' => {}
216
228
  }
@@ -477,5 +489,4 @@ describe G5Authenticatable::User do
477
489
  end
478
490
  end
479
491
  end
480
-
481
492
  end
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ describe G5Authenticatable::ImpersonateSessionable do
4
+ let!(:user) { FactoryGirl.create(:g5_authenticatable_user) }
5
+
6
+ class MyImpersponateSessionableTest
7
+ include G5Authenticatable::ImpersonateSessionable
8
+ end
9
+
10
+ let(:service_instance) { MyImpersponateSessionableTest.new }
11
+
12
+ describe '#impersonation_user?' do
13
+ subject(:impersonation_user) { service_instance.send(:impersonation_user?) }
14
+
15
+ before do
16
+ expect(service_instance).to receive(:impersonation_user).and_return(user)
17
+ end
18
+
19
+ it { expect(impersonation_user).to be_truthy }
20
+ end
21
+
22
+ describe '#impersonation_user' do
23
+ subject(:impersonation_user) { service_instance.send(:impersonation_user) }
24
+
25
+ before do
26
+ expect(service_instance).to receive(:impersonate_admin_uid).and_return(user.uid)
27
+ end
28
+
29
+ it { expect(impersonation_user).to eq(user) }
30
+ end
31
+
32
+ describe '#user_to_impersonate' do
33
+ subject(:user_to_impersonate) { service_instance.send(:user_to_impersonate) }
34
+
35
+ before do
36
+ expect(service_instance).to receive(:impersonating_user_uid).and_return(user.uid)
37
+ end
38
+
39
+ it { expect(user_to_impersonate).to eq(user) }
40
+ end
41
+
42
+ describe '#able_to_impersonate?' do
43
+ subject(:able_to_impersonate) { service_instance.send(:able_to_impersonate?, user, user2) }
44
+
45
+ context 'having a super admin and any other user' do
46
+ let!(:user) do
47
+ user = FactoryGirl.create(:g5_authenticatable_user)
48
+ user.add_role(:super_admin)
49
+ user
50
+ end
51
+ let!(:user2) { FactoryGirl.create(:g5_authenticatable_user) }
52
+
53
+ it { expect(able_to_impersonate).to eq(true) }
54
+ end
55
+
56
+ context 'having an admin' do
57
+ let!(:user) do
58
+ user = FactoryGirl.create(:g5_authenticatable_user)
59
+ user.add_role(:admin)
60
+ user
61
+ end
62
+
63
+ context 'assuming a super admin' do
64
+ let!(:user2) do
65
+ user = FactoryGirl.create(:g5_authenticatable_user)
66
+ user.add_role(:super_admin)
67
+ user
68
+ end
69
+
70
+ it { expect(able_to_impersonate).to eq(false) }
71
+ end
72
+
73
+ context 'assuming another admin' do
74
+ let!(:user2) do
75
+ user = FactoryGirl.create(:g5_authenticatable_user)
76
+ user.add_role(:admin)
77
+ user
78
+ end
79
+
80
+ it { expect(able_to_impersonate).to eq(true) }
81
+ end
82
+
83
+ context 'assuming a regular user' do
84
+ let!(:user2) { FactoryGirl.create(:g5_authenticatable_user) }
85
+
86
+ it { expect(able_to_impersonate).to eq(true) }
87
+ end
88
+ end
89
+
90
+ context 'providing no user' do
91
+ it { expect(service_instance.send(:able_to_impersonate?, user, nil)).to eq(false) }
92
+
93
+ it { expect(service_instance.send(:able_to_impersonate?, nil, user)).to eq(false) }
94
+
95
+ it { expect(service_instance.send(:able_to_impersonate?, nil, nil)).to eq(false) }
96
+ end
97
+ end
98
+
99
+ describe '#user_by_uid' do
100
+ subject(:user_by_uid) { service_instance.send(:user_by_uid, uid) }
101
+
102
+ context 'having an existing uid' do
103
+ let(:uid) { user.uid }
104
+ it { expect(user_by_uid).to eq(user) }
105
+ end
106
+
107
+ context 'having a no existing uid' do
108
+ let(:uid) { 'some-random-text' }
109
+ it { expect(user_by_uid).to be_nil }
110
+ end
111
+ end
112
+ 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.7.3
4
+ version: 0.7.4.beta.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - maeve
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-30 00:00:00.000000000 Z
11
+ date: 2015-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: devise_g5_authenticatable
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.3
19
+ version: 0.2.4.beta
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.2.3
26
+ version: 0.2.4.beta
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: omniauth-g5
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -126,9 +126,11 @@ 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/services/g5_authenticatable/impersonate_sessionable.rb
129
130
  - app/views/g5_authenticatable/error/auth_error.html.erb
130
131
  - app/views/layouts/g5_authenticatable/application.html.erb
131
132
  - config/initializers/devise.rb
133
+ - config/initializers/impersonate_strategy.rb
132
134
  - config/initializers/rolify.rb
133
135
  - config/locales/devise.en.yml
134
136
  - config/routes.rb
@@ -242,6 +244,7 @@ files:
242
244
  - spec/requests/token_validation_spec.rb
243
245
  - spec/routing/auth_error_routing_spec.rb
244
246
  - spec/routing/sign_out_routing_spec.rb
247
+ - spec/services/g5_authenticatable/impersonate_sessionable_spec.rb
245
248
  - spec/spec_helper.rb
246
249
  - spec/support/devise.rb
247
250
  - spec/support/shared_contexts/rake.rb
@@ -263,9 +266,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
263
266
  version: '0'
264
267
  required_rubygems_version: !ruby/object:Gem::Requirement
265
268
  requirements:
266
- - - ">="
269
+ - - ">"
267
270
  - !ruby/object:Gem::Version
268
- version: '0'
271
+ version: 1.3.1
269
272
  requirements: []
270
273
  rubyforge_project:
271
274
  rubygems_version: 2.2.2
@@ -362,10 +365,10 @@ test_files:
362
365
  - spec/requests/token_validation_spec.rb
363
366
  - spec/routing/auth_error_routing_spec.rb
364
367
  - spec/routing/sign_out_routing_spec.rb
368
+ - spec/services/g5_authenticatable/impersonate_sessionable_spec.rb
365
369
  - spec/spec_helper.rb
366
370
  - spec/support/devise.rb
367
371
  - spec/support/shared_contexts/rake.rb
368
372
  - spec/support/shared_examples/super_admin_authorizer.rb
369
373
  - spec/support/token_validation.rb
370
374
  - spec/tasks/purge_users_spec.rb
371
- has_rdoc: