diff --git a/lib/matrix_server.ex b/lib/matrix_server.ex index e9e3e38..5171ecc 100644 --- a/lib/matrix_server.ex +++ b/lib/matrix_server.ex @@ -30,17 +30,6 @@ defmodule MatrixServer do |> validate_required(required) end - def generate_error(errcode) do - {get_errcode_status(errcode), %{errcode: errcode, error: get_errcode_error(errcode)}} - end - - # TODO: make a plug for this? - def get_errcode_error("M_BAD_JSON"), do: "Bad request." - def get_errcode_error("M_USER_IN_USE"), do: "Username is already taken." - def get_errcode_error("M_INVALID_USERNAME"), do: "Invalid username." - - def get_errcode_status(_), do: 400 - def get_mxid(localpart) when is_binary(localpart) do "@#{localpart}:#{server_name()}" end diff --git a/lib/matrix_server_web/controllers/account_controller.ex b/lib/matrix_server_web/controllers/account_controller.ex index e5fe220..d50e4a2 100644 --- a/lib/matrix_server_web/controllers/account_controller.ex +++ b/lib/matrix_server_web/controllers/account_controller.ex @@ -1,7 +1,8 @@ defmodule MatrixServerWeb.AccountController do use MatrixServerWeb, :controller - import MatrixServer, only: [get_mxid: 1] + import MatrixServer + import MatrixServerWeb.Plug.Error alias MatrixServer.Account alias Plug.Conn @@ -9,21 +10,15 @@ defmodule MatrixServerWeb.AccountController do def available(conn, params) do localpart = Map.get(params, "username", "") - {status, data} = - case Account.available?(localpart) do - :ok -> - {200, %{available: true}} + case Account.available?(localpart) do + :ok -> + conn + |> put_status(200) + |> json(%{available: true}) - {:error, :user_in_use} -> - {400, %{errcode: "M_USER_IN_USE", error: "Desired user ID is already taken."}} - - {:error, :invalid_username} -> - {400, %{errocode: "M_INVALID_USERNAME", error: "Desired user ID is invalid."}} - end - - conn - |> put_status(status) - |> json(data) + {:error, error} -> + put_error(conn, error) + end end def whoami(%Conn{assigns: %{account: %Account{localpart: localpart}}} = conn, _params) do diff --git a/lib/matrix_server_web/controllers/auth_controller.ex b/lib/matrix_server_web/controllers/auth_controller.ex index 4c486a0..bb6aa60 100644 --- a/lib/matrix_server_web/controllers/auth_controller.ex +++ b/lib/matrix_server_web/controllers/auth_controller.ex @@ -2,6 +2,7 @@ defmodule MatrixServerWeb.AuthController do use MatrixServerWeb, :controller import MatrixServer + import MatrixServerWeb.Plug.Error alias MatrixServer.{Repo, Account} alias Ecto.Changeset @@ -38,7 +39,7 @@ defmodule MatrixServerWeb.AuthController do {200, data} {:error, error} -> - generate_error(error) + put_error(conn, error) end conn @@ -48,11 +49,7 @@ defmodule MatrixServerWeb.AuthController do def register(conn, %{"auth" => _}) do # Other login types are unsupported for now. - data = %{errcode: "M_FORBIDDEN", error: "Login type not supported"} - - conn - |> put_status(400) - |> json(data) + put_error(conn, :forbidden) end def register(conn, _params) do @@ -80,9 +77,9 @@ defmodule MatrixServerWeb.AuthController do end defp get_register_error(%Changeset{errors: [error | _]}), do: get_register_error(error) - defp get_register_error({:localpart, {_, [{:constraint, :unique} | _]}}), do: "M_USER_IN_USE" - defp get_register_error({:localpart, {_, [{:validation, _} | _]}}), do: "M_INVALID_USERNAME" - defp get_register_error(_), do: "M_BAD_JSON" + defp get_register_error({:localpart, {_, [{:constraint, :unique} | _]}}), do: :user_in_use + defp get_register_error({:localpart, {_, [{:validation, _} | _]}}), do: :invalid_username + defp get_register_error(_), do: :bad_json defp register_schema do types = %{ diff --git a/lib/matrix_server_web/authenticate.ex b/lib/matrix_server_web/plug/authenticate.ex similarity index 64% rename from lib/matrix_server_web/authenticate.ex rename to lib/matrix_server_web/plug/authenticate.ex index d517c62..b30e7f2 100644 --- a/lib/matrix_server_web/authenticate.ex +++ b/lib/matrix_server_web/plug/authenticate.ex @@ -1,11 +1,12 @@ -defmodule MatrixServerWeb.Authenticate do +defmodule MatrixServerWeb.Plug.Authenticate do + import MatrixServerWeb.Plug.Error import Plug.Conn import Phoenix.Controller, only: [json: 2] alias MatrixServer.Account alias Plug.Conn - def init(options), do: options + def init(opts), do: opts def call(%Conn{params: %{"access_token" => access_token}} = conn, _opts) do authenticate(conn, access_token) @@ -17,12 +18,7 @@ defmodule MatrixServerWeb.Authenticate do authenticate(conn, access_token) _ -> - data = %{errcode: "M_MISSING_TOKEN", error: "Access token missing."} - - conn - |> put_status(401) - |> json(data) - |> halt() + put_error(conn, :missing_token) end end @@ -34,12 +30,7 @@ defmodule MatrixServerWeb.Authenticate do |> assign(:device, device) nil -> - data = %{errcode: "M_UNKNOWN_TOKEN", error: "Invalid access token."} - - conn - |> put_status(401) - |> json(data) - |> halt() + put_error(conn, :unknown_token) end end end diff --git a/lib/matrix_server_web/plug/error.ex b/lib/matrix_server_web/plug/error.ex new file mode 100644 index 0000000..74ad8db --- /dev/null +++ b/lib/matrix_server_web/plug/error.ex @@ -0,0 +1,23 @@ +defmodule MatrixServerWeb.Plug.Error do + import Plug.Conn + import Phoenix.Controller, only: [json: 2] + + @error_code_and_message %{ + bad_json: {400, "M_BAD_JSON", "Bad request."}, + user_in_use: {400, "M_USE_IN_USE", "Username is already taken."}, + invalid_username: {400, "M_INVALID_USERNAME", "Invalid username."}, + forbidden: {400, "M_FORBIDDEN", "The requested action is forbidden."}, + unknown_token: {401, "M_UNKNOWN_TOKEN", "Invalid access token."}, + missing_token: {401, "M_MISSING_TOKEN", "Access token required."} + } + + def put_error(conn, error) do + {status, errcode, errmsg} = @error_code_and_message[error] + data = %{errcode: errcode, error: errmsg} + + conn + |> put_status(status) + |> json(data) + |> halt() + end +end diff --git a/lib/matrix_server_web/router.ex b/lib/matrix_server_web/router.ex index 66378bd..4e2e215 100644 --- a/lib/matrix_server_web/router.ex +++ b/lib/matrix_server_web/router.ex @@ -1,13 +1,15 @@ defmodule MatrixServerWeb.Router do use MatrixServerWeb, :router + alias MatrixServerWeb.Plug.Authenticate + pipeline :public do plug :accepts, ["json"] end pipeline :authenticated do plug :accepts, ["json"] - plug MatrixServerWeb.Authenticate + plug Authenticate end scope "/_matrix", MatrixServerWeb do