Implement client joined rooms endpoint
Track which rooms a local account has joined Add some documentation to modules
This commit is contained in:
parent
9d40f8bc8b
commit
6f8c224d50
8 changed files with 95 additions and 11 deletions
|
@ -11,7 +11,7 @@ defmodule MatrixServer.RoomServer do
|
|||
import Ecto.Query
|
||||
import Ecto.Changeset
|
||||
|
||||
alias MatrixServer.{Repo, Room, Event, StateResolution}
|
||||
alias MatrixServer.{Repo, Room, Event, StateResolution, JoinedRoom, Account}
|
||||
alias MatrixServer.StateResolution.Authorization
|
||||
alias MatrixServerWeb.Client.Request.CreateRoom
|
||||
|
||||
|
@ -199,6 +199,7 @@ defmodule MatrixServer.RoomServer do
|
|||
join_creator <- Event.join(room, account, [create_room]),
|
||||
{:ok, state_set, join_creator, room} <-
|
||||
verify_and_insert_event(join_creator, state_set, room),
|
||||
{:ok, _} <- insert_joined_room_assoc(account, room),
|
||||
pls <- Event.power_levels(room, account, [create_room, join_creator]),
|
||||
{:ok, state_set, pls, room} <- verify_and_insert_event(pls, state_set, room) do
|
||||
auth_events = [create_room, join_creator, pls]
|
||||
|
@ -236,6 +237,10 @@ defmodule MatrixServer.RoomServer do
|
|||
end
|
||||
end
|
||||
|
||||
defp insert_joined_room_assoc(%Account{localpart: localpart}, %Room{id: room_id}) do
|
||||
Repo.insert(%JoinedRoom{localpart: localpart, room_id: room_id})
|
||||
end
|
||||
|
||||
# TODO: trusted_private_chat:
|
||||
# All invitees are given the same power level as the room creator.
|
||||
defp room_creation_preset(account, nil, %Room{visibility: visibility} = room, auth_events) do
|
||||
|
|
|
@ -3,7 +3,7 @@ defmodule MatrixServer.Account do
|
|||
|
||||
import Ecto.{Changeset, Query}
|
||||
|
||||
alias MatrixServer.{Repo, Account, Device}
|
||||
alias MatrixServer.{Repo, Account, Device, Room, JoinedRoom}
|
||||
alias MatrixServerWeb.Client.Request.{Register, Login}
|
||||
alias Ecto.Multi
|
||||
|
||||
|
@ -17,6 +17,11 @@ defmodule MatrixServer.Account do
|
|||
schema "accounts" do
|
||||
field :password_hash, :string, redact: true
|
||||
has_many :devices, Device, foreign_key: :localpart
|
||||
|
||||
many_to_many :joined_rooms, Room,
|
||||
join_through: JoinedRoom,
|
||||
join_keys: [localpart: :localpart, room_id: :id]
|
||||
|
||||
timestamps(updated_at: false)
|
||||
end
|
||||
|
||||
|
|
16
lib/matrix_server/schema/joined_room.ex
Normal file
16
lib/matrix_server/schema/joined_room.ex
Normal file
|
@ -0,0 +1,16 @@
|
|||
defmodule MatrixServer.JoinedRoom do
|
||||
use Ecto.Schema
|
||||
|
||||
alias MatrixServer.{Account, Room}
|
||||
|
||||
@primary_key false
|
||||
schema "joined_rooms" do
|
||||
belongs_to :account, Account,
|
||||
foreign_key: :localpart,
|
||||
references: :localpart,
|
||||
type: :string,
|
||||
primary_key: true
|
||||
|
||||
belongs_to :room, Room, primary_key: true, type: :string
|
||||
end
|
||||
end
|
|
@ -1,4 +1,23 @@
|
|||
defmodule MatrixServer.StateResolution do
|
||||
@moduledoc """
|
||||
Functions for resolving the state of a Matrix room.
|
||||
|
||||
Currently, only state resolution from room version 2 is supported,
|
||||
see [the Matrix docs](https://spec.matrix.org/unstable/rooms/v2/).
|
||||
|
||||
The current implementation of the state resolution algorithm performs
|
||||
rather badly.
|
||||
Each time state is resolved, all events in the room are fetched from
|
||||
the database and loaded into memory.
|
||||
This is mostly so I didn't have to worry about fetching events from the
|
||||
database when developing this initial implementation.
|
||||
Then, the state is calculated using the new event's previous events and auth
|
||||
events.
|
||||
To prevent loading all events into memory, and calculating the whole state each
|
||||
time, we should make snapshots of the state of a room at regular intervals.
|
||||
It looks like Dendrite does this too.
|
||||
"""
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
alias MatrixServer.{Repo, Event, Room}
|
||||
|
@ -61,6 +80,13 @@ defmodule MatrixServer.StateResolution do
|
|||
|> Enum.reduce(MapSet.new(), &MapSet.union/2)
|
||||
end
|
||||
|
||||
def update_state_set(
|
||||
%Event{type: event_type, state_key: state_key} = event,
|
||||
state_set
|
||||
) do
|
||||
Map.put(state_set, {event_type, state_key}, event)
|
||||
end
|
||||
|
||||
defp do_resolve([], _), do: %{}
|
||||
|
||||
defp do_resolve(state_sets, room_events) do
|
||||
|
@ -265,13 +291,6 @@ defmodule MatrixServer.StateResolution do
|
|||
end)
|
||||
end
|
||||
|
||||
def update_state_set(
|
||||
%Event{type: event_type, state_key: state_key} = event,
|
||||
state_set
|
||||
) do
|
||||
Map.put(state_set, {event_type, state_key}, event)
|
||||
end
|
||||
|
||||
defp authorized?(%Event{auth_events: auth_event_ids} = event, state_set, room_events) do
|
||||
state_set =
|
||||
auth_event_ids
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
defmodule MatrixServer.StateResolution.Authorization do
|
||||
@moduledoc """
|
||||
Implementation of Matrix event authorization rules for stat resolution.
|
||||
|
||||
Note that some authorization rules are already checked in
|
||||
`MatrixServer.Event.prevalidate/1` so they are skipped here.
|
||||
"""
|
||||
|
||||
import MatrixServer.StateResolution
|
||||
import Ecto.Query
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@ defmodule MatrixServerWeb.Client.RoomController do
|
|||
use MatrixServerWeb, :controller
|
||||
|
||||
import MatrixServerWeb.Error
|
||||
import Ecto.Changeset
|
||||
import Ecto.{Changeset, Query}
|
||||
|
||||
alias MatrixServer.Room
|
||||
alias MatrixServer.{Repo, Room}
|
||||
alias MatrixServerWeb.Client.Request.CreateRoom
|
||||
alias Ecto.Changeset
|
||||
alias Plug.Conn
|
||||
|
@ -31,4 +31,19 @@ defmodule MatrixServerWeb.Client.RoomController do
|
|||
put_error(conn, :bad_json)
|
||||
end
|
||||
end
|
||||
|
||||
def joined_rooms(%Conn{assigns: %{account: account}} = conn, _params) do
|
||||
joined_room_ids = account
|
||||
|> Ecto.assoc(:joined_rooms)
|
||||
|> select([jr], jr.id)
|
||||
|> Repo.all()
|
||||
|
||||
data = %{
|
||||
joined_rooms: joined_room_ids
|
||||
}
|
||||
|
||||
conn
|
||||
|> put_status(200)
|
||||
|> json(data)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -51,6 +51,7 @@ defmodule MatrixServerWeb.Router do
|
|||
post "/logout", AccountController, :logout
|
||||
post "/logout/all", AccountController, :logout_all
|
||||
post "/createRoom", RoomController, :create
|
||||
get "/joined_rooms", RoomController, :joined_rooms
|
||||
|
||||
scope "/directory/room" do
|
||||
put "/:alias", AliasesController, :create
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
defmodule MatrixServer.Repo.Migrations.CreateJoinedRoomsTable do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create table(:joined_rooms, primary_key: false) do
|
||||
add :localpart,
|
||||
references(:accounts, column: :localpart, type: :string),
|
||||
primary_key: true,
|
||||
null: false
|
||||
|
||||
add :room_id, references(:rooms, type: :string),
|
||||
primary_key: true,
|
||||
null: false
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue