From 1a5b66a3d7ff1dbda04d5bbc48f24281a3e31dff Mon Sep 17 00:00:00 2001 From: Pim Kunis Date: Fri, 30 Jul 2021 15:56:24 +0200 Subject: [PATCH] Add alias creation endpoint --- lib/matrix_server/alias.ex | 28 +++++++++++++++++++ lib/matrix_server/room.ex | 3 +- .../controllers/aliases_controller.ex | 22 +++++++++++++++ lib/matrix_server_web/plug/error.ex | 8 ++++-- lib/matrix_server_web/router.ex | 4 +++ .../20210730122017_create_aliases_table.exs | 12 ++++++++ 6 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 lib/matrix_server/alias.ex create mode 100644 lib/matrix_server_web/controllers/aliases_controller.ex create mode 100644 priv/repo/migrations/20210730122017_create_aliases_table.exs diff --git a/lib/matrix_server/alias.ex b/lib/matrix_server/alias.ex new file mode 100644 index 0000000..a33d423 --- /dev/null +++ b/lib/matrix_server/alias.ex @@ -0,0 +1,28 @@ +defmodule MatrixServer.Alias do + use Ecto.Schema + + import Ecto.Changeset + + alias MatrixServer.{Repo, Alias, Room} + alias Ecto.Changeset + + @primary_key {:alias, :string, []} + schema "aliases" do + belongs_to :room, Room, foreign_key: :room_id, references: :id, type: :string + end + + def create(alias, room_id) do + change(%Alias{}, alias: alias, room_id: room_id) + |> assoc_constraint(:room) + |> unique_constraint(:alias, name: :aliases_pkey) + |> Repo.insert() + end + + def get_error(%Changeset{errors: [error | _]}), do: get_error(error) + def get_error({:alias, {_, [{:constraint, :unique} | _]}}), do: :room_alias_exists + + def get_error({:room, {_, [{:constraint, :assoc} | _]}}), + do: {:not_found, "The room was not found."} + + def get_error(_), do: :bad_json +end diff --git a/lib/matrix_server/room.ex b/lib/matrix_server/room.ex index c01b647..883cbdb 100644 --- a/lib/matrix_server/room.ex +++ b/lib/matrix_server/room.ex @@ -4,7 +4,7 @@ defmodule MatrixServer.Room do import Ecto.Changeset import Ecto.Query - alias MatrixServer.{Repo, Room, Event, RoomServer} + alias MatrixServer.{Repo, Room, Event, Alias, RoomServer} alias MatrixServerWeb.API.CreateRoom @primary_key {:id, :string, []} @@ -13,6 +13,7 @@ defmodule MatrixServer.Room do field :state, {:array, {:array, :string}} field :forward_extremities, {:array, :string} has_many :events, Event, foreign_key: :event_id + has_many :aliases, Alias, foreign_key: :room_id end def changeset(room, params \\ %{}) do diff --git a/lib/matrix_server_web/controllers/aliases_controller.ex b/lib/matrix_server_web/controllers/aliases_controller.ex new file mode 100644 index 0000000..6c06641 --- /dev/null +++ b/lib/matrix_server_web/controllers/aliases_controller.ex @@ -0,0 +1,22 @@ +defmodule MatrixServerWeb.AliasesController do + use MatrixServerWeb, :controller + + import MatrixServerWeb.Plug.Error + + alias MatrixServer.Alias + + def create(conn, %{"alias" => alias, "room_id" => room_id}) do + case Alias.create(alias, room_id) do + {:ok, _} -> + conn + |> put_status(200) + |> json(%{}) + + {:error, cs} -> + put_error(conn, Alias.get_error(cs)) + end + end + + # TODO: create error view for this? + def create(conn, _), do: put_error(conn, :bad_json) +end diff --git a/lib/matrix_server_web/plug/error.ex b/lib/matrix_server_web/plug/error.ex index 465232d..d65abad 100644 --- a/lib/matrix_server_web/plug/error.ex +++ b/lib/matrix_server_web/plug/error.ex @@ -10,11 +10,15 @@ defmodule MatrixServerWeb.Plug.Error do unrecognized: {400, "M_UNRECOGNIZED", "Unrecognized request."}, unknown: {400, "M_UNKNOWN", "An unknown error occurred."}, invalid_room_state: - {400, "M_INVALID_ROOM_STATE", "The request would result in and invalid room state."}, + {400, "M_INVALID_ROOM_STATE", "The request would leave the room in an invalid state."}, unknown_token: {401, "M_UNKNOWN_TOKEN", "Invalid access token."}, - missing_token: {401, "M_MISSING_TOKEN", "Access token required."} + missing_token: {401, "M_MISSING_TOKEN", "Access token required."}, + not_found: {404, "M_NOT_FOUND", "The requested resource was not found."}, + room_alias_exists: {409, "M.UNKNOWN", "The given room alias already exists."} } + def put_error(conn, {error, msg}), do: put_error(conn, error, msg) + def put_error(conn, error, msg \\ nil) do {status, errcode, default_msg} = @error_map[error] data = %{errcode: errcode, error: msg || default_msg} diff --git a/lib/matrix_server_web/router.ex b/lib/matrix_server_web/router.ex index 382169d..f007714 100644 --- a/lib/matrix_server_web/router.ex +++ b/lib/matrix_server_web/router.ex @@ -33,6 +33,10 @@ defmodule MatrixServerWeb.Router do post "/logout", AccountController, :logout post "/logout/all", AccountController, :logout_all post "/createRoom", RoomController, :create + + scope "/directory/room" do + put "/:alias", AliasesController, :create + end end end diff --git a/priv/repo/migrations/20210730122017_create_aliases_table.exs b/priv/repo/migrations/20210730122017_create_aliases_table.exs new file mode 100644 index 0000000..b5f8df8 --- /dev/null +++ b/priv/repo/migrations/20210730122017_create_aliases_table.exs @@ -0,0 +1,12 @@ +defmodule MatrixServer.Repo.Migrations.CreateAliasesTable do + use Ecto.Migration + + def change do + create table(:aliases, primary_key: false) do + add :alias, :string, primary_key: true, null: false + add :room_id, references(:rooms, type: :string, on_delete: :delete_all), null: false + end + + create index(:aliases, [:room_id]) + end +end