Implement client invite endpoint

Refactor room server to automatically determine auth events
Add documentation in various places
This commit is contained in:
Pim Kunis 2021-08-25 01:27:03 +02:00
parent 6f8c224d50
commit bcc6cbb24b
15 changed files with 345 additions and 209 deletions

View file

@ -7,6 +7,11 @@ defmodule MatrixServerWeb.Client.AccountController do
alias MatrixServer.{Account, Repo}
alias Plug.Conn
@doc """
Checks to see if a username is available, and valid, for the server.
Action for GET /_matrix/client/r0/register/available.
"""
def available(conn, params) do
localpart = Map.get(params, "username", "")
@ -21,6 +26,11 @@ defmodule MatrixServerWeb.Client.AccountController do
end
end
@doc """
Gets information about the owner of a given access token.
Action for GET /_matrix/client/r0/account/whoami.
"""
def whoami(%Conn{assigns: %{account: %Account{localpart: localpart}}} = conn, _params) do
data = %{user_id: get_mxid(localpart)}
@ -29,6 +39,11 @@ defmodule MatrixServerWeb.Client.AccountController do
|> json(data)
end
@doc """
Invalidates an existing access token, so that it can no longer be used for authorization.
Action for POST /_matrix/client/r0/logout.
"""
def logout(%Conn{assigns: %{device: device}} = conn, _params) do
case Repo.delete(device) do
{:ok, _} ->
@ -41,6 +56,12 @@ defmodule MatrixServerWeb.Client.AccountController do
end
end
@doc """
Invalidates all access tokens for a user, so that they can no longer be used
for authorization.
Action for POST /_matrix/client/r0/logout/all.
"""
def logout_all(%Conn{assigns: %{account: account}} = conn, _params) do
Repo.delete_all(Ecto.assoc(account, :devices))

View file

@ -5,6 +5,11 @@ defmodule MatrixServerWeb.Client.AliasesController do
alias MatrixServer.Alias
@doc """
Create a new mapping from room alias to room ID.
Action for PUT /_matrix/client/r0/directory/room/{roomAlias}.
"""
def create(conn, %{"alias" => alias, "room_id" => room_id}) do
case Alias.create(alias, room_id) do
{:ok, _} ->

View file

@ -5,6 +5,11 @@ defmodule MatrixServerWeb.Client.InfoController do
@supported_versions ["r0.6.1"]
@doc """
Gets the versions of the specification supported by the server.
Action for GET /_matrix/client/versions.
"""
def versions(conn, _params) do
data = %{versions: @supported_versions}

View file

@ -10,6 +10,11 @@ defmodule MatrixServerWeb.Client.LoginController do
@login_type "m.login.password"
@doc """
Gets the homeserver's supported login types to authenticate users.
Action for GET /_matrix/client/r0/login.
"""
def login_types(conn, _params) do
data = %{flows: [%{type: @login_type}]}
@ -18,6 +23,12 @@ defmodule MatrixServerWeb.Client.LoginController do
|> json(data)
end
@doc """
Authenticates the user, and issues an access token they can use to
authorize themself in subsequent requests.
Action for POST /_matrix/client/r0/login.
"""
def login(
conn,
%{"type" => @login_type, "identifier" => %{"type" => "m.id.user"}} = params

View file

@ -10,6 +10,11 @@ defmodule MatrixServerWeb.Client.RegisterController do
@register_type "m.login.dummy"
@doc """
Register for an account on this homeserver.
Action for POST /_matrix/client/r0/register.
"""
def register(conn, %{"auth" => %{"type" => @register_type}} = params) do
case Register.changeset(params) do
%Changeset{valid?: true} = cs ->

View file

@ -4,11 +4,17 @@ defmodule MatrixServerWeb.Client.RoomController do
import MatrixServerWeb.Error
import Ecto.{Changeset, Query}
alias MatrixServer.{Repo, Room}
alias MatrixServer.{Repo, Room, RoomServer}
alias MatrixServer.Types.UserId
alias MatrixServerWeb.Client.Request.CreateRoom
alias Ecto.Changeset
alias Plug.Conn
@doc """
Create a new room with various configuration options.
Action for POST /_matrix/client/r0/createRoom.
"""
def create(%Conn{assigns: %{account: account}} = conn, params) do
case CreateRoom.changeset(params) do
%Changeset{valid?: true} = cs ->
@ -32,11 +38,17 @@ defmodule MatrixServerWeb.Client.RoomController do
end
end
@doc """
This API returns a list of the user's current rooms.
Action for GET /_matrix/client/r0/joined_rooms.
"""
def joined_rooms(%Conn{assigns: %{account: account}} = conn, _params) do
joined_room_ids = account
|> Ecto.assoc(:joined_rooms)
|> select([jr], jr.id)
|> Repo.all()
joined_room_ids =
account
|> Ecto.assoc(:joined_rooms)
|> select([jr], jr.id)
|> Repo.all()
data = %{
joined_rooms: joined_room_ids
@ -46,4 +58,32 @@ defmodule MatrixServerWeb.Client.RoomController do
|> put_status(200)
|> json(data)
end
@doc """
This API invites a user to participate in a particular room.
Action for POST /_matrix/client/r0/rooms/{roomId}/invite.
"""
def invite(%Conn{assigns: %{account: account}} = conn, %{
"room_id" => room_id,
"user_id" => user_id
}) do
with {:ok, _} <- UserId.cast(user_id),
{:ok, pid} <- RoomServer.get_room_server(room_id) do
case RoomServer.invite(pid, account, user_id) do
:ok ->
conn
|> send_resp(200, [])
|> halt()
{:error, _} ->
put_error(conn, :unknown)
end
else
:error -> put_error(conn, :invalid_param, "Given user ID is invalid.")
{:error, :not_found} -> put_error(conn, :not_found, "The given room was not found.")
end
end
def invite(conn, _), do: put_error(conn, :missing_param)
end

View file

@ -8,6 +8,11 @@ defmodule MatrixServerWeb.Federation.EventController do
alias MatrixServer.{Repo, Event, RoomServer}
alias MatrixServerWeb.Federation.Transaction
@doc """
Retrieves a single event.
Action for GET /_matrix/federation/v1/event/{eventId}.
"""
def event(%Plug.Conn{assigns: %{origin: origin}} = conn, %{"event_id" => event_id}) do
query =
Event
@ -39,6 +44,11 @@ defmodule MatrixServerWeb.Federation.EventController do
def event(conn, _), do: put_error(conn, :missing_param)
@doc """
Retrieves a snapshot of a room's state at a given event.
Action for GET /_matrix/federation/v1/state/{roomId}.
"""
def state(%Plug.Conn{assigns: %{origin: origin}} = conn, %{
"event_id" => event_id,
"room_id" => room_id
@ -48,6 +58,11 @@ defmodule MatrixServerWeb.Federation.EventController do
def state(conn, _), do: put_error(conn, :missing_param)
@doc """
Retrieves a snapshot of a room's state at a given event, in the form of event IDs.
Action for GET /_matrix/federation/v1/state_ids/{roomId}.
"""
def state_ids(%Plug.Conn{assigns: %{origin: origin}} = conn, %{
"event_id" => event_id,
"room_id" => room_id

View file

@ -5,6 +5,11 @@ defmodule MatrixServerWeb.Federation.KeyController do
alias MatrixServer.KeyServer
@doc """
Gets the homeserver's published signing keys.
Action for GET /_matrix/key/v2/server/{keyId}.
"""
def get_signing_keys(conn, _params) do
keys =
KeyServer.get_own_signing_keys()

View file

@ -31,6 +31,12 @@ defmodule MatrixServerWeb.Federation.QueryController do
end
end
@doc """
Performs a query to get profile information, such as a display name or avatar,
for a given user.
Action for GET /_matrix/federation/v1/query/profile.
"""
def profile(conn, params) do
with {:ok, %ProfileRequest{user_id: %UserId{localpart: localpart, domain: domain}}} <-
ProfileRequest.validate(params) do

View file

@ -56,6 +56,10 @@ defmodule MatrixServerWeb.Router do
scope "/directory/room" do
put "/:alias", AliasesController, :create
end
scope "/rooms/:room_id" do
post "/invite", RoomController, :invite
end
end
end