mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-09-15 13:02:05 +09:00
Close live Action Cable connections on sign out (#268)
Action Cable authorizes a Connection once at the WebSocket handshake and never re-checks it. Destroying the session record refuses future handshakes and HTTP requests bearing the cookie, but a socket opened before sign out keeps its handshake-time current_user and keeps authorizing new subscriptions and delivering frames as the signed-out user. Reset the user's remote connections when the session is terminated. Clients tear down and reconnect: the signed-out device carries a destroyed session and cleared cookie and is rejected at the fresh handshake, while the user's other devices with still-valid sessions reconnect and stay live. This reuses the existing reset_remote_connections primitive already used on membership removal, for the same reason. Run the disconnect last and best-effort, after the session record and cookie are already gone, so sign out completes even when the realtime service is unreachable.
This commit is contained in:
@@ -56,6 +56,30 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
|
||||
assert_nil Session.find_by(id: session.id)
|
||||
end
|
||||
|
||||
test "destroy closes the signed-out user's live connections" do
|
||||
sign_in :david
|
||||
|
||||
remote_connections = mock
|
||||
remote_connections.expects(:disconnect).with(reconnect: true)
|
||||
ActionCable.server.stubs(:remote_connections).returns(mock.tap { |m| m.expects(:where).with(current_user: users(:david)).returns(remote_connections) })
|
||||
|
||||
delete session_url
|
||||
|
||||
assert_redirected_to root_url
|
||||
end
|
||||
|
||||
test "destroy still signs out when the realtime service is unreachable" do
|
||||
sign_in :david
|
||||
session = users(:david).sessions.last
|
||||
ActionCable.server.stubs(:remote_connections).raises(RuntimeError.new("cable down"))
|
||||
|
||||
delete session_url
|
||||
|
||||
assert_redirected_to root_url
|
||||
assert_not cookies[:session_token].present?
|
||||
assert_nil Session.find_by(id: session.id)
|
||||
end
|
||||
|
||||
test "destroy removes the push subscription for the device" do
|
||||
sign_in :david
|
||||
|
||||
|
||||
Reference in New Issue
Block a user