devise_g5_authenticatable 0.1.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.
Files changed (120) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +25 -0
  6. data/Gemfile +23 -0
  7. data/LICENSE +20 -0
  8. data/README.md +243 -0
  9. data/Rakefile +20 -0
  10. data/app/controllers/devise_g5_authenticatable/registrations_controller.rb +5 -0
  11. data/app/controllers/devise_g5_authenticatable/sessions_controller.rb +58 -0
  12. data/circle.yml +4 -0
  13. data/config/initializers/devise_g5_authenticatable.rb +3 -0
  14. data/config/locales/en.yml +6 -0
  15. data/devise_g5_authenticatable.gemspec +24 -0
  16. data/lib/devise_g5_authenticatable.rb +16 -0
  17. data/lib/devise_g5_authenticatable/controllers/helpers.rb +37 -0
  18. data/lib/devise_g5_authenticatable/controllers/url_helpers.rb +13 -0
  19. data/lib/devise_g5_authenticatable/engine.rb +11 -0
  20. data/lib/devise_g5_authenticatable/g5.rb +4 -0
  21. data/lib/devise_g5_authenticatable/g5/auth_password_validator.rb +30 -0
  22. data/lib/devise_g5_authenticatable/g5/auth_user_creator.rb +48 -0
  23. data/lib/devise_g5_authenticatable/g5/auth_user_updater.rb +43 -0
  24. data/lib/devise_g5_authenticatable/g5/user_exporter.rb +61 -0
  25. data/lib/devise_g5_authenticatable/models/g5_authenticatable.rb +99 -0
  26. data/lib/devise_g5_authenticatable/models/protected_attributes.rb +16 -0
  27. data/lib/devise_g5_authenticatable/omniauth.rb +9 -0
  28. data/lib/devise_g5_authenticatable/routes.rb +58 -0
  29. data/lib/devise_g5_authenticatable/version.rb +3 -0
  30. data/lib/tasks/g5/export_users.rake +13 -0
  31. data/spec/controllers/helpers_spec.rb +295 -0
  32. data/spec/controllers/sessions_controller_spec.rb +256 -0
  33. data/spec/controllers/url_helpers_spec.rb +332 -0
  34. data/spec/dummy/.gitignore +15 -0
  35. data/spec/dummy/README.rdoc +261 -0
  36. data/spec/dummy/Rakefile +7 -0
  37. data/spec/dummy/app/assets/images/rails.png +0 -0
  38. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  39. data/spec/dummy/app/assets/javascripts/custom_sessions.js +2 -0
  40. data/spec/dummy/app/assets/javascripts/home.js +2 -0
  41. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  42. data/spec/dummy/app/assets/stylesheets/custom_sessions.css +4 -0
  43. data/spec/dummy/app/assets/stylesheets/home.css +4 -0
  44. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  45. data/spec/dummy/app/controllers/custom_registrations_controllers.rb +2 -0
  46. data/spec/dummy/app/controllers/custom_sessions_controller.rb +2 -0
  47. data/spec/dummy/app/controllers/home_controller.rb +4 -0
  48. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  49. data/spec/dummy/app/helpers/custom_sessions_helper.rb +2 -0
  50. data/spec/dummy/app/helpers/home_helper.rb +2 -0
  51. data/spec/dummy/app/mailers/.gitkeep +0 -0
  52. data/spec/dummy/app/models/admin.rb +3 -0
  53. data/spec/dummy/app/models/user.rb +10 -0
  54. data/spec/dummy/app/views/anonymous/new.html.erb +0 -0
  55. data/spec/dummy/app/views/home/index.html.erb +1 -0
  56. data/spec/dummy/app/views/layouts/application.html.erb +16 -0
  57. data/spec/dummy/config.ru +4 -0
  58. data/spec/dummy/config/application.rb +64 -0
  59. data/spec/dummy/config/boot.rb +10 -0
  60. data/spec/dummy/config/database.yml.ci +6 -0
  61. data/spec/dummy/config/database.yml.sample +13 -0
  62. data/spec/dummy/config/environment.rb +5 -0
  63. data/spec/dummy/config/environments/development.rb +39 -0
  64. data/spec/dummy/config/environments/production.rb +67 -0
  65. data/spec/dummy/config/environments/test.rb +37 -0
  66. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  67. data/spec/dummy/config/initializers/devise.rb +259 -0
  68. data/spec/dummy/config/initializers/inflections.rb +15 -0
  69. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  70. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  71. data/spec/dummy/config/initializers/session_store.rb +8 -0
  72. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  73. data/spec/dummy/config/locales/devise.en.yml +60 -0
  74. data/spec/dummy/config/locales/en.yml +5 -0
  75. data/spec/dummy/config/routes.rb +70 -0
  76. data/spec/dummy/db/migrate/20131230235849_devise_create_users.rb +42 -0
  77. data/spec/dummy/db/migrate/20140102213131_drop_database_authenticatable.rb +16 -0
  78. data/spec/dummy/db/migrate/20140103032308_drop_recoverable.rb +16 -0
  79. data/spec/dummy/db/migrate/20140103042329_drop_rememberable.rb +13 -0
  80. data/spec/dummy/db/migrate/20140103174810_add_omniauth_columns_to_users.rb +18 -0
  81. data/spec/dummy/db/migrate/20140103191601_add_email_back_to_user.rb +8 -0
  82. data/spec/dummy/db/migrate/20140113202948_devise_create_admins.rb +42 -0
  83. data/spec/dummy/db/migrate/20140113233821_add_provider_and_uid_to_admins.rb +8 -0
  84. data/spec/dummy/db/schema.rb +50 -0
  85. data/spec/dummy/db/seeds.rb +7 -0
  86. data/spec/dummy/lib/assets/.gitkeep +0 -0
  87. data/spec/dummy/lib/tasks/.gitkeep +0 -0
  88. data/spec/dummy/log/.gitkeep +0 -0
  89. data/spec/dummy/public/404.html +26 -0
  90. data/spec/dummy/public/422.html +26 -0
  91. data/spec/dummy/public/500.html +25 -0
  92. data/spec/dummy/public/favicon.ico +0 -0
  93. data/spec/dummy/public/robots.txt +5 -0
  94. data/spec/dummy/script/rails +6 -0
  95. data/spec/dummy/vendor/assets/javascripts/.gitkeep +0 -0
  96. data/spec/dummy/vendor/assets/stylesheets/.gitkeep +0 -0
  97. data/spec/dummy/vendor/plugins/.gitkeep +0 -0
  98. data/spec/factories/admin.rb +10 -0
  99. data/spec/factories/user.rb +10 -0
  100. data/spec/features/edit_registration_spec.rb +109 -0
  101. data/spec/features/registration_spec.rb +99 -0
  102. data/spec/features/sign_in_spec.rb +91 -0
  103. data/spec/features/sign_out_spec.rb +7 -0
  104. data/spec/g5/auth_password_validator_spec.rb +81 -0
  105. data/spec/g5/auth_user_creator_spec.rb +100 -0
  106. data/spec/g5/auth_user_updater_spec.rb +113 -0
  107. data/spec/g5/user_exporter_spec.rb +105 -0
  108. data/spec/models/g5_authenticatable_spec.rb +540 -0
  109. data/spec/models/protected_attributes_spec.rb +17 -0
  110. data/spec/routing/registrations_routing_spec.rb +107 -0
  111. data/spec/routing/sessions_routing_spec.rb +111 -0
  112. data/spec/spec_helper.rb +44 -0
  113. data/spec/support/devise.rb +3 -0
  114. data/spec/support/omniauth.rb +3 -0
  115. data/spec/support/shared_contexts/oauth_error.rb +9 -0
  116. data/spec/support/shared_contexts/rake.rb +21 -0
  117. data/spec/support/shared_examples/registration_error.rb +15 -0
  118. data/spec/support/user_feature_methods.rb +26 -0
  119. data/spec/tasks/export_users_spec.rb +90 -0
  120. metadata +293 -0
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ describe Devise::G5::AuthUserCreator do
4
+ let(:creator) { described_class.new(model) }
5
+
6
+ describe '#create' do
7
+ subject(:create) { creator.create }
8
+
9
+ let(:model) do
10
+ build_stubbed(:user, password: password,
11
+ password_confirmation: password_confirmation,
12
+ updated_by: updated_by)
13
+ end
14
+
15
+ let(:updated_by) {}
16
+ let(:password) { 'new password' }
17
+ let(:password_confirmation) { 'new password confirmation' }
18
+
19
+ let(:auth_client) { double(:g5_authentication_client, create_user: auth_user) }
20
+ let(:auth_user) { double(:auth_user, id: uid, email: model.email) }
21
+ let(:uid) { 'remote-auth-user-42' }
22
+ before do
23
+ allow(G5AuthenticationClient::Client).to receive(:new).and_return(auth_client)
24
+ end
25
+
26
+ context 'when the new model has no uid' do
27
+ before { model.uid = nil }
28
+
29
+ context 'when updated by an existing user' do
30
+ let(:updated_by) { build_stubbed(:user) }
31
+
32
+ before { create }
33
+
34
+ it 'should use the token for updated_by user to call g5 auth' do
35
+ expect(G5AuthenticationClient::Client).to have_received(:new).
36
+ with(access_token: updated_by.g5_access_token)
37
+ end
38
+
39
+ it 'should create a new auth user with the correct email' do
40
+ expect(auth_client).to have_received(:create_user).
41
+ with(hash_including(email: model.email))
42
+ end
43
+
44
+ it 'should create a new auth user with the correct password' do
45
+ expect(auth_client).to have_received(:create_user).
46
+ with(hash_including(password: password))
47
+ end
48
+
49
+ it 'should create a new auth user with the correct password confirmation' do
50
+ expect(auth_client).to have_received(:create_user).
51
+ with(hash_including(password_confirmation: password_confirmation))
52
+ end
53
+
54
+ it 'should reset the password' do
55
+ expect(model.password).to be_nil
56
+ end
57
+
58
+ it 'should reset the password_confirmation' do
59
+ expect(model.password_confirmation).to be_nil
60
+ end
61
+ end
62
+
63
+ context 'when auth service returns an error' do
64
+ before do
65
+ allow(auth_client).to receive(:create_user).and_raise('Error!')
66
+ end
67
+
68
+ it 'should raise an exception' do
69
+ expect { create }.to raise_error('Error!')
70
+ end
71
+ end
72
+
73
+ context 'when not updated by an existing user' do
74
+ before { create }
75
+
76
+ it 'should use the user token to call g5 auth' do
77
+ expect(G5AuthenticationClient::Client).to have_received(:new).
78
+ with(access_token: model.g5_access_token)
79
+ end
80
+ end
81
+ end
82
+
83
+ context 'when new model already has a uid' do
84
+ before { model.uid = 'remote-user-42' }
85
+ before { create }
86
+
87
+ it 'should not create a user' do
88
+ expect(auth_client).to_not have_received(:create_user)
89
+ end
90
+
91
+ it 'should not reset the password' do
92
+ expect(model.password).to_not be_blank
93
+ end
94
+
95
+ it 'should not reset the password_confirmation' do
96
+ expect(model.password_confirmation).to_not be_blank
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ describe Devise::G5::AuthUserUpdater do
4
+ let(:updater) { described_class.new(model) }
5
+
6
+ let(:auth_client) { double(:g5_authentication_client, update_user: auth_user) }
7
+ let(:auth_user) { double(:auth_user, id: model.uid, email: model.email) }
8
+ before do
9
+ allow(G5AuthenticationClient::Client).to receive(:new).and_return(auth_client)
10
+ end
11
+
12
+ let(:model) { create(:user, updated_by: updated_by) }
13
+ let(:updated_by) {}
14
+
15
+ describe '#update' do
16
+ subject(:update) { updater.update }
17
+
18
+ context 'when email and password are unchanged' do
19
+ before { model.password = nil }
20
+ before { update }
21
+
22
+ it 'should not update the auth service' do
23
+ expect(auth_client).to_not have_received(:update_user)
24
+ end
25
+ end
26
+
27
+ context 'when email has changed' do
28
+ before { model.email = updated_email }
29
+ let(:updated_email) { 'updated.email@test.host' }
30
+
31
+
32
+ context 'when user has been updated by another user' do
33
+ let(:updated_by) { create(:user) }
34
+
35
+ context 'when auth user update is successful' do
36
+ before { update }
37
+
38
+ it 'should use the token for updated_by to call g5 auth' do
39
+ expect(G5AuthenticationClient::Client).to have_received(:new).
40
+ with(access_token: updated_by.g5_access_token)
41
+ end
42
+
43
+ it 'should update the email' do
44
+ expect(auth_client).to have_received(:update_user).
45
+ with(hash_including(email: updated_email))
46
+ end
47
+
48
+ it 'should reset the password' do
49
+ expect(model.password).to be_nil
50
+ end
51
+
52
+ it 'should reset the password confirmation' do
53
+ expect(model.password_confirmation).to be_nil
54
+ end
55
+
56
+ it 'should return the updated user' do
57
+ expect(update).to eq(auth_user)
58
+ end
59
+ end
60
+
61
+ context 'when auth service returns an error' do
62
+ before do
63
+ allow(auth_client).to receive(:update_user).and_raise('Error!')
64
+ end
65
+
66
+ it 'should raise an exception' do
67
+ expect { update }.to raise_error
68
+ end
69
+ end
70
+ end
71
+
72
+ context 'when user has not been updated by another user' do
73
+ before { update }
74
+
75
+ it 'should use the user token to call g5 auth' do
76
+ expect(G5AuthenticationClient::Client).to have_received(:new).
77
+ with(access_token: model.g5_access_token)
78
+ end
79
+ end
80
+ end
81
+
82
+ context 'when password is set' do
83
+ before do
84
+ model.password = updated_password
85
+ model.password_confirmation = updated_password_confirmation
86
+ end
87
+
88
+ let(:updated_password) { 'my_new_secret' }
89
+ let(:updated_password_confirmation) { 'not a match' }
90
+
91
+ before { update }
92
+
93
+ it 'should update the password' do
94
+ expect(auth_client).to have_received(:update_user).
95
+ with(hash_including(password: updated_password))
96
+ update
97
+ end
98
+
99
+ it 'should update the password_confirmation' do
100
+ expect(auth_client).to have_received(:update_user).
101
+ with(hash_including(password_confirmation: updated_password_confirmation))
102
+ end
103
+
104
+ it 'should reset the password' do
105
+ expect(model.password).to be_nil
106
+ end
107
+
108
+ it 'should reset the password confirmation' do
109
+ expect(model.password_confirmation).to be_nil
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ describe G5::UserExporter do
4
+ let(:exporter) { G5::UserExporter.new(options) }
5
+
6
+ let(:options) do
7
+ {client_id: 'my_client_id',
8
+ client_secret: 'soopersekrit',
9
+ redirect_uri: 'https://app.host/my/callback',
10
+ endpoint: 'https://auth.host',
11
+ authorization_code: 'abc123'}
12
+ end
13
+
14
+ describe '#export' do
15
+ subject(:export) { exporter.export }
16
+
17
+ let(:uid) { 'abc123yabbadabbadoo' }
18
+ let(:email) { 'fred@flintstone.com' }
19
+ let(:encrypted_password) { 'asdfklja;jtiohtsdgnmesmdnfsmdnfweurth34t' }
20
+
21
+ let(:local_user) do
22
+ double(:local_user, :id => 42,
23
+ :email => email,
24
+ :encrypted_password => encrypted_password,
25
+ :uid= => nil,
26
+ :provider= => nil,
27
+ :save => true)
28
+ end
29
+ before { allow(User).to receive(:all).and_return([local_user]) }
30
+
31
+ let(:auth_user) { double(:auth_user, id: uid, email: email) }
32
+ let(:auth_client) { double(:auth_client, create_user: auth_user) }
33
+ before do
34
+ allow(G5AuthenticationClient::Client).to receive(:new).and_return(auth_client)
35
+ end
36
+
37
+ it 'should initialize the auth client with the correct client_id' do
38
+ expect(G5AuthenticationClient::Client).to receive(:new).
39
+ with(hash_including(client_id: options[:client_id])).
40
+ and_return(auth_client)
41
+ export
42
+ end
43
+
44
+ it 'should initialize the auth client with the correct client_secret' do
45
+ expect(G5AuthenticationClient::Client).to receive(:new).
46
+ with(hash_including(client_secret: options[:client_secret])).
47
+ and_return(auth_client)
48
+ export
49
+ end
50
+
51
+ it 'should initialize the auth client with the correct redirect_uri' do
52
+ expect(G5AuthenticationClient::Client).to receive(:new).
53
+ with(hash_including(redirect_uri: options[:redirect_uri])).
54
+ and_return(auth_client)
55
+ export
56
+ end
57
+
58
+ it 'should initialize the auth client with the correct endpoint' do
59
+ expect(G5AuthenticationClient::Client).to receive(:new).
60
+ with(hash_including(endpoint: options[:endpoint])).
61
+ and_return(auth_client)
62
+ export
63
+ end
64
+
65
+ it 'should initialize the auth client with the correct authorization code' do
66
+ expect(G5AuthenticationClient::Client).to receive(:new).
67
+ with(hash_including(authorization_code: options[:authorization_code])).
68
+ and_return(auth_client)
69
+ export
70
+ end
71
+
72
+ it 'should create the auth user with the correct email' do
73
+ expect(auth_client).to receive(:create_user).
74
+ with(hash_including(email: email)).
75
+ and_return(auth_user)
76
+ export
77
+ end
78
+
79
+ it 'should create the auth user with the correct default password' do
80
+ expect(auth_client).to receive(:create_user).
81
+ with(hash_including(password: encrypted_password)).
82
+ and_return(auth_user)
83
+ export
84
+ end
85
+
86
+ it 'should set the uid on the local user' do
87
+ expect(local_user).to receive(:uid=).with(uid)
88
+ export
89
+ end
90
+
91
+ it 'should set the provider on the local user' do
92
+ expect(local_user).to receive(:provider=).with('g5')
93
+ export
94
+ end
95
+
96
+ it 'should save the local user' do
97
+ expect(local_user).to receive(:save).and_return(true)
98
+ export
99
+ end
100
+
101
+ it 'should return the SQL update statement with the encrypted password' do
102
+ expect(export).to match(/update users set encrypted_password='#{encrypted_password}' where id=#{uid};/i)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,540 @@
1
+ require 'spec_helper'
2
+
3
+ describe Devise::Models::G5Authenticatable do
4
+ subject { model }
5
+
6
+ let(:model_class) { User }
7
+ let(:model) { model_class.new(attributes) }
8
+ let(:attributes) { Hash.new }
9
+
10
+
11
+ describe '#save!' do
12
+ subject(:save) { model.save! }
13
+
14
+ context 'when model is new' do
15
+ let(:attributes) do
16
+ {email: email,
17
+ password: password,
18
+ password_confirmation: password_confirmation,
19
+ provider: provider,
20
+ uid: uid,
21
+ current_password: current_password,
22
+ updated_by: updated_by}
23
+ end
24
+
25
+ let(:email) { 'test.email@test.host' }
26
+ let(:password) { 'my_secret' }
27
+ let(:password_confirmation) { password }
28
+ let(:current_password) { 'my_current_password' }
29
+ let(:provider) {}
30
+ let(:uid) {}
31
+ let(:updated_by) { model_class.new }
32
+
33
+ let(:auth_user_creator) { double(:auth_user_creator, create: auth_user) }
34
+ let(:auth_user) { double(:auth_user, id: auth_id) }
35
+ let(:auth_id) { 1 }
36
+
37
+ before do
38
+ allow(Devise::G5::AuthUserCreator).to receive(:new).and_return(auth_user_creator)
39
+ end
40
+
41
+ context 'when model is valid' do
42
+ before { save }
43
+
44
+ it 'should persist the email' do
45
+ expect(model_class.find(model.id).email).to eq(email)
46
+ end
47
+
48
+ it 'should not persist the password' do
49
+ expect(model_class.find(model.id).password).to be_nil
50
+ end
51
+
52
+ it 'should not persist the password_confirmation' do
53
+ expect(model_class.find(model.id).password_confirmation).to be_nil
54
+ end
55
+
56
+ it 'should not persist the current_password' do
57
+ expect(model_class.find(model.id).current_password).to be_nil
58
+ end
59
+
60
+ it 'should not persist updated by' do
61
+ expect(model_class.find(model.id).updated_by).to be_nil
62
+ end
63
+
64
+ it 'should initialize a service class for creating auth users' do
65
+ expect(Devise::G5::AuthUserCreator).to have_received(:new).with(model)
66
+ end
67
+
68
+ it 'should create an auth user' do
69
+ expect(auth_user_creator).to have_received(:create)
70
+ end
71
+ end
72
+
73
+ context 'when uid is an integer' do
74
+ let(:uid) { 42 }
75
+
76
+ it 'should not raise an error' do
77
+ expect { save }.to_not raise_error
78
+ end
79
+ end
80
+
81
+ context 'when there is an error creating the auth user' do
82
+ before do
83
+ allow(auth_user_creator).to receive(:create).and_raise(error)
84
+ end
85
+
86
+ context 'with OAuth2::Error' do
87
+ let(:error) { OAuth2::Error.new(response) }
88
+ let(:response) do
89
+ double(:response, :parsed => error_hash,
90
+ :body => error_body,
91
+ :error= => nil)
92
+ end
93
+
94
+ let(:error_hash) do
95
+ { 'error' => error_code,
96
+ 'error_description' => error_description }
97
+ end
98
+
99
+ let(:error_code) { "Email can't be blank" }
100
+ let(:error_description) { 'Validation failed' }
101
+ let(:error_body) { 'problems' }
102
+
103
+ it 'should raise a RecordNotSaved error with the OAuth error code' do
104
+ expect { save }. to raise_error(ActiveRecord::RecordNotSaved, error_code)
105
+ end
106
+ end
107
+
108
+ context 'with some other error' do
109
+ let(:error) { StandardError.new(error_message) }
110
+ let(:error_message) { 'problems' }
111
+
112
+ it 'should raise a RecordNotSaved error' do
113
+ expect { save }.to raise_error(ActiveRecord::RecordNotSaved, error_message)
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ context 'when model is updated' do
120
+ let(:model) { create(:user) }
121
+
122
+ let(:auth_user_updater) { double(:user_updater, update: auth_user) }
123
+ let(:auth_user) { double(:auth_user, id: auth_id) }
124
+ let(:auth_id) { 'remote-auth-id-42' }
125
+ before do
126
+ allow(Devise::G5::AuthUserUpdater).to receive(:new).and_return(auth_user_updater)
127
+ end
128
+
129
+ context 'with successful auth user update' do
130
+ before { save }
131
+
132
+ it 'should initialize the auth user updater' do
133
+ expect(Devise::G5::AuthUserUpdater).to have_received(:new).with(model)
134
+ end
135
+
136
+ it 'should update the auth user' do
137
+ expect(auth_user_updater).to have_received(:update)
138
+ end
139
+ end
140
+
141
+ context 'with unsuccessful auth user update' do
142
+ before do
143
+ allow(auth_user_updater).to receive(:update).and_raise(error_message)
144
+ end
145
+ let(:error_message) { 'problems' }
146
+
147
+ it 'should raise an error' do
148
+ expect { save }.to raise_error
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ describe '#update_with_password' do
155
+ subject { update_with_password }
156
+ let(:update_with_password) { model.update_with_password(params) }
157
+
158
+ let(:model) { create(:user) }
159
+
160
+ let(:params) do
161
+ {current_password: current_password,
162
+ password: updated_password,
163
+ password_confirmation: updated_password,
164
+ email: updated_email}
165
+ end
166
+
167
+ let(:current_password) {}
168
+ let(:updated_password) { 'updated_secret' }
169
+ let(:updated_email) { 'update@email.com' }
170
+
171
+ let(:auth_updater) { double(:auth_user_updater, update: true) }
172
+ before { allow(Devise::G5::AuthUserUpdater).to receive(:new).and_return(auth_updater) }
173
+
174
+ let(:password_validator) { double(:auth_password_validator) }
175
+ before do
176
+ allow(Devise::G5::AuthPasswordValidator).to receive(:new).
177
+ and_return(password_validator)
178
+ end
179
+
180
+ context 'with valid current password' do
181
+ before { allow(password_validator).to receive(:valid_password?).and_return(true) }
182
+
183
+ before { update_with_password }
184
+
185
+ context 'with valid input' do
186
+ it 'should return true' do
187
+ expect(update_with_password).to be_true
188
+ end
189
+
190
+ it 'should initialize the auth user updater' do
191
+ expect(Devise::G5::AuthUserUpdater).to have_received(:new).with(model)
192
+ end
193
+
194
+ it 'should update the credentials in the auth server' do
195
+ expect(auth_updater).to have_received(:update)
196
+ end
197
+
198
+ it 'should update the email on the local model' do
199
+ expect(model.email).to eq(updated_email)
200
+ end
201
+ end
202
+
203
+ context 'when there is a validation error' do
204
+ let(:updated_email) { '' }
205
+
206
+ it 'should return false' do
207
+ expect(update_with_password).to be_false
208
+ end
209
+
210
+ it 'should not update the credentials on the auth server' do
211
+ expect(auth_updater).to_not have_received(:update)
212
+ end
213
+
214
+ it 'should add an error to the email attribute' do
215
+ expect(model.errors[:email].count).to eq(1)
216
+ end
217
+ end
218
+ end
219
+
220
+ context 'with invalid current password' do
221
+ before { allow(password_validator).to receive(:valid_password?).and_return(false) }
222
+
223
+ before { update_with_password }
224
+
225
+ context 'when current password is missing' do
226
+ let(:current_password) { '' }
227
+
228
+ it 'should return false' do
229
+ expect(update_with_password).to be_false
230
+ end
231
+
232
+ it 'should set an error on the current_password attribute' do
233
+ expect(model.errors[:current_password]).to include("can't be blank")
234
+ end
235
+
236
+ it 'should not update user credentials in the remote server' do
237
+ expect(auth_updater).to_not have_received(:update)
238
+ end
239
+ end
240
+
241
+ context 'when current password is incorrect' do
242
+ let(:current_password) { 'something wrong' }
243
+
244
+ it 'should return false' do
245
+ expect(update_with_password).to be_false
246
+ end
247
+
248
+ it 'should set an error on the current_password attribute' do
249
+ expect(model.errors[:current_password]).to include('is invalid')
250
+ end
251
+
252
+ it 'should not update user credentials in the remote server' do
253
+ expect(auth_updater).to_not have_received(:update)
254
+ end
255
+ end
256
+ end
257
+ end
258
+
259
+ describe '#clean_up_passwords' do
260
+ subject(:clean_up_passwords) { model.clean_up_passwords }
261
+ let(:model) do
262
+ build_stubbed(:user, password: password,
263
+ password_confirmation: password)
264
+ end
265
+
266
+ let(:password) { 'foobarbaz' }
267
+
268
+ it 'should change the password to nil' do
269
+ expect { clean_up_passwords }.to change { model.password }.
270
+ from(password).to(nil)
271
+ end
272
+
273
+ it 'should change the password_confirmation to nil' do
274
+ expect { clean_up_passwords }.to change { model.password_confirmation }.
275
+ from(password).to(nil)
276
+ end
277
+ end
278
+
279
+ describe '#valid_password?' do
280
+ subject(:valid_password?) { model.valid_password?(password) }
281
+
282
+ let(:model) { create(:user) }
283
+ let(:password) { 'foobarbaz' }
284
+
285
+ let(:password_validator) { double(:password_validator, valid_password?: valid) }
286
+ before do
287
+ allow(Devise::G5::AuthPasswordValidator).to receive(:new).and_return(password_validator)
288
+ end
289
+
290
+ before { valid_password? }
291
+
292
+ context 'when password is valid' do
293
+ let(:valid) { true }
294
+
295
+ it 'should return true' do
296
+ expect(valid_password?).to be_true
297
+ end
298
+
299
+ it 'should initialize the validator with the model' do
300
+ expect(Devise::G5::AuthPasswordValidator).to have_received(:new).with(model)
301
+ end
302
+
303
+ it 'should check the password against the auth server' do
304
+ expect(password_validator).to have_received(:valid_password?).with(password)
305
+ end
306
+ end
307
+
308
+ context 'when password is invalid' do
309
+ let(:valid) { false }
310
+
311
+ it 'should return false' do
312
+ expect(valid_password?).to be_false
313
+ end
314
+
315
+ it 'should initialize the validator with the model' do
316
+ expect(Devise::G5::AuthPasswordValidator).to have_received(:new).with(model)
317
+ end
318
+
319
+ it 'should check the password against the auth server' do
320
+ expect(password_validator).to have_received(:valid_password?).with(password)
321
+ end
322
+ end
323
+ end
324
+
325
+ describe '.find_and_update_for_g5_oauth' do
326
+ subject(:find_and_update) { model_class.find_and_update_for_g5_oauth(auth_data) }
327
+
328
+ let(:auth_data) do
329
+ OmniAuth::AuthHash.new({
330
+ provider: 'g5',
331
+ uid: '123999',
332
+ info: {name: 'Foo Bar',
333
+ email: 'foo@bar.com'},
334
+ credentials: {token: 'abc123'}
335
+ })
336
+ end
337
+
338
+ context 'when model exists' do
339
+ let!(:model) do
340
+ create(:user, provider: auth_data['provider'],
341
+ uid: auth_data['uid'],
342
+ g5_access_token: 'old_token')
343
+ end
344
+
345
+ it 'should return the model' do
346
+ expect(find_and_update).to eq(model)
347
+ end
348
+
349
+ it 'should save the updated g5_access_token' do
350
+ find_and_update
351
+ model.reload
352
+ expect(model.g5_access_token).to eq(auth_data.credentials.token)
353
+ end
354
+ end
355
+
356
+ context 'when model does not exist' do
357
+ it 'should return nothing' do
358
+ expect(find_and_update).to be_nil
359
+ end
360
+ end
361
+ end
362
+
363
+ describe '.find_for_g5_oauth' do
364
+ subject(:find_for_g5_oauth) { model_class.find_for_g5_oauth(auth_data) }
365
+
366
+ let(:auth_data) do
367
+ OmniAuth::AuthHash.new({
368
+ provider: 'g5',
369
+ uid: uid,
370
+ info: {name: 'Foo Bar',
371
+ email: 'foo@bar.com'},
372
+ credentials: {token: 'abc123'}
373
+ })
374
+ end
375
+
376
+ context 'when model exists' do
377
+ let!(:model) do
378
+ create(:user, provider: auth_data.provider,
379
+ uid: uid.to_s)
380
+ end
381
+
382
+ context 'when auth data uid is an integer' do
383
+ let(:uid) { 42 }
384
+
385
+ it 'should return the model' do
386
+ expect(find_for_g5_oauth).to eq(model)
387
+ end
388
+
389
+ it 'should not create any new models' do
390
+ expect { find_for_g5_oauth }.to_not change { model_class.count }
391
+ end
392
+ end
393
+
394
+ context 'when auth data uid is a string' do
395
+ let(:uid) { 'some/crazy/string1234#id' }
396
+
397
+ it 'should return the model' do
398
+ expect(find_for_g5_oauth).to eq(model)
399
+ end
400
+
401
+ it 'should not create any new models' do
402
+ expect { find_for_g5_oauth }.to_not change { model_class.count }
403
+ end
404
+ end
405
+ end
406
+
407
+ context 'when model does not exist' do
408
+ let(:uid) { '42' }
409
+
410
+ it 'should not return anything' do
411
+ expect(find_for_g5_oauth).to be_nil
412
+ end
413
+
414
+ it 'should not create any new models' do
415
+ expect { find_for_g5_oauth }.to_not change { model_class.count }
416
+ end
417
+ end
418
+ end
419
+
420
+ describe '#update_g5_credentials' do
421
+ subject(:update_g5_credentials) { model.update_g5_credentials(auth_data) }
422
+
423
+ let(:auth_data) do
424
+ OmniAuth::AuthHash.new({
425
+ provider: 'g5',
426
+ uid: '123999',
427
+ info: {name: 'Foo Bar',
428
+ email: 'foo@bar.com'},
429
+ credentials: {token: 'abc123'}
430
+ })
431
+ end
432
+
433
+ let(:model) do
434
+ create(:user, provider: auth_data['provider'],
435
+ uid: auth_data['uid'],
436
+ g5_access_token: 'old_token')
437
+ end
438
+
439
+ it 'should update the g5_access_token' do
440
+ expect { update_g5_credentials }.to change { model.g5_access_token }.to(auth_data.credentials.token)
441
+ end
442
+
443
+ it 'should not save the changes' do
444
+ update_g5_credentials
445
+ expect(model.g5_access_token_changed?).to be_true
446
+ end
447
+ end
448
+
449
+ describe '#revoke_g5_credentials!' do
450
+ subject(:revoke_g5_credentials!) { model.revoke_g5_credentials! }
451
+
452
+ let(:auth_updater) { double(:auth_user_updater, update: nil) }
453
+ before { allow(Devise::G5::AuthUserUpdater).to receive(:new).and_return(auth_updater) }
454
+
455
+ let(:model) { create(:user, g5_access_token: g5_token) }
456
+ before { model.password = model.password_confirmation = nil }
457
+
458
+ context 'when there is a g5 token' do
459
+ let(:g5_token) { 'my_g5_token' }
460
+
461
+ it 'should reset the g5 token' do
462
+ revoke_g5_credentials!
463
+ expect(model.g5_access_token).to be_nil
464
+ end
465
+
466
+ it 'should save the changes' do
467
+ revoke_g5_credentials!
468
+ expect { model.reload }.to_not change { model.g5_access_token }
469
+ end
470
+ end
471
+
472
+ context 'when there is no g5 token' do
473
+ let(:g5_token) {}
474
+
475
+ it 'should not set the g5 token' do
476
+ revoke_g5_credentials!
477
+ expect(model.g5_access_token).to be_nil
478
+ end
479
+ end
480
+ end
481
+
482
+ describe '#new_with_session' do
483
+ subject(:new_with_session) { model_class.new_with_session(params, session) }
484
+
485
+ let(:auth_data) do
486
+ OmniAuth::AuthHash.new({
487
+ provider: 'g5',
488
+ uid: '123999',
489
+ info: {name: 'Foo Bar',
490
+ email: 'foo@bar.com'},
491
+ credentials: {token: 'abc123'}
492
+ })
493
+ end
494
+
495
+ context 'with params' do
496
+ let(:params) { {'email' => email_param} }
497
+ let(:email_param) { 'my.email.param@test.host' }
498
+
499
+ context 'with session data' do
500
+ let(:session) { {'omniauth.auth' => auth_data} }
501
+
502
+ it { should be_new_record }
503
+ its(:email) { should == email_param }
504
+ its(:provider) { should == auth_data.provider }
505
+ its(:uid) { should == auth_data.uid }
506
+ end
507
+
508
+ context 'without session data' do
509
+ let(:session) { Hash.new }
510
+
511
+ it { should be_new_record }
512
+ its(:email) { should == email_param }
513
+ its(:provider) { should be_nil }
514
+ its(:uid) { should be_nil }
515
+ end
516
+ end
517
+
518
+ context 'without params' do
519
+ let(:params) { Hash.new }
520
+
521
+ context 'with session data' do
522
+ let(:session) { {'omniauth.auth' => auth_data} }
523
+
524
+ it { should be_new_record }
525
+ its(:email) { should == auth_data.info[:email] }
526
+ its(:provider) { should == auth_data.provider }
527
+ its(:uid) { should == auth_data.uid }
528
+ end
529
+
530
+ context 'without session data' do
531
+ let(:session) { Hash.new }
532
+
533
+ it { should be_new_record }
534
+ its(:email) { should be_blank }
535
+ its(:provider) { should be_nil }
536
+ its(:uid) { should be_nil }
537
+ end
538
+ end
539
+ end
540
+ end