parent
2f3824cecc
commit
f8b8082ee5
1 changed files with 18 additions and 53 deletions
|
|
@ -10,9 +10,6 @@ defmodule ToweropsWeb.Plugs.UpdateSessionActivity do
|
|||
each session was last active. The update happens in a background task to avoid
|
||||
slowing down requests.
|
||||
"""
|
||||
use Gettext, backend: ToweropsWeb.Gettext
|
||||
|
||||
import Phoenix.Controller, only: [put_flash: 3, redirect: 2]
|
||||
import Plug.Conn
|
||||
|
||||
alias Towerops.Accounts
|
||||
|
|
@ -28,48 +25,39 @@ defmodule ToweropsWeb.Plugs.UpdateSessionActivity do
|
|||
@doc """
|
||||
Updates the last_activity_at timestamp for the current browser session.
|
||||
|
||||
Checks for session inactivity timeout and logs out the user if the session
|
||||
has been inactive for more than 30 minutes.
|
||||
Checks for session inactivity timeout and revokes the token if the session
|
||||
has been inactive for more than 30 minutes. All database work runs in a
|
||||
background task so the request is not blocked.
|
||||
|
||||
When a timed-out session is detected, the token is deleted so the next
|
||||
request will be unauthenticated and redirected to login by the auth pipeline.
|
||||
|
||||
Looks up the session by the token stored in the session cookie, then
|
||||
updates the timestamp in a background task.
|
||||
"""
|
||||
def call(conn, _opts) do
|
||||
case get_session(conn, :user_token) do
|
||||
nil -> conn
|
||||
token -> handle_session_activity(conn, token)
|
||||
end
|
||||
end
|
||||
|
||||
# Handle session activity check and timeout
|
||||
defp handle_session_activity(conn, token) do
|
||||
case check_session_activity(token) do
|
||||
:active ->
|
||||
# Session is active, update timestamp in background
|
||||
Task.start(fn -> update_session_activity(token) end)
|
||||
nil ->
|
||||
conn
|
||||
|
||||
:timeout ->
|
||||
# Session timed out due to inactivity
|
||||
logout_inactive_session(conn, token)
|
||||
|
||||
:not_found ->
|
||||
# Session not found, continue normally
|
||||
token ->
|
||||
live_socket_id = get_session(conn, :live_socket_id)
|
||||
Task.start(fn -> handle_session_activity(token, live_socket_id) end)
|
||||
conn
|
||||
end
|
||||
end
|
||||
|
||||
# Check if session is still active or has timed out
|
||||
defp check_session_activity(token) do
|
||||
# Runs in a background task: check activity and either touch or revoke the session
|
||||
defp handle_session_activity(token, live_socket_id) do
|
||||
case Accounts.get_browser_session_by_token_value(token) do
|
||||
nil ->
|
||||
:not_found
|
||||
:ok
|
||||
|
||||
session ->
|
||||
if session_timed_out?(session) do
|
||||
:timeout
|
||||
revoke_inactive_session(token, live_socket_id)
|
||||
else
|
||||
:active
|
||||
Accounts.touch_browser_session(session)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -81,35 +69,12 @@ defmodule ToweropsWeb.Plugs.UpdateSessionActivity do
|
|||
inactive_seconds > @inactivity_timeout_seconds
|
||||
end
|
||||
|
||||
# Log out user due to inactivity timeout
|
||||
defp logout_inactive_session(conn, token) do
|
||||
# Delete the session token
|
||||
# Revoke the token so the next request will be unauthenticated
|
||||
defp revoke_inactive_session(token, live_socket_id) do
|
||||
Accounts.delete_user_session_token(token)
|
||||
|
||||
# Broadcast logout to LiveView socket
|
||||
if live_socket_id = get_session(conn, :live_socket_id) do
|
||||
if live_socket_id do
|
||||
ToweropsWeb.Endpoint.broadcast(live_socket_id, "disconnect", %{})
|
||||
end
|
||||
|
||||
# Clear session and redirect to login
|
||||
conn
|
||||
|> configure_session(renew: true)
|
||||
|> clear_session()
|
||||
|> delete_resp_cookie("_towerops_web_user_remember_me")
|
||||
|> put_flash(:info, gettext("Your session expired due to inactivity. Please log in again."))
|
||||
|> redirect(to: "/users/log-in")
|
||||
|> halt()
|
||||
end
|
||||
|
||||
defp update_session_activity(token) do
|
||||
case Accounts.get_browser_session_by_token_value(token) do
|
||||
nil ->
|
||||
# No browser session found (might be an old session from before this feature)
|
||||
:ok
|
||||
|
||||
session ->
|
||||
# Update activity timestamp
|
||||
Accounts.touch_browser_session(session)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue