Users can access their items via API. Authentication via API token. No public access to items.

This commit is contained in:
2026-04-22 10:32:42 +02:00
parent 6076654aa4
commit b077a1c81c
7 changed files with 143 additions and 1 deletions

View File

@ -0,0 +1,28 @@
defmodule GenericRestServerWeb.UserTokenController do
use GenericRestServerWeb, :controller
alias GenericRestServer.Accounts
alias GenericRestServer.Accounts.User
action_fallback GenericRestServerWeb.FallbackController
def log_in(conn, %{"user" => user_params}) do
case Accounts.get_user_by_email_and_password(user_params["email"], user_params["password"]) do
%User{} = user ->
create_token(conn, user)
_ ->
conn
|> put_status(:forbidden)
|> render(:error, %{error: "No access for you!"})
end
end
defp create_token(conn, user) do
encoded_token = Accounts.create_user_api_token(user)
updated_user = Map.put(user, :token, encoded_token)
render(conn, :token, user: updated_user)
end
end

View File

@ -0,0 +1,17 @@
defmodule GenericRestServerWeb.UserTokenJSON do
def token(%{user: user}) do
%{
data: %{
id: user.id,
email: user.email,
token: user.token
}
}
end
def error(%{error: error}) do
%{
error: error
}
end
end

View File

@ -17,16 +17,28 @@ defmodule GenericRestServerWeb.Router do
plug :accepts, ["json"]
end
pipeline :protected_api do
plug :accepts, ["json"]
plug :fetch_current_scope_for_api_user
end
scope "/", GenericRestServerWeb do
pipe_through :browser
get "/", PageController, :home
end
# Other scopes may use custom stacks.
# public API
scope "/api", GenericRestServerWeb do
pipe_through :api
post "/log_in", UserTokenController, :log_in
end
# protected API
scope "/api", GenericRestServerWeb do
pipe_through :protected_api
resources "/items", ItemController, except: [:new, :edit]
end

View File

@ -284,4 +284,20 @@ defmodule GenericRestServerWeb.UserAuth do
end
defp maybe_store_return_to(conn), do: conn
## API
def fetch_current_scope_for_api_user(conn, _opts) do
with [<<bearer::binary-size(6), " ", token::binary>>] <-
get_req_header(conn, "authorization"),
true <- String.downcase(bearer) == "bearer",
{:ok, user} <- Accounts.fetch_user_by_api_token(token) do
assign(conn, :current_scope, Scope.for_user(user))
else
_ ->
conn
|> send_resp(:unauthorized, "No access for you")
|> halt()
end
end
end