-
Notifications
You must be signed in to change notification settings - Fork 5.5k
/
Copy pathauthenticatable_test.rb
714 lines (580 loc) · 21.2 KB
/
authenticatable_test.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
# frozen_string_literal: true
require 'test_helper'
class AuthenticationSanityTest < Devise::IntegrationTest
test 'sign in should not run model validations' do
sign_in_as_user
assert_not User.validations_performed
end
test 'home should be accessible without sign in' do
visit '/'
assert_response :success
assert_template 'home/index'
end
test 'sign in as user should not authenticate admin scope' do
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
end
test 'sign in as admin should not authenticate user scope' do
sign_in_as_admin
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
end
test 'sign in as both user and admin at same time' do
sign_in_as_user
sign_in_as_admin
assert warden.authenticated?(:user)
assert warden.authenticated?(:admin)
end
test 'sign out as user should not touch admin authentication if sign_out_all_scopes is false' do
swap Devise, sign_out_all_scopes: false do
sign_in_as_user
sign_in_as_admin
delete destroy_user_session_path
assert_not warden.authenticated?(:user)
assert warden.authenticated?(:admin)
end
end
test 'sign out as admin should not touch user authentication if sign_out_all_scopes is false' do
swap Devise, sign_out_all_scopes: false do
sign_in_as_user
sign_in_as_admin
delete destroy_admin_session_path
assert_not warden.authenticated?(:admin)
assert warden.authenticated?(:user)
end
end
test 'sign out as user should also sign out admin if sign_out_all_scopes is true' do
swap Devise, sign_out_all_scopes: true do
sign_in_as_user
sign_in_as_admin
delete destroy_user_session_path
assert_not warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
end
end
test 'sign out as admin should also sign out user if sign_out_all_scopes is true' do
swap Devise, sign_out_all_scopes: true do
sign_in_as_user
sign_in_as_admin
delete destroy_admin_session_path
assert_not warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
end
end
test 'not signed in as admin should not be able to access admins actions' do
get admins_path
assert_redirected_to new_admin_session_path
assert_not warden.authenticated?(:admin)
end
test 'signed in as user should not be able to access admins actions' do
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
get admins_path
assert_redirected_to new_admin_session_path
end
test 'signed in as admin should be able to access admin actions' do
sign_in_as_admin
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get admins_path
assert_response :success
assert_template 'admins/index'
assert_contain 'Welcome Admin'
end
test 'authenticated admin should not be able to sign as admin again' do
sign_in_as_admin
get new_admin_session_path
assert_response :redirect
assert_redirected_to admin_root_path
assert warden.authenticated?(:admin)
end
test 'authenticated admin should be able to sign out' do
sign_in_as_admin
assert warden.authenticated?(:admin)
delete destroy_admin_session_path
assert_response :redirect
assert_redirected_to root_path
get root_path
assert_contain 'Signed out successfully'
assert_not warden.authenticated?(:admin)
end
test 'unauthenticated admin set message on sign out' do
delete destroy_admin_session_path
assert_response :redirect
assert_redirected_to root_path
get root_path
assert_contain 'Signed out successfully'
end
test 'scope uses custom failure app' do
put "/en/accounts/management"
assert_equal "Oops, not found", response.body
assert_equal 404, response.status
end
end
class AuthenticationRoutesRestrictions < Devise::IntegrationTest
test 'not signed in should not be able to access private route (authenticate denied)' do
get private_path
assert_redirected_to new_admin_session_path
assert_not warden.authenticated?(:admin)
end
test 'signed in as user should not be able to access private route restricted to admins (authenticate denied)' do
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
get private_path
assert_redirected_to new_admin_session_path
end
test 'signed in as admin should be able to access private route restricted to admins (authenticate accepted)' do
sign_in_as_admin
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get private_path
assert_response :success
assert_template 'home/private'
assert_contain 'Private!'
end
test 'signed in as inactive admin should not be able to access private/active route restricted to active admins (authenticate denied)' do
sign_in_as_admin(active: false)
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
assert_raises ActionController::RoutingError do
get "/private/active"
end
end
test 'signed in as active admin should be able to access private/active route restricted to active admins (authenticate accepted)' do
sign_in_as_admin(active: true)
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get private_active_path
assert_response :success
assert_template 'home/private'
assert_contain 'Private!'
end
test 'signed in as admin should get admin dashboard (authenticated accepted)' do
sign_in_as_admin
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get dashboard_path
assert_response :success
assert_template 'home/admin_dashboard'
assert_contain 'Admin dashboard'
end
test 'signed in as user should get user dashboard (authenticated accepted)' do
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
get dashboard_path
assert_response :success
assert_template 'home/user_dashboard'
assert_contain 'User dashboard'
end
test 'not signed in should get no dashboard (authenticated denied)' do
assert_raises ActionController::RoutingError do
get dashboard_path
end
end
test 'signed in as inactive admin should not be able to access dashboard/active route restricted to active admins (authenticated denied)' do
sign_in_as_admin(active: false)
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
assert_raises ActionController::RoutingError do
get "/dashboard/active"
end
end
test 'signed in as active admin should be able to access dashboard/active route restricted to active admins (authenticated accepted)' do
sign_in_as_admin(active: true)
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get dashboard_active_path
assert_response :success
assert_template 'home/admin_dashboard'
assert_contain 'Admin dashboard'
end
test 'signed in user should not see unauthenticated page (unauthenticated denied)' do
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
assert_raises ActionController::RoutingError do
get join_path
end
end
test 'not signed in users should see unauthenticated page (unauthenticated accepted)' do
get join_path
assert_response :success
assert_template 'home/join'
assert_contain 'Join'
end
end
class AuthenticationRedirectTest < Devise::IntegrationTest
test 'redirect from warden shows sign in or sign up message' do
get admins_path
warden_path = new_admin_session_path
assert_redirected_to warden_path
get warden_path
assert_contain 'You need to sign in or sign up before continuing.'
end
test 'redirect from warden respects i18n locale set at the controller' do
get admins_path(locale: "pt-BR")
assert_redirected_to new_admin_session_path
follow_redirect!
assert_contain 'Para continuar, faça login ou registre-se.'
end
test 'redirect to default url if no other was configured' do
sign_in_as_user
assert_template 'home/index'
assert_nil session[:"user_return_to"]
end
test 'redirect to requested url after sign in' do
get users_path
assert_redirected_to new_user_session_path
assert_equal users_path, session[:"user_return_to"]
follow_redirect!
sign_in_as_user visit: false
assert_current_url '/users'
assert_nil session[:"user_return_to"]
end
test 'redirect to last requested url overwriting the stored return_to option' do
get expire_user_path(create_user)
assert_redirected_to new_user_session_path
assert_equal expire_user_path(create_user), session[:"user_return_to"]
get users_path
assert_redirected_to new_user_session_path
assert_equal users_path, session[:"user_return_to"]
follow_redirect!
sign_in_as_user visit: false
assert_current_url '/users'
assert_nil session[:"user_return_to"]
end
test 'xml http requests does not store urls for redirect' do
get users_path, headers: { 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest' }
assert_equal 401, response.status
assert_nil session[:"user_return_to"]
end
test 'redirect to configured home path for a given scope after sign in' do
sign_in_as_admin
assert_equal "/admin_area/home", @request.path
end
test 'require_no_authentication should set the already_authenticated flash message' do
sign_in_as_user
visit new_user_session_path
assert_equal I18n.t("devise.failure.already_authenticated"), flash[:alert]
end
test 'require_no_authentication should set the already_authenticated flash message as admin' do
store_translations en: {
devise: { failure: { admin: { already_authenticated: 'You are already signed in as admin.' } } }
} do
sign_in_as_admin
visit new_admin_session_path
assert_equal "You are already signed in as admin.", flash[:alert]
end
end
end
class AuthenticationSessionTest < Devise::IntegrationTest
test 'destroyed account is signed out' do
sign_in_as_user
get '/users'
User.destroy_all
get '/users'
assert_redirected_to new_user_session_path
end
test 'refreshes _csrf_token' do
swap ApplicationController, allow_forgery_protection: true do
get new_user_session_path
token_from_session = request.session[:_csrf_token]
if Devise::Test.rails71_and_up?
token_from_env = request.env["action_controller.csrf_token"]
end
sign_in_as_user
assert_not_equal request.session[:_csrf_token], token_from_session
if Devise::Test.rails71_and_up?
assert_not_equal request.env["action_controller.csrf_token"], token_from_env
end
end
end
test 'allows session to be set for a given scope' do
sign_in_as_user
get '/users'
assert_equal "Cart", @controller.user_session[:cart]
end
test 'session id is changed on sign in' do
get '/users'
session_id = request.session["session_id"]
get '/users'
assert_equal session_id, request.session["session_id"]
sign_in_as_user
assert_not_equal session_id, request.session["session_id"]
end
end
class AuthenticationWithScopedViewsTest < Devise::IntegrationTest
test 'renders the scoped view if turned on and view is available' do
swap Devise, scoped_views: true do
assert_raise Webrat::NotFoundError do
sign_in_as_user
end
assert_match %r{Special user view}, response.body
end
end
test 'renders the scoped view if turned on in a specific controller' do
begin
Devise::SessionsController.scoped_views = true
assert_raise Webrat::NotFoundError do
sign_in_as_user
end
assert_match %r{Special user view}, response.body
assert_not Devise::PasswordsController.scoped_views?
ensure
Devise::SessionsController.send :remove_instance_variable, :@scoped_views
end
end
test 'does not render the scoped view if turned off' do
swap Devise, scoped_views: false do
assert_nothing_raised do
sign_in_as_user
end
end
end
test 'does not render the scoped view if not available' do
swap Devise, scoped_views: true do
assert_nothing_raised do
sign_in_as_admin
end
end
end
end
class AuthenticationOthersTest < Devise::IntegrationTest
test 'handles unverified requests gets rid of caches' do
swap ApplicationController, allow_forgery_protection: true do
post exhibit_user_url(1)
assert_not warden.authenticated?(:user)
sign_in_as_user
assert warden.authenticated?(:user)
post exhibit_user_url(1)
assert_not warden.authenticated?(:user)
assert_equal "User is not authenticated", response.body
end
end
test 'uses the custom controller with the custom controller view' do
get '/admin_area/sign_in'
assert_contain 'Log in'
assert_contain 'Welcome to "admins/sessions" controller!'
assert_contain 'Welcome to "sessions/new" view!'
end
test 'render 404 on roles without routes' do
assert_raise ActionController::RoutingError do
get '/admin_area/password/new'
end
end
test 'does not intercept Rails 401 responses' do
get '/unauthenticated'
assert_equal 401, response.status
end
test 'render 404 on roles without mapping' do
assert_raise AbstractController::ActionNotFound do
get '/sign_in'
end
end
test 'sign in with script name' do
assert_nothing_raised do
get new_user_session_path, headers: { "SCRIPT_NAME" => "/omg" }
fill_in "email", with: "[email protected]"
end
end
test 'sign in stub in json format' do
get new_user_session_path(format: 'json')
assert_match '{"user":{', response.body
assert_match '"email":""', response.body
assert_match '"password":null', response.body
end
test 'sign in stub in json with non attribute key' do
swap Devise, authentication_keys: [:other_key] do
get new_user_session_path(format: 'json')
assert_match '{"user":{', response.body
assert_match '"other_key":null', response.body
assert_match '"password":null', response.body
end
end
test 'uses the mapping from router' do
sign_in_as_user visit: "/as/sign_in"
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
end
test 'sign in with json format returns json response' do
create_user
post user_session_path(format: 'json'), params: { user: {email: "[email protected]", password: '12345678'} }
assert_response :success
assert_includes response.body, '{"user":{'
end
test 'sign in with json format is idempotent' do
get new_user_session_path(format: 'json')
assert_response :success
create_user
post user_session_path(format: 'json'), params: { user: {email: "[email protected]", password: '12345678'} }
assert_response :success
get new_user_session_path(format: 'json')
assert_response :success
post user_session_path(format: 'json'), params: { user: {email: "[email protected]", password: '12345678'} }
assert_response :success
assert_includes response.body, '{"user":{'
end
test 'sign out with html redirects' do
sign_in_as_user
delete destroy_user_session_path
assert_response :redirect
assert_current_url '/'
sign_in_as_user
delete destroy_user_session_path(format: 'html')
assert_response :redirect
assert_current_url '/'
end
test 'sign out with json format returns no content' do
sign_in_as_user
delete destroy_user_session_path(format: 'json')
assert_response :no_content
assert_not warden.authenticated?(:user)
end
test 'sign out with non-navigational format via XHR does not redirect' do
swap Devise, navigational_formats: ['*/*', :html] do
sign_in_as_admin
get destroy_sign_out_via_get_session_path, xhr: true, headers: { "HTTP_ACCEPT" => "application/json,text/javascript,*/*" } # NOTE: Bug is triggered by combination of XHR and */*.
assert_response :no_content
assert_not warden.authenticated?(:user)
end
end
# Belt and braces ... Perhaps this test is not necessary?
test 'sign out with navigational format via XHR does redirect' do
swap Devise, navigational_formats: ['*/*', :html] do
sign_in_as_user
delete destroy_user_session_path, xhr: true, headers: { "HTTP_ACCEPT" => "text/html,*/*" }
assert_response :redirect
assert_not warden.authenticated?(:user)
end
end
end
class AuthenticationKeysTest < Devise::IntegrationTest
test 'missing authentication keys cause authentication to abort' do
swap Devise, authentication_keys: [:subdomain] do
sign_in_as_user
assert_contain "Invalid Subdomain or password."
assert_not warden.authenticated?(:user)
end
end
test 'missing authentication keys cause authentication to abort unless marked as not required' do
swap Devise, authentication_keys: { email: true, subdomain: false } do
sign_in_as_user
assert warden.authenticated?(:user)
end
end
end
class AuthenticationRequestKeysTest < Devise::IntegrationTest
test 'request keys are used on authentication' do
host! 'foo.bar.baz'
swap Devise, request_keys: [:subdomain] do
User.expects(:find_for_authentication).with({ subdomain: 'foo', email: '[email protected]' }).returns(create_user)
sign_in_as_user
assert warden.authenticated?(:user)
end
end
test 'invalid request keys raises NoMethodError' do
swap Devise, request_keys: [:unknown_method] do
assert_raise NoMethodError do
sign_in_as_user
end
assert_not warden.authenticated?(:user)
end
end
test 'blank request keys cause authentication to abort' do
host! 'test.com'
swap Devise, request_keys: [:subdomain] do
sign_in_as_user
assert_contain "Invalid Email or password."
assert_not warden.authenticated?(:user)
end
end
test 'blank request keys cause authentication to abort unless if marked as not required' do
host! 'test.com'
swap Devise, request_keys: { subdomain: false } do
sign_in_as_user
assert warden.authenticated?(:user)
end
end
end
class AuthenticationSignOutViaTest < Devise::IntegrationTest
def sign_in!(scope)
sign_in_as_admin(visit: send("new_#{scope}_session_path"))
assert warden.authenticated?(scope)
end
test 'allow sign out via delete when sign_out_via provides only delete' do
sign_in!(:sign_out_via_delete)
delete destroy_sign_out_via_delete_session_path
assert_not warden.authenticated?(:sign_out_via_delete)
end
test 'do not allow sign out via get when sign_out_via provides only delete' do
sign_in!(:sign_out_via_delete)
assert_raise ActionController::RoutingError do
get destroy_sign_out_via_delete_session_path
end
assert warden.authenticated?(:sign_out_via_delete)
end
test 'allow sign out via post when sign_out_via provides only post' do
sign_in!(:sign_out_via_post)
post destroy_sign_out_via_post_session_path
assert_not warden.authenticated?(:sign_out_via_post)
end
test 'do not allow sign out via get when sign_out_via provides only post' do
sign_in!(:sign_out_via_post)
assert_raise ActionController::RoutingError do
get destroy_sign_out_via_delete_session_path
end
assert warden.authenticated?(:sign_out_via_post)
end
test 'allow sign out via delete when sign_out_via provides delete and post' do
sign_in!(:sign_out_via_delete_or_post)
delete destroy_sign_out_via_delete_or_post_session_path
assert_not warden.authenticated?(:sign_out_via_delete_or_post)
end
test 'allow sign out via post when sign_out_via provides delete and post' do
sign_in!(:sign_out_via_delete_or_post)
post destroy_sign_out_via_delete_or_post_session_path
assert_not warden.authenticated?(:sign_out_via_delete_or_post)
end
test 'do not allow sign out via get when sign_out_via provides delete and post' do
sign_in!(:sign_out_via_delete_or_post)
assert_raise ActionController::RoutingError do
get destroy_sign_out_via_delete_or_post_session_path
end
assert warden.authenticated?(:sign_out_via_delete_or_post)
end
end
class DoubleAuthenticationRedirectTest < Devise::IntegrationTest
test 'signed in as user redirects when visiting user sign in page' do
sign_in_as_user
get new_user_session_path(format: :html)
assert_redirected_to '/'
end
test 'signed in as admin redirects when visiting admin sign in page' do
sign_in_as_admin
get new_admin_session_path(format: :html)
assert_redirected_to '/admin_area/home'
end
test 'signed in as both user and admin redirects when visiting admin sign in page' do
sign_in_as_user
sign_in_as_admin
get new_user_session_path(format: :html)
assert_redirected_to '/'
get new_admin_session_path(format: :html)
assert_redirected_to '/admin_area/home'
end
end
class DoubleSignOutRedirectTest < Devise::IntegrationTest
test 'sign out after already having signed out redirects to sign in' do
sign_in_as_user
post destroy_sign_out_via_delete_or_post_session_path
get root_path
assert_contain 'Signed out successfully.'
post destroy_sign_out_via_delete_or_post_session_path
get root_path
assert_contain 'Signed out successfully.'
end
end