defmodule HostasWeb.Auth.TokenController do import Ecto.Query, only: [from: 2] use HostasWeb, :controller alias Hostas.Repo alias Hostas.Denizen alias Hostas.Token @doc """ Generates an API token. Responds with the token if the user provides the correct password """ def create(conn, %{"handle" => handle, "password" => given_password}) do case Repo.one(from d in Denizen, where: d.handle == ^handle, select: %{id: d.id, password: d.password}) do nil -> conn |> put_status(404) |> json(%{"error" => "No user with handle #{handle}"}) denizen -> %{id: denizen_id, password: real_password_hash} = denizen if Bcrypt.verify_pass(given_password, real_password_hash) do # Create a random token token = Base.encode64(:crypto.strong_rand_bytes(256)) # Calculate when the token should expire {:ok, time_now} = DateTime.now("Etc/UTC") expiry = DateTime.add(time_now, 30, :day) |> DateTime.truncate(:second) # Register the token {:ok, token_struct} = Repo.insert( %Token{denizen_id: denizen_id, token: token, expires: expiry}) conn |> put_status(201) |> json(Map.take(token_struct, [:token, :expires])) else # Reject the request, as passwords don't match conn |> put_status(401) |> json(%{"error" => "Password mismatch"}) end end end def create(conn, params) do conn |> put_status(422) |> json(%{"error" => "Missing required parameters"}) end @doc """ Responds with 200 OK if the requester's `Bearing` header contains a valid, non-expired API token """ def verify(_conn, _params) do :ok end @doc """ Deletes the token the requester used in the `Bearing` header """ def revoke(_conn, _params) do :ok end @doc """ Deletes the token the requester used in the `Bearing` header and responds with a new one if the old one was valid and unexpired """ def renew(_conn, _params) do :ok end end