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,58 @@
1
+ module Devise
2
+ class Mapping
3
+ alias :original_initialize :initialize
4
+
5
+ def initialize(name, options)
6
+ set_default_g5_controllers(options)
7
+ original_initialize(name, options)
8
+ end
9
+
10
+ private
11
+ def set_default_g5_controllers(options)
12
+ options[:controllers] ||= {}
13
+ options[:controllers].reverse_merge!({
14
+ registrations: 'devise_g5_authenticatable/registrations',
15
+ sessions: 'devise_g5_authenticatable/sessions'
16
+ })
17
+ options
18
+ end
19
+ end
20
+ end
21
+
22
+ module ActionDispatch::Routing
23
+ class Mapper
24
+ protected
25
+ def devise_session(mapping, controllers)
26
+ set_omniauth_path_prefix(mapping)
27
+ build_session_routes(mapping, controllers)
28
+ build_g5_omniauth_routes(mapping, controllers)
29
+ end
30
+
31
+ def set_omniauth_path_prefix(mapping)
32
+ path_prefix = Devise.omniauth_path_prefix || "/#{mapping.fullpath}/auth".squeeze("/")
33
+ set_omniauth_path_prefix!(path_prefix) unless ::OmniAuth.config.path_prefix.present?
34
+ end
35
+
36
+ def build_session_routes(mapping, controllers)
37
+ resource :session, only: [], controller: controllers[:sessions], path: '' do
38
+ get :new, path: mapping.path_names[:sign_in], as: :new
39
+ post :create, path: mapping.path_names[:sign_in]
40
+ match :destroy, path: mapping.path_names[:sign_out], as: :destroy, via: mapping.sign_out_via
41
+ end
42
+ end
43
+
44
+ def build_g5_omniauth_routes(mapping, controllers)
45
+ match 'auth/g5',
46
+ controller: controllers[:sessions],
47
+ action: 'omniauth_passthru',
48
+ as: :g5_authorize,
49
+ via: [:get, :post]
50
+
51
+ match 'auth/g5/callback',
52
+ controller: controllers[:sessions],
53
+ action: 'create',
54
+ as: :g5_callback,
55
+ via: [:get, :post]
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module DeviseG5Authenticatable
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,13 @@
1
+ require 'devise_g5_authenticatable/g5/user_exporter'
2
+
3
+ namespace :g5 do
4
+ desc "Create an auth user for each row in users table and dump id/password for update in auth server"
5
+ task :export_users, [:authorization_code, :client_id, :client_secret, :redirect_uri, :endpoint] => :environment do |t, args|
6
+ args.with_defaults(client_id: ENV['G5_AUTH_CLIENT_ID'],
7
+ client_secret: ENV['G5_AUTH_CLIENT_SECRET'],
8
+ redirect_uri: ENV['G5_AUTH_REDIRECT_URI'],
9
+ endpoint: ENV['G5_AUTH_ENDPOINT'],
10
+ authorization_code: ENV['G5_AUTH_AUTHORIZATION_CODE'])
11
+ puts G5::UserExporter.new(args).export
12
+ end
13
+ end
@@ -0,0 +1,295 @@
1
+ require 'spec_helper'
2
+
3
+ describe DeviseG5Authenticatable::Helpers do
4
+ controller(ActionController::Base) do
5
+ include Devise::Controllers::Helpers
6
+ include DeviseG5Authenticatable::Helpers
7
+ end
8
+
9
+ describe '#clear_blank_passwords' do
10
+ subject(:clear_passwords) { get :index, password_params }
11
+ before { clear_passwords }
12
+
13
+ controller do
14
+ before_filter :clear_blank_passwords, only: :index
15
+
16
+ def index
17
+ render status: 200, text: 'Index'
18
+ end
19
+ end
20
+
21
+ context 'when password params are populated' do
22
+ let(:password_params) do
23
+ {
24
+ scope => {
25
+ password: password,
26
+ password_confirmation: password_confirmation,
27
+ current_password: current_password,
28
+ email: 'foo@test.host'
29
+ }
30
+ }
31
+ end
32
+
33
+ let(:scope) { :user }
34
+
35
+ let(:password) { 'some_secret' }
36
+ let(:password_confirmation) { 'some_other_secret' }
37
+ let(:current_password) { 'current_secret' }
38
+
39
+ context 'with user scope' do
40
+ let(:scope) { :user }
41
+
42
+ context 'with non-blank password params' do
43
+ it 'should not change the password param' do
44
+ expect(controller.params[:user][:password]).to eq(password)
45
+ end
46
+
47
+ it 'should not change the password_confirmation param' do
48
+ expect(controller.params[:user][:password_confirmation]).to eq(password_confirmation)
49
+ end
50
+
51
+ it 'should not change the current_password param' do
52
+ expect(controller.params[:user][:current_password]).to eq(current_password)
53
+ end
54
+
55
+ it 'should not change the non-password param' do
56
+ expect(controller.params[:user][:email]).to eq(password_params[:user][:email])
57
+ end
58
+ end
59
+
60
+ context 'when password is nil' do
61
+ let(:password) {}
62
+
63
+ it 'should set the password param to nil' do
64
+ expect(controller.params[:user][:password]).to be_nil
65
+ end
66
+
67
+ it 'should not change the password confirmation param' do
68
+ expect(controller.params[:user][:password_confirmation]).to eq(password_confirmation)
69
+ end
70
+
71
+ it 'should not change the current_password param' do
72
+ expect(controller.params[:user][:current_password]).to eq(current_password)
73
+ end
74
+ end
75
+
76
+ context 'when password is blank' do
77
+ let(:password) { ' ' }
78
+
79
+ it 'should set the password param to nil' do
80
+ expect(controller.params[:user][:password]).to be_nil
81
+ end
82
+
83
+ it 'should not change the password confirmation param' do
84
+ expect(controller.params[:user][:password_confirmation]).to eq(password_confirmation)
85
+ end
86
+
87
+ it 'should not change the current_password param' do
88
+ expect(controller.params[:user][:current_password]).to eq(current_password)
89
+ end
90
+ end
91
+
92
+ context 'when password confirmation is nil' do
93
+ let(:password_confirmation) {}
94
+
95
+ it 'should not change the password param' do
96
+ expect(controller.params[:user][:password]).to eq(password)
97
+ end
98
+
99
+ it 'should set the password_confirmation param to nil' do
100
+ expect(controller.params[:user][:password_confirmation]).to be_nil
101
+ end
102
+
103
+ it 'should not change the current_password param' do
104
+ expect(controller.params[:user][:current_password]).to eq(current_password)
105
+ end
106
+ end
107
+
108
+ context 'when password confirmation is blank' do
109
+ let(:password_confirmation) { ' ' }
110
+
111
+ it 'should not change the password param' do
112
+ expect(controller.params[:user][:password]).to eq(password)
113
+ end
114
+
115
+ it 'should set the password_confirmation param to nil' do
116
+ expect(controller.params[:user][:password_confirmation]).to be_nil
117
+ end
118
+
119
+ it 'should not change the current_password param' do
120
+ expect(controller.params[:user][:current_password]).to eq(current_password)
121
+ end
122
+ end
123
+
124
+ context 'when current_password is nil' do
125
+ let(:current_password) {}
126
+
127
+ it 'should not change the password param' do
128
+ expect(controller.params[:user][:password]).to eq(password)
129
+ end
130
+
131
+ it 'should not change the password_confirmation param' do
132
+ expect(controller.params[:user][:password_confirmation]).to eq(password_confirmation)
133
+ end
134
+
135
+ it 'should set the current password param to nil' do
136
+ expect(controller.params[:user][:current_password]).to be_nil
137
+ end
138
+ end
139
+
140
+ context 'when current_password is blank' do
141
+ let(:current_password) { ' ' }
142
+
143
+ it 'should not change the password param' do
144
+ expect(controller.params[:user][:password]).to eq(password)
145
+ end
146
+
147
+ it 'should not change the password_confirmation param' do
148
+ expect(controller.params[:user][:password_confirmation]).to eq(password_confirmation)
149
+ end
150
+
151
+ it 'should set the current password param to nil' do
152
+ expect(controller.params[:user][:current_password]).to be_nil
153
+ end
154
+ end
155
+ end
156
+
157
+ context 'with admin scope' do
158
+ let(:scope) { :admin }
159
+
160
+ context 'when password is blank' do
161
+ let(:password) { ' ' }
162
+
163
+ it 'should set the admin password param to nil' do
164
+ expect(controller.params[:admin][:password]).to be_nil
165
+ end
166
+ end
167
+
168
+ context 'when password confirmation is blank' do
169
+ let(:password_confirmation) { ' ' }
170
+
171
+ it 'should set the admin password confirmation to nil' do
172
+ expect(controller.params[:admin][:password_confirmation]).to be_nil
173
+ end
174
+ end
175
+
176
+ context 'when current password is blank' do
177
+ let(:current_password) { ' ' }
178
+
179
+ it 'should set the admin current password param to nil' do
180
+ expect(controller.params[:admin][:current_password]).to be_nil
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ context 'when there are no password params' do
187
+ let(:password_params) { Hash.new }
188
+
189
+ it 'should not change any params' do
190
+ expect(controller.params[:user]).to be_nil
191
+ end
192
+ end
193
+ end
194
+
195
+ describe '#set_updated_by_user' do
196
+ subject(:set_updated_by_user) { post :create, user_params }
197
+
198
+ controller do
199
+ define_helpers(:user)
200
+ define_helpers(:admin)
201
+
202
+ before_filter :set_updated_by_user, only: :create
203
+
204
+ def create
205
+ render status: 200, text: 'Create'
206
+ end
207
+ end
208
+
209
+ before { sign_in :user, current_user }
210
+ let(:current_user) { create(:user) }
211
+
212
+ before { set_updated_by_user }
213
+
214
+ context 'when there is a user param' do
215
+ let(:user_params) { {user: attributes_for(:user)} }
216
+
217
+ it 'should set the user updated_by' do
218
+ expect(controller.params[:user][:updated_by]).to eq(current_user)
219
+ end
220
+ end
221
+
222
+ context 'when there is no user param' do
223
+ let(:user_params) { Hash.new }
224
+
225
+ it 'should set the updated_by' do
226
+ expect(controller.params[:updated_by]).to eq(current_user)
227
+ end
228
+ end
229
+ end
230
+
231
+ describe '#set_updated_by_admin' do
232
+ subject(:set_updated_by_admin) { post :create, admin_params }
233
+
234
+ controller do
235
+ define_helpers(:user)
236
+ define_helpers(:admin)
237
+
238
+ before_filter :set_updated_by_admin, only: :create
239
+
240
+ def create
241
+ render status: 200, text: 'Create'
242
+ end
243
+ end
244
+
245
+ before { sign_in :admin, current_admin }
246
+ let(:current_admin) { create(:admin) }
247
+
248
+ before { set_updated_by_admin }
249
+
250
+ context 'when there is an admin param' do
251
+ let(:admin_params) { {admin: attributes_for(:admin)} }
252
+
253
+ it 'should set the admin updated_by' do
254
+ expect(controller.params[:admin][:updated_by]).to eq(current_admin)
255
+ end
256
+ end
257
+
258
+ context 'when there is no admin param' do
259
+ let(:admin_params) { Hash.new }
260
+
261
+ it 'should set the updated_by' do
262
+ expect(controller.params[:updated_by]).to eq(current_admin)
263
+ end
264
+ end
265
+ end
266
+
267
+ describe '#handle_resource_error' do
268
+ subject(:action_with_error) { post :create }
269
+
270
+ before { request.env['devise.mapping'] = Devise.mappings[:user] }
271
+
272
+ controller(DeviseController) do
273
+ rescue_from ActiveRecord::RecordNotSaved, with: :handle_resource_error
274
+
275
+ def create
276
+ self.resource = resource_class.new
277
+ raise ActiveRecord::RecordNotSaved.new('my_error')
278
+ end
279
+ end
280
+
281
+ before { action_with_error }
282
+
283
+ it 'should be successful' do
284
+ expect(response).to be_success
285
+ end
286
+
287
+ it 'should set the base error on the resource' do
288
+ expect(controller.resource.errors[:base]).to eq(['my_error'])
289
+ end
290
+
291
+ it 'should render the model creation form' do
292
+ expect(response).to render_template('anonymous/new')
293
+ end
294
+ end
295
+ end
@@ -0,0 +1,256 @@
1
+ require 'spec_helper'
2
+
3
+ describe DeviseG5Authenticatable::SessionsController do
4
+ before { request.env['devise.mapping'] = Devise.mappings[scope] }
5
+ let(:scope) { :user }
6
+
7
+ describe '#new' do
8
+ subject(:new_session) { get :new }
9
+
10
+ context 'with user scope' do
11
+ it 'should redirect to the scoped authorize path' do
12
+ expect(new_session).to redirect_to(user_g5_authorize_path)
13
+ end
14
+ end
15
+
16
+ context 'with admin scope' do
17
+ let(:scope) { :admin }
18
+
19
+ it 'should redirect to the scoped authorize path' do
20
+ expect(new_session).to redirect_to(admin_g5_authorize_path)
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '#omniauth_passthru' do
26
+ subject(:passthru) { get :omniauth_passthru }
27
+
28
+ it 'should return a 404' do
29
+ expect(passthru).to be_not_found
30
+ end
31
+ end
32
+
33
+ describe '#create' do
34
+ subject(:create_session) { post :create }
35
+
36
+ let(:auth_hash) do
37
+ OmniAuth::AuthHash.new({
38
+ provider: 'g5',
39
+ uid: '45',
40
+ info: {name: 'Foo Bar',
41
+ email: 'foo@bar.com'},
42
+ credentials: {token: 'abc123'}
43
+ })
44
+ end
45
+ before { request.env['omniauth.auth'] = auth_hash }
46
+
47
+ context 'when local model exists' do
48
+ let(:model) do
49
+ stub_model(model_class, provider: auth_hash.provider,
50
+ uid: auth_hash.uid,
51
+ email: auth_hash.email,
52
+ g5_access_token: auth_hash.credentials.token,
53
+ save!: true,
54
+ update_g5_credentials: true,
55
+ email_changed?: false)
56
+ end
57
+ before { model_class.stub(find_and_update_for_g5_oauth: model) }
58
+
59
+ context 'with user scope' do
60
+ let(:model_class) { User }
61
+ let(:scope) { :user }
62
+
63
+ it 'should find the user and update the oauth credentials' do
64
+ User.should_receive(:find_and_update_for_g5_oauth).with(auth_hash).and_return(model)
65
+ create_session
66
+ end
67
+
68
+ it 'should set the flash message' do
69
+ create_session
70
+ expect(flash[:notice]).to eq('Signed in successfully.')
71
+ end
72
+
73
+ it 'should sign in the user' do
74
+ expect { create_session }.to change { controller.current_user }.from(nil).to(model)
75
+ end
76
+
77
+ it 'should redirect the user' do
78
+ create_session
79
+ expect(response).to be_a_redirect
80
+ end
81
+ end
82
+
83
+ context 'with admin scope' do
84
+ let(:model_class) { Admin }
85
+ let(:scope) { :admin }
86
+
87
+ it 'should find the admin and update the oauth credentials' do
88
+ Admin.should_receive(:find_and_update_for_g5_oauth).with(auth_hash).and_return(model)
89
+ create_session
90
+ end
91
+
92
+ it 'should sign in the admin' do
93
+ expect { create_session }.to change { controller.current_admin }.from(nil).to(model)
94
+ end
95
+ end
96
+ end
97
+
98
+ context 'when local model does not exist' do
99
+ before { model_class.stub(find_and_update_for_g5_oauth: nil) }
100
+
101
+ context 'with user scope' do
102
+ let(:scope) { :user }
103
+ let(:model_class) { User }
104
+
105
+ it 'should set the flash message' do
106
+ create_session
107
+ expect(flash[:alert]).to eq('You must sign up before continuing.')
108
+ end
109
+
110
+ it 'should not sign in a user' do
111
+ expect { create_session }.to_not change { controller.current_user }
112
+ end
113
+
114
+ it 'should redirect to the user registration path' do
115
+ expect(create_session).to redirect_to(new_user_registration_path)
116
+ end
117
+
118
+ it 'should set the auth data on the session' do
119
+ expect { create_session }.to change { session['omniauth.auth'] }.to(auth_hash)
120
+ end
121
+ end
122
+
123
+ context 'with admin scope' do
124
+ let(:scope) { :admin }
125
+ let(:model_class) { Admin }
126
+
127
+ it 'should redirect to the admin registration path' do
128
+ expect(create_session).to redirect_to(new_admin_registration_path)
129
+ end
130
+
131
+ it 'should set the auth data on the session' do
132
+ expect { create_session }.to change { session['omniauth.auth'] }.to(auth_hash)
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ describe '#destroy' do
139
+ subject(:destroy_session) { delete :destroy }
140
+
141
+ let(:auth_client) { double(:auth_client, sign_out_url: auth_sign_out_url) }
142
+ let(:auth_sign_out_url) { 'https://auth.test.host/sign_out?redirect_url=http%3A%2F%2Ftest.host%2F' }
143
+ before do
144
+ allow(G5AuthenticationClient::Client).to receive(:new).and_return(auth_client)
145
+ end
146
+
147
+ let(:model) { create(scope) }
148
+
149
+ before do
150
+ sign_in(scope, model)
151
+ allow(model).to receive(:revoke_g5_credentials!)
152
+ end
153
+
154
+ context 'with user scope' do
155
+ let(:scope) { :user }
156
+
157
+ it 'should sign out the user locally' do
158
+ expect { destroy_session }.to change { controller.current_user }.to(nil)
159
+ end
160
+
161
+ it 'should construct the sign out URL with the correct redirect URL' do
162
+ expect(auth_client).to receive(:sign_out_url).
163
+ with(root_url).
164
+ and_return(auth_sign_out_url)
165
+ destroy_session
166
+ end
167
+
168
+ it 'should redirect to the auth server to sign out globally' do
169
+ expect(destroy_session).to redirect_to(auth_sign_out_url)
170
+ end
171
+
172
+ it 'should revoke the g5 access token' do
173
+ expect(controller.current_user).to receive(:revoke_g5_credentials!)
174
+ destroy_session
175
+ end
176
+ end
177
+
178
+ context 'with admin scope' do
179
+ let(:scope) { :admin }
180
+
181
+ it 'should sign out the admin locally' do
182
+ expect { destroy_session }.to change { controller.current_admin }.to(nil)
183
+ end
184
+
185
+ it 'should revoke the g5 access token' do
186
+ expect(controller.current_admin).to receive(:revoke_g5_credentials!)
187
+ destroy_session
188
+ end
189
+ end
190
+ end
191
+
192
+ describe '#failure' do
193
+ subject(:failure) do
194
+ # We need some trickery here because the failure action is actually rack
195
+ # rather than rails
196
+ rack_response = described_class.action(:failure).call(request.env)
197
+ @response = ActionDispatch::TestResponse.from_response(rack_response.last)
198
+ end
199
+
200
+ before do
201
+ request.env['omniauth.error'] = error
202
+ request.env['omniauth.error.strategy'] = omniauth_strategy
203
+ end
204
+
205
+ let(:omniauth_strategy) { double(:omniauth_strategy, name: 'G5') }
206
+
207
+ context 'with error_reason' do
208
+ let(:error) { double(:error, error_reason: reason) }
209
+ let(:reason) { 'The error reason' }
210
+
211
+ it 'should set the flash message' do
212
+ failure
213
+ expect(flash[:alert]).to eq("Could not authenticate you from G5 because \"#{reason}\".")
214
+ end
215
+
216
+ it 'should be a redirect' do
217
+ failure
218
+ expect(response).to be_a_redirect
219
+ end
220
+
221
+ it 'should redirect to root path' do
222
+ failure
223
+ expect(response).to redirect_to(root_path)
224
+ end
225
+ end
226
+
227
+ context 'with error string' do
228
+ let(:error) { double(:error, error: message) }
229
+ let(:message) { 'The error string' }
230
+
231
+ it 'should set the flash message' do
232
+ failure
233
+ expect(flash[:alert]).to eq("Could not authenticate you from G5 because \"#{message}\".")
234
+ end
235
+
236
+ it 'should redirect to the root path' do
237
+ expect(failure).to redirect_to(root_path)
238
+ end
239
+ end
240
+
241
+ context 'with omniauth error type' do
242
+ before { request.env['omniauth.error.type'] = :invalid_credentials }
243
+ let(:humanized_type) { 'Invalid credentials' }
244
+ let(:error) { Object.new }
245
+
246
+ it 'should set the flash message' do
247
+ failure
248
+ expect(flash[:alert]).to eq("Could not authenticate you from G5 because \"#{humanized_type}\".")
249
+ end
250
+
251
+ it 'should redirect to the root path' do
252
+ expect(failure).to redirect_to(root_path)
253
+ end
254
+ end
255
+ end
256
+ end