Save state set in database

This commit is contained in:
Pim Kunis 2021-07-25 17:39:22 +02:00
parent 8a5bba72fb
commit d3c16dd7aa
3 changed files with 48 additions and 15 deletions

View file

@ -9,11 +9,6 @@ defmodule MatrixServer.RoomServer do
@registry MatrixServer.RoomServer.Registry @registry MatrixServer.RoomServer.Registry
@supervisor MatrixServer.RoomServer.Supervisor @supervisor MatrixServer.RoomServer.Supervisor
def start_link(opts) do
{name, opts} = Keyword.pop(opts, :name)
GenServer.start_link(__MODULE__, opts, name: name)
end
def create_room(input, account) do def create_room(input, account) do
%Room{id: room_id} = room = Repo.insert!(Room.create_changeset(input)) %Room{id: room_id} = room = Repo.insert!(Room.create_changeset(input))
@ -27,6 +22,11 @@ defmodule MatrixServer.RoomServer do
DynamicSupervisor.start_child(@supervisor, {__MODULE__, opts}) DynamicSupervisor.start_child(@supervisor, {__MODULE__, opts})
end end
def start_link(opts) do
{name, opts} = Keyword.pop(opts, :name)
GenServer.start_link(__MODULE__, opts, name: name)
end
@impl true @impl true
def init(opts) do def init(opts) do
%Room{id: room_id} = Keyword.fetch!(opts, :room) %Room{id: room_id} = Keyword.fetch!(opts, :room)
@ -36,6 +36,8 @@ defmodule MatrixServer.RoomServer do
Repo.transaction(fn -> Repo.transaction(fn ->
with {:ok, state_set} <- insert_create_room_event(account, input, room_id) do with {:ok, state_set} <- insert_create_room_event(account, input, room_id) do
{:ok, %{room_id: room_id, state_set: state_set}} {:ok, %{room_id: room_id, state_set: state_set}}
else
_ -> {:error, :something}
end end
end) end)
end end
@ -47,27 +49,30 @@ defmodule MatrixServer.RoomServer do
) do ) do
create_room_event = Event.create_room(room_id, MatrixServer.get_mxid(localpart), room_version) create_room_event = Event.create_room(room_id, MatrixServer.get_mxid(localpart), room_version)
verify_and_insert_event(create_room_event) verify_and_insert_event(create_room_event, %{})
{:ok, %{}}
end end
defp verify_and_insert_event(event) do defp verify_and_insert_event(event, current_state_set) do
# Check the following things: # Check the following things:
# 1. TODO: Is a valid event, otherwise it is dropped. # 1. TODO: Is a valid event, otherwise it is dropped.
# 2. TODO: Passes signature checks, otherwise it is dropped. # 2. TODO: Passes signature checks, otherwise it is dropped.
# 3. TODO: Passes hash checks, otherwise it is redacted before being processed further. # 3. TODO: Passes hash checks, otherwise it is redacted before being processed further.
# 4. Passes authorization rules based on the event's auth events, otherwise it is rejected. # 4. Passes authorization rules based on the event's auth events, otherwise it is rejected.
# 5. Passes authorization rules based on the state at the event, otherwise it is rejected. # 5. Passes authorization rules based on the state at the event, otherwise it is rejected.
# 6. TODO: Passes authorization rules based on the current state of the room, otherwise it is "soft failed". # 6. Passes authorization rules based on the current state of the room, otherwise it is "soft failed".
if StateResolution.is_authorized_by_auth_events(event) do if StateResolution.is_authorized_by_auth_events(event) do
state_set = StateResolution.resolve(event, false) state_set = StateResolution.resolve(event, false)
if StateResolution.is_authorized(event, state_set) do if StateResolution.is_authorized(event, state_set) do
if StateResolution.is_authorized(event, current_state_set) do
# TODO: Assume the event is a forward extremity, should check this actually. # TODO: Assume the event is a forward extremity, should check this actually.
Room.update_forward_extremities(event) Room.update_forward_extremities(event)
{:ok, event} = Repo.insert(event) {:ok, event} = Repo.insert(event)
state_set = StateResolution.resolve_forward_extremities(event)
{:ok, state_set} {:ok, state_set}
else
{:error, :soft_failed}
end
else else
{:error, :rejected} {:error, :rejected}
end end

View file

@ -1,7 +1,9 @@
defmodule MatrixServer.StateResolution do defmodule MatrixServer.StateResolution do
import Ecto.Query import Ecto.Query
alias MatrixServer.{Repo, Event} alias MatrixServer.{Repo, Event, Room}
def resolve(event), do: resolve(event, true)
def resolve(%Event{room_id: room_id} = event, apply_state) do def resolve(%Event{room_id: room_id} = event, apply_state) do
room_events = room_events =
@ -322,6 +324,23 @@ defmodule MatrixServer.StateResolution do
is_authorized(event, state_set) is_authorized(event, state_set)
end end
def resolve_forward_extremities(%Event{room_id: room_id}) do
room_events =
Event
|> where([e], e.room_id == ^room_id)
|> select([e], {e.event_id, e})
|> Repo.all()
|> Enum.into(%{})
Event
|> where([e], e.room_id == ^room_id)
|> join(:inner, [e], r in Room, on: e.room_id == r.id)
|> where([e, r], e.event_id == fragment("ANY(?)", r.forward_extremities))
|> Repo.all()
|> Enum.map(&resolve/1)
|> do_resolve(room_events)
end
def testing do def testing do
%Event{content: content} = event = Event.power_levels("room1", "charlie") %Event{content: content} = event = Event.power_levels("room1", "charlie")
event = %Event{event | content: %{content | "ban" => 0}} event = %Event{event | content: %{content | "ban" => 0}}

View file

@ -0,0 +1,9 @@
defmodule MatrixServer.Repo.Migrations.AddStateToRoom do
use Ecto.Migration
def change do
alter table(:rooms) do
add :state, :map, default: %{}, null: false
end
end
end