defmodule MaatFeatherWeb.AuthController do @moduledoc """ Controller for authentication. """ use MaatFeatherWeb, :controller alias MaatFeather.Users alias MaatFeather.Users.User alias MaatFeather.Auth.{Token, TOTP} alias MaatFeatherWeb.UserView action_fallback MaatFeatherWeb.FallbackController @doc """ Signin a user to the system. """ def signin(conn, %{"email" => email, "password" => password} = params) do with %User{} = user <- Users.get_user_by!(email: email), true <- Argon2.verify_pass(password, user.password_hash) do unless user.has_mfa do {:ok, access_token, _claims} = Token.encode(user) conn |> put_status(:ok) |> json(%{access_token: access_token}) else if TOTP.is_valid?(user.secret_key, params["totp_token"]) do {:ok, access_token, _claims} = Token.encode(user) conn |> put_status(:ok) |> json(%{access_token: access_token}) else {:error, :unauthorized} end end else _ -> {:error, :unauthorized} end end def refresh_token(%Plug.Conn{assigns: %{access_token: access_token}} = conn, _params) do with {:ok, {_old_token, _old_claims}, {new_token, _new_claims}} <- Token.refresh(access_token) do conn |> put_status(:ok) |> json(%{refresh_token: new_token}) else {:error, message} -> conn |> put_status(:unauthorized) |> json(%{errors: %{message: message}}) end end def refresh_token(_conn, _params), do: {:error, :unauthorized} def totp_qrcode(%Plug.Conn{assigns: %{user: %{"sub" => address}}} = conn, _params) do case Users.get_user!(address) do nil -> {:error, :not_found} user -> qrcode = TOTP.gen_qrcode(user.email, user.secret_key) conn |> put_status(:ok) |> json(%{qrcode: qrcode}) end end @doc """ Get user profile. """ def profile( %Plug.Conn{assigns: %{user: %{"sub" => address}}} = conn, _params ) do case Users.get_user!(address) do nil -> {:error, :not_found} user -> conn |> put_view(UserView) |> put_status(:ok) |> render("show.json", %{user: user}) end end def profile(_conn, _params), do: {:error, :unauthorized} end