Add validation of auth events for events
This commit is contained in:
parent
b9156ed8b3
commit
dd7000e069
2 changed files with 54 additions and 11 deletions
|
@ -1,7 +1,9 @@
|
||||||
defmodule MatrixServer.RoomServer do
|
defmodule MatrixServer.RoomServer do
|
||||||
use GenServer
|
use GenServer
|
||||||
|
|
||||||
alias MatrixServer.{Repo, Room, Event, Account}
|
import Ecto.Query
|
||||||
|
|
||||||
|
alias MatrixServer.{Repo, Room, Event, Account, StateResolution}
|
||||||
alias MatrixServerWeb.API.CreateRoom
|
alias MatrixServerWeb.API.CreateRoom
|
||||||
|
|
||||||
@registry MatrixServer.RoomServer.Registry
|
@registry MatrixServer.RoomServer.Registry
|
||||||
|
@ -43,11 +45,33 @@ defmodule MatrixServer.RoomServer do
|
||||||
%CreateRoom{room_version: room_version},
|
%CreateRoom{room_version: room_version},
|
||||||
room_id
|
room_id
|
||||||
) do
|
) do
|
||||||
state_set =
|
create_room_event = Event.create_room(room_id, MatrixServer.get_mxid(localpart), room_version)
|
||||||
Event.create_room(room_id, MatrixServer.get_mxid(localpart), room_version)
|
verify_event(create_room_event)
|
||||||
|> Repo.insert!()
|
|> IO.inspect()
|
||||||
|> MatrixServer.StateResolution.resolve(true)
|
|
||||||
|
|
||||||
{:ok, state_set}
|
{:ok, %{}}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp verify_event(%Event{auth_events: auth_event_ids} = event) do
|
||||||
|
# Check the following things:
|
||||||
|
# 1. TODO: Is a valid event, 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.
|
||||||
|
# 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.
|
||||||
|
# 6. TODO: 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
|
||||||
|
auth_events =
|
||||||
|
Event
|
||||||
|
|> where([e], e.event_id in ^auth_event_ids)
|
||||||
|
|> select([e], {e.event_id, e})
|
||||||
|
|> Repo.all()
|
||||||
|
|> Enum.into(%{})
|
||||||
|
# TODO: make the state set a mapping to Event struct.
|
||||||
|
state_set = StateResolution.resolve(event, false)
|
||||||
|
StateResolution.is_authorized(event, state_set, auth_events)
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,7 @@ defmodule MatrixServer.StateResolution do
|
||||||
|> Map.put(:auth_events, ["create", "join_charlie", "b"])
|
|> Map.put(:auth_events, ["create", "join_charlie", "b"])
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve(%Event{room_id: room_id} = event, apply_state \\ false) do
|
def resolve(%Event{room_id: room_id} = event, apply_state) do
|
||||||
room_events =
|
room_events =
|
||||||
Event
|
Event
|
||||||
|> where([e], e.room_id == ^room_id)
|
|> where([e], e.room_id == ^room_id)
|
||||||
|
@ -31,7 +31,7 @@ defmodule MatrixServer.StateResolution do
|
||||||
state_sets =
|
state_sets =
|
||||||
prev_event_ids
|
prev_event_ids
|
||||||
|> Enum.map(&room_events[&1])
|
|> Enum.map(&room_events[&1])
|
||||||
|> Enum.map(&resolve(&1, room_events))
|
|> Enum.map(&resolve(&1, room_events, apply_state))
|
||||||
|
|
||||||
resolved_state = do_resolve(state_sets, room_events)
|
resolved_state = do_resolve(state_sets, room_events)
|
||||||
# TODO: check if state event
|
# TODO: check if state event
|
||||||
|
@ -55,6 +55,7 @@ defmodule MatrixServer.StateResolution do
|
||||||
end
|
end
|
||||||
|
|
||||||
def do_resolve(state_sets, room_events, unconflicted_state_map, conflicted_state_set) do
|
def do_resolve(state_sets, room_events, unconflicted_state_map, conflicted_state_set) do
|
||||||
|
# TODO: make the state set a hashmap instead of a set.
|
||||||
full_conflicted_set =
|
full_conflicted_set =
|
||||||
MapSet.union(conflicted_state_set, auth_difference(state_sets, room_events))
|
MapSet.union(conflicted_state_set, auth_difference(state_sets, room_events))
|
||||||
|
|
||||||
|
@ -82,8 +83,8 @@ defmodule MatrixServer.StateResolution do
|
||||||
|
|
||||||
conflicted_control_events_with_auth_ids
|
conflicted_control_events_with_auth_ids
|
||||||
|> MapSet.difference(full_conflicted_set)
|
|> MapSet.difference(full_conflicted_set)
|
||||||
|> Enum.map(&room_events[&1])
|
|
||||||
|> Enum.sort(mainline_order(resolved_power_levels, room_events))
|
|> Enum.sort(mainline_order(resolved_power_levels, room_events))
|
||||||
|
|> Enum.map(&room_events[&1])
|
||||||
|> iterative_auth_checks(partial_resolved_state, room_events)
|
|> iterative_auth_checks(partial_resolved_state, room_events)
|
||||||
|> Map.merge(unconflicted_state_map)
|
|> Map.merge(unconflicted_state_map)
|
||||||
end
|
end
|
||||||
|
@ -205,8 +206,9 @@ defmodule MatrixServer.StateResolution do
|
||||||
|> Enum.with_index()
|
|> Enum.with_index()
|
||||||
|> Enum.into(%{})
|
|> Enum.into(%{})
|
||||||
|
|
||||||
fn %Event{origin_server_ts: timestamp1, event_id: event_id1} = event1,
|
fn event_id1, event_id2 ->
|
||||||
%Event{origin_server_ts: timestamp2, event_id: event_id2} = event2 ->
|
%Event{origin_server_ts: timestamp1} = event1 = room_events[event_id1]
|
||||||
|
%Event{origin_server_ts: timestamp2} = event2 = room_events[event_id2]
|
||||||
mainline_depth1 = get_mainline_depth(mainline_map, event1, room_events)
|
mainline_depth1 = get_mainline_depth(mainline_map, event1, room_events)
|
||||||
mainline_depth2 = get_mainline_depth(mainline_map, event2, room_events)
|
mainline_depth2 = get_mainline_depth(mainline_map, event2, room_events)
|
||||||
|
|
||||||
|
@ -344,4 +346,21 @@ defmodule MatrixServer.StateResolution do
|
||||||
event_id = state_set[{"m.room.create", ""}]
|
event_id = state_set[{"m.room.create", ""}]
|
||||||
room_events[event_id].sender == user
|
room_events[event_id].sender == user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def is_authorized_by_auth_events(%Event{auth_events: auth_event_ids} = event) do
|
||||||
|
# We assume the auth events are validated beforehand.
|
||||||
|
auth_events =
|
||||||
|
Event
|
||||||
|
|> where([e], e.event_id in ^auth_event_ids)
|
||||||
|
|> select([e], {e.event_id, e})
|
||||||
|
|> Repo.all()
|
||||||
|
|> Enum.into(%{})
|
||||||
|
|
||||||
|
# TODO: make the state set a mapping to Event struct.
|
||||||
|
state_set = Enum.reduce(auth_events, %{}, fn {event_id, %Event{type: type, state_key: state_key}}, acc ->
|
||||||
|
Map.put(acc, {type, state_key}, event_id)
|
||||||
|
end)
|
||||||
|
|
||||||
|
is_authorized(event, state_set, auth_events)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue