oneshot
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
defmodule Rsh26poolWeb.Auth do
|
||||
@moduledoc """
|
||||
Token-based authentication.
|
||||
|
||||
When a user creates or joins a room we generate a random token, persist it on
|
||||
their `Participant` row, and store that token in the session cookie. On every
|
||||
request the token is looked up to identify the current participant. This is
|
||||
the token scheme described in the proposal (a random string whose owner is
|
||||
recorded in the database, kept in a cookie).
|
||||
"""
|
||||
use Rsh26poolWeb, :verified_routes
|
||||
|
||||
import Plug.Conn
|
||||
|
||||
alias Phoenix.LiveView
|
||||
alias Rsh26pool.Voting
|
||||
|
||||
@token_key "participant_token"
|
||||
|
||||
## Plug (controllers) ---------------------------------------------------
|
||||
|
||||
@doc "Assigns `:current_participant` from the session token (may be nil)."
|
||||
def fetch_current_participant(conn, _opts) do
|
||||
participant = participant_from_token(get_session(conn, @token_key))
|
||||
assign(conn, :current_participant, participant)
|
||||
end
|
||||
|
||||
@doc "Persists a participant's token in the session and assigns it."
|
||||
def log_in_participant(conn, participant) do
|
||||
conn
|
||||
|> put_session(@token_key, participant.token)
|
||||
|> assign(:current_participant, participant)
|
||||
end
|
||||
|
||||
@doc "Clears the session token (logout)."
|
||||
def log_out_participant(conn) do
|
||||
conn
|
||||
|> delete_session(@token_key)
|
||||
|> assign(:current_participant, nil)
|
||||
end
|
||||
|
||||
## LiveView on_mount hooks ---------------------------------------------
|
||||
|
||||
@doc """
|
||||
`on_mount` hooks:
|
||||
|
||||
* `:mount_current_participant` — assigns `:current_participant` (may be nil)
|
||||
* `:require_participant` — requires the viewer to belong to the room in the
|
||||
URL, otherwise redirects to the enter page
|
||||
* `:require_owner` — requires the viewer to be the owner of the room
|
||||
"""
|
||||
def on_mount(:mount_current_participant, _params, session, socket) do
|
||||
{:cont, assign_current_participant(socket, session)}
|
||||
end
|
||||
|
||||
def on_mount(:require_participant, params, session, socket) do
|
||||
socket = assign_current_participant(socket, session)
|
||||
participant = socket.assigns.current_participant
|
||||
room_number = params["room_number"]
|
||||
|
||||
if participant && participant.room && participant.room.room_number == room_number do
|
||||
{:cont, socket}
|
||||
else
|
||||
socket =
|
||||
socket
|
||||
|> LiveView.put_flash(:error, "このルームに参加するには入室してください。")
|
||||
|> LiveView.redirect(to: ~p"/enter?#{[room: room_number]}")
|
||||
|
||||
{:halt, socket}
|
||||
end
|
||||
end
|
||||
|
||||
def on_mount(:require_owner, params, session, socket) do
|
||||
socket = assign_current_participant(socket, session)
|
||||
participant = socket.assigns.current_participant
|
||||
room_number = params["room_number"]
|
||||
|
||||
if participant && participant.room && participant.room.room_number == room_number &&
|
||||
participant.role == "owner" do
|
||||
{:cont, socket}
|
||||
else
|
||||
socket =
|
||||
socket
|
||||
|> LiveView.put_flash(:error, "この管理ページにアクセスする権限がありません。")
|
||||
|> LiveView.redirect(to: ~p"/")
|
||||
|
||||
{:halt, socket}
|
||||
end
|
||||
end
|
||||
|
||||
defp assign_current_participant(socket, session) do
|
||||
Phoenix.Component.assign_new(socket, :current_participant, fn ->
|
||||
participant_from_token(session[@token_key])
|
||||
end)
|
||||
end
|
||||
|
||||
defp participant_from_token(nil), do: nil
|
||||
defp participant_from_token(token), do: Voting.get_participant_by_token(token)
|
||||
end
|
||||
Reference in New Issue
Block a user