test: cover test_revoke_login_session_by_id_signs_out_only_that_device
This commit is contained in:
1 parent
a04596c925
commit
f0803046dd
1 file changed
+122
@@ -476,3 +476,125 @@ class AuthenticatableTest < Minitest::Test
|
||||
assert_equal 200, status_a
|
||||
end
|
||||
|
||||
def test_revoke_login_session_by_id_signs_out_only_that_device
|
||||
browser_a_remember = cookie_named(multi_sign_in, 'remember_session_token')
|
||||
browser_b_remember = cookie_named(multi_sign_in, 'remember_session_token')
|
||||
browser_b_id = AuthLoginSession.order(:id, :desc).first.id
|
||||
|
||||
status, _, body = call('POST', "/multi/revoke/#{browser_b_id}", cookies: browser_a_remember)
|
||||
assert_equal 200, status
|
||||
assert_equal 'revoked', body.join
|
||||
|
||||
status_b, = call('GET', '/multi/dashboard', cookies: browser_b_remember)
|
||||
assert_equal 302, status_b
|
||||
status_a, = call('GET', '/multi/dashboard', cookies: browser_a_remember)
|
||||
assert_equal 200, status_a
|
||||
end
|
||||
|
||||
def test_revoke_login_session_refuses_a_session_belonging_to_another_user
|
||||
AuthUser.create!(email: 'other@example.com', password: 'hunter2')
|
||||
other_login = AuthLoginSession.create!(user_id: AuthUser.find_by(email: 'other@example.com').id)
|
||||
browser_a_remember = cookie_named(multi_sign_in, 'remember_session_token')
|
||||
|
||||
status, _, body = call('POST', "/multi/revoke/#{other_login.id}", cookies: browser_a_remember)
|
||||
assert_equal 404, status
|
||||
assert_equal 'not found', body.join
|
||||
refute_nil AuthLoginSession.find_by(id: other_login.id)
|
||||
end
|
||||
|
||||
def test_revoking_the_current_login_session_signs_that_browser_out_too
|
||||
browser_a_remember = cookie_named(multi_sign_in, 'remember_session_token')
|
||||
current_id = AuthLoginSession.first.id
|
||||
|
||||
call('POST', "/multi/revoke/#{current_id}", cookies: browser_a_remember)
|
||||
|
||||
status, = call('GET', '/multi/dashboard', cookies: browser_a_remember)
|
||||
assert_equal 302, status
|
||||
end
|
||||
|
||||
def test_signing_in_without_remember_does_not_set_a_remember_session_cookie
|
||||
headers = multi_sign_in(remember: false)
|
||||
assert_nil cookie_named(headers, 'remember_session_token')
|
||||
assert_equal 0, AuthLoginSession.count
|
||||
end
|
||||
|
||||
def capped_sign_in
|
||||
_, headers, = call('POST', '/capped/sign_in',
|
||||
headers: { 'Content-Type' => 'application/x-www-form-urlencoded' },
|
||||
body: 'email=foksiu@example.com&password=hunter2')
|
||||
headers
|
||||
end
|
||||
|
||||
def test_max_remember_sessions_requires_remember_sessions
|
||||
error = assert_raises(ArgumentError) do
|
||||
Class.new(Prism::Controller) do
|
||||
include Prism::Authenticatable
|
||||
authenticate_with model: :AuthUser, max_remember_sessions: 2
|
||||
end
|
||||
end
|
||||
assert_match(/max_remember_sessions: requires remember_sessions:/, error.message)
|
||||
end
|
||||
|
||||
def test_under_the_limit_keeps_every_browser
|
||||
browser_a = cookie_named(capped_sign_in, 'remember_session_token')
|
||||
browser_b = cookie_named(capped_sign_in, 'remember_session_token')
|
||||
assert_equal 2, AuthLoginSession.count
|
||||
|
||||
status_a, = call('GET', '/capped/dashboard', cookies: browser_a)
|
||||
status_b, = call('GET', '/capped/dashboard', cookies: browser_b)
|
||||
assert_equal 200, status_a
|
||||
assert_equal 200, status_b
|
||||
end
|
||||
|
||||
def test_exceeding_the_limit_signs_out_the_oldest_browser_first
|
||||
browser_a = cookie_named(capped_sign_in, 'remember_session_token')
|
||||
browser_b = cookie_named(capped_sign_in, 'remember_session_token')
|
||||
browser_c = cookie_named(capped_sign_in, 'remember_session_token')
|
||||
|
||||
assert_equal 2, AuthLoginSession.count
|
||||
|
||||
status_a, = call('GET', '/capped/dashboard', cookies: browser_a)
|
||||
assert_equal 302, status_a, 'the oldest (first) browser should have been pruned'
|
||||
|
||||
status_b, = call('GET', '/capped/dashboard', cookies: browser_b)
|
||||
status_c, = call('GET', '/capped/dashboard', cookies: browser_c)
|
||||
assert_equal 200, status_b
|
||||
assert_equal 200, status_c
|
||||
end
|
||||
|
||||
def test_repeatedly_exceeding_the_limit_keeps_it_pinned_at_the_max
|
||||
5.times { capped_sign_in }
|
||||
assert_equal 2, AuthLoginSession.count
|
||||
end
|
||||
|
||||
def zero_capped_sign_in
|
||||
call('POST', '/zero-capped/sign_in',
|
||||
headers: { 'Content-Type' => 'application/x-www-form-urlencoded' },
|
||||
body: 'email=foksiu@example.com&password=hunter2')
|
||||
end
|
||||
|
||||
# `max_remember_sessions: 0` is a deliberately-set "never actually
|
||||
# remembered" limit (see the comment on prune_oldest_login_sessions) -
|
||||
# unlike every positive limit above, it must prune the row `sign_in`
|
||||
# itself just created, not just older ones.
|
||||
def test_max_remember_sessions_of_zero_prunes_the_row_it_just_created
|
||||
status, headers, = zero_capped_sign_in
|
||||
assert_equal 200, status
|
||||
assert_equal 0, AuthLoginSession.count,
|
||||
'a limit of 0 must prune the just-created row too, not only rows older than it'
|
||||
|
||||
session_cookie = session_cookie_from(headers)
|
||||
refute_nil session_cookie, 'sign_in always sets the plain session cookie regardless of the remember-row prune'
|
||||
status, = call('GET', '/zero-capped/dashboard', cookies: session_cookie)
|
||||
assert_equal 200, status, 'the session cookie set by this very sign_in must still authenticate the request'
|
||||
end
|
||||
|
||||
def test_max_remember_sessions_of_zero_makes_the_remember_cookie_dead_on_arrival
|
||||
_, headers, = zero_capped_sign_in
|
||||
remember_cookie = cookie_named(headers, 'remember_session_token')
|
||||
refute_nil remember_cookie, 'sign_in(remember: true) sets the cookie unconditionally, before the prune runs'
|
||||
|
||||
status, = call('GET', '/zero-capped/dashboard', cookies: remember_cookie)
|
||||
assert_equal 302, status, 'the remember cookie token matches no row once the limit-0 prune destroyed it'
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user