g5_authenticatable 0.7.3 → 0.7.4.beta.1

Sign up to get free protection for your applications and to get access to all the features.
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: