Rename repository

This commit is contained in:
Pim Kunis 2021-09-01 14:43:55 +02:00
parent 4aeb2d2cd8
commit 232df26b85
71 changed files with 348 additions and 345 deletions

View file

@ -0,0 +1,119 @@
defmodule ArchitexWeb.Federation.EventController do
use ArchitexWeb, :controller
use ArchitexWeb.Federation.AuthenticateServer
import ArchitexWeb.Error
import Ecto.Query
alias Architex.{Repo, Event, RoomServer}
alias ArchitexWeb.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
|> where([e], e.event_id == ^event_id)
|> preload(:room)
case Repo.one(query) do
%Event{room: room} = event ->
case RoomServer.get_room_server(room) do
{:ok, pid} ->
if RoomServer.server_in_room?(pid, origin) do
data = Transaction.new([event])
conn
|> put_status(200)
|> json(data)
else
put_error(conn, :unauthorized, "Origin server is not participating in room.")
end
_ ->
put_error(conn, :unknown)
end
nil ->
put_error(conn, :not_found, "Event or room not found.")
end
end
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
}) do
get_state_or_state_ids(conn, :state, origin, event_id, room_id)
end
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
}) do
get_state_or_state_ids(conn, :state_ids, origin, event_id, room_id)
end
def state_ids(conn, _), do: put_error(conn, :missing_param)
@spec get_state_or_state_ids(
Plug.Conn.t(),
:state | :state_ids,
String.t(),
String.t(),
String.t()
) :: Plug.Conn.t()
defp get_state_or_state_ids(conn, state_or_state_ids, origin, event_id, room_id) do
query =
Event
|> where([e], e.event_id == ^event_id and e.room_id == ^room_id)
|> preload(:room)
case Repo.one(query) do
%Event{room: room} = event ->
case RoomServer.get_room_server(room) do
{:ok, pid} ->
if RoomServer.server_in_room?(pid, origin) do
{state_events, auth_chain} =
case state_or_state_ids do
:state -> RoomServer.get_state_at_event(pid, event)
:state_ids -> RoomServer.get_state_ids_at_event(pid, event)
end
data = %{
auth_chain: auth_chain,
pdus: state_events
}
conn
|> put_status(200)
|> json(data)
else
put_error(conn, :unauthorized, "Origin server is not participating in room.")
end
_ ->
put_error(conn, :unknown)
end
nil ->
put_error(conn, :not_found, "Event or room not found.")
end
end
end

View file

@ -0,0 +1,43 @@
defmodule ArchitexWeb.Federation.KeyController do
use ArchitexWeb, :controller
import ArchitexWeb.Error
alias Architex.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()
|> Enum.into(%{}, fn {key_id, key} ->
{key_id, %{"key" => key}}
end)
# TODO: Consider using TimeX.
# Valid for one month.
valid_until = DateTime.utc_now() |> DateTime.add(60 * 60 * 24 * 30, :second)
data = %{
server_name: Architex.server_name(),
verify_keys: keys,
old_verify_keys: %{},
valid_until_ts: DateTime.to_unix(valid_until, :millisecond)
}
case KeyServer.sign_object(data) do
{:ok, sig, key_id} ->
signed_data = Architex.add_signature(data, key_id, sig)
conn
|> put_status(200)
|> json(signed_data)
:error ->
put_error(conn, :unknown, "Error signing object.")
end
end
end

View file

@ -0,0 +1,61 @@
defmodule ArchitexWeb.Federation.QueryController do
use ArchitexWeb, :controller
use ArchitexWeb.Federation.AuthenticateServer
import ArchitexWeb.Error
import Ecto.Query
alias Architex.{Repo, Account}
alias Architex.Types.UserId
defmodule ProfileRequest do
use Ecto.Schema
import Ecto.Changeset
@primary_key false
embedded_schema do
field :user_id, UserId
field :field, :string
end
def validate(params) do
%__MODULE__{}
|> cast(params, [:user_id, :field])
|> validate_required([:user_id])
|> validate_inclusion(:field, ["displayname", "avatar_url"])
|> then(fn
%Ecto.Changeset{valid?: true} = cs -> {:ok, apply_changes(cs)}
_ -> :error
end)
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
if domain == Architex.server_name() do
case Repo.one(from a in Account, where: a.localpart == ^localpart) do
%Account{} ->
# TODO: Return displayname and avatar_url when we implement them.
conn
|> put_status(200)
|> json(%{})
nil ->
put_error(conn, :not_found, "User does not exist.")
end
else
put_error(conn, :not_found, "Wrong server name.")
end
else
_ -> put_error(conn, :bad_json)
end
end
end