Rename repository
This commit is contained in:
parent
4aeb2d2cd8
commit
232df26b85
71 changed files with 348 additions and 345 deletions
119
lib/architex_web/federation/controllers/event_controller.ex
Normal file
119
lib/architex_web/federation/controllers/event_controller.ex
Normal 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
|
43
lib/architex_web/federation/controllers/key_controller.ex
Normal file
43
lib/architex_web/federation/controllers/key_controller.ex
Normal 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
|
61
lib/architex_web/federation/controllers/query_controller.ex
Normal file
61
lib/architex_web/federation/controllers/query_controller.ex
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue