Add function to query whether server participates in a room

Move from integer timestamps to datetimes
This commit is contained in:
Pim Kunis 2021-08-16 19:30:47 +02:00
parent 5d75244bc0
commit 02edff90e7
7 changed files with 65 additions and 20 deletions

View file

@ -126,4 +126,12 @@ defmodule MatrixServer do
ArgumentError -> false ArgumentError -> false
end end
end end
def min_datetime(datetime1, datetime2) do
if DateTime.compare(datetime1, datetime2) == :gt do
datetime2
else
datetime1
end
end
end end

View file

@ -46,6 +46,10 @@ defmodule MatrixServer.RoomServer do
GenServer.call(pid, {:create_room, account, input}) GenServer.call(pid, {:create_room, account, input})
end end
def server_in_room(pid, domain) do
GenServer.call(pid, {:server_in_room, domain})
end
### Implementation ### Implementation
@impl true @impl true
@ -120,6 +124,18 @@ defmodule MatrixServer.RoomServer do
end end
end end
def handle_call({:server_in_room, domain}, _from, %{state_set: state_set} = state) do
result = Enum.any?(state_set, fn
{{"m.room.member", user_id}, %Event{content: %{"membership" => "join"}}} ->
MatrixServer.get_domain(user_id) == domain
_ ->
false
end)
{:reply, result, state}
end
# TODO: trusted_private_chat: # TODO: trusted_private_chat:
# All invitees are given the same power level as the room creator. # 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 defp room_creation_preset(account, nil, %Room{visibility: visibility} = room, auth_events) do

View file

@ -8,7 +8,7 @@ defmodule MatrixServer.Event do
@primary_key {:event_id, :string, []} @primary_key {:event_id, :string, []}
schema "events" do schema "events" do
field :type, :string field :type, :string
field :origin_server_ts, :integer field :origin_server_ts, :utc_datetime_usec
field :state_key, :string field :state_key, :string
field :sender, :string field :sender, :string
field :content, :map field :content, :map
@ -27,7 +27,7 @@ defmodule MatrixServer.Event do
room_id: room_id, room_id: room_id,
sender: MatrixServer.get_mxid(localpart), sender: MatrixServer.get_mxid(localpart),
event_id: generate_event_id(), event_id: generate_event_id(),
origin_server_ts: System.os_time(:millisecond), origin_server_ts: DateTime.utc_now(),
prev_events: [], prev_events: [],
auth_events: [] auth_events: []
} }

View file

@ -10,7 +10,7 @@ defmodule MatrixServer.ServerKeyInfo do
@primary_key {:server_name, :string, []} @primary_key {:server_name, :string, []}
schema "server_key_info" do schema "server_key_info" do
field :valid_until, :integer field :valid_until, :utc_datetime
has_many :signing_keys, SigningKey, foreign_key: :server_name has_many :signing_keys, SigningKey, foreign_key: :server_name
end end
@ -34,31 +34,33 @@ defmodule MatrixServer.ServerKeyInfo do
defp refresh_signing_keys(server_name) do defp refresh_signing_keys(server_name) do
# TODO: Handle expired keys. # TODO: Handle expired keys.
in_a_week = System.os_time(:millisecond) + 1000 * 60 * 60 * 24 * 7 in_a_week = DateTime.utc_now() |> DateTime.add(60 * 60 * 24 * 7, :second)
client = HTTPClient.client(server_name) client = HTTPClient.client(server_name)
with {:ok, with {:ok,
%GetSigningKeys{ %GetSigningKeys{
server_name: server_name, server_name: server_name,
verify_keys: verify_keys, verify_keys: verify_keys,
valid_until_ts: valid_until valid_until_ts: valid_until_ts
}} <- }} <- HTTPClient.get_signing_keys(client),
HTTPClient.get_signing_keys(client) do {:ok, valid_until} <- DateTime.from_unix(valid_until_ts) do
signing_keys = signing_keys =
Enum.map(verify_keys, fn {key_id, %{"key" => key}} -> Enum.map(verify_keys, fn {key_id, %{"key" => key}} ->
[server_name: server_name, signing_key_id: key_id, signing_key: key] [server_name: server_name, signing_key_id: key_id, signing_key: key]
end) end)
# Always check every week to prevent misuse. # Always check every week to prevent misuse.
ski = %ServerKeyInfo{server_name: server_name, valid_until: min(valid_until, in_a_week)} ski = %ServerKeyInfo{
server_name: server_name,
valid_until: MatrixServer.min_datetime(in_a_week, valid_until)
}
case upsert_multi(server_name, ski, signing_keys) |> Repo.transaction() do case upsert_multi(server_name, ski, signing_keys) |> Repo.transaction() do
{:ok, %{new_ski: ski}} -> {:ok, ski} {:ok, %{new_ski: ski}} -> {:ok, ski}
{:error, _} -> :error {:error, _} -> :error
end end
else else
:error -> _ -> :error
:error
end end
end end

View file

@ -5,8 +5,6 @@ defmodule MatrixServerWeb.Federation.KeyController do
alias MatrixServer.KeyServer alias MatrixServer.KeyServer
@key_valid_time_ms 1000 * 60 * 24 * 30
def get_signing_keys(conn, _params) do def get_signing_keys(conn, _params) do
keys = keys =
KeyServer.get_own_signing_keys() KeyServer.get_own_signing_keys()
@ -14,11 +12,15 @@ defmodule MatrixServerWeb.Federation.KeyController do
{key_id, %{"key" => key}} {key_id, %{"key" => key}}
end) end)
# TODO: Consider using TimeX.
# Valid for one month.
valid_until = DateTime.utc_now() |> DateTime.add(60 * 60 * 24 * 30, :second)
data = %{ data = %{
server_name: MatrixServer.server_name(), server_name: MatrixServer.server_name(),
verify_keys: keys, verify_keys: keys,
old_verify_keys: %{}, old_verify_keys: %{},
valid_until_ts: System.os_time(:millisecond) + @key_valid_time_ms valid_until_ts: valid_until
} }
case KeyServer.sign_object(data) do case KeyServer.sign_object(data) do

View file

@ -0,0 +1,15 @@
defmodule MatrixServer.Repo.Migrations.ChangeTimestampsToDatetime do
use Ecto.Migration
def change do
alter table(:events) do
remove :origin_server_ts, :integer, null: false
add :origin_server_ts, :utc_datetime_usec, null: false
end
alter table(:server_key_info) do
remove :valid_until, :bigint, default: 0, null: false
add :valid_until, :utc_datetime_usec, null: false
end
end
end

View file

@ -1,5 +1,7 @@
alias MatrixServer.{Repo, Room, Event, Account, Device} alias MatrixServer.{Repo, Room, Event, Account, Device}
timestamp = fn n -> DateTime.from_unix!(n, :microsecond) end
Repo.insert!(%Account{ Repo.insert!(%Account{
localpart: "chuck", localpart: "chuck",
password_hash: Bcrypt.hash_pwd_salt("sneed") password_hash: Bcrypt.hash_pwd_salt("sneed")
@ -40,7 +42,7 @@ room =
Repo.insert!( Repo.insert!(
Event.create_room(room, alice, "v1") Event.create_room(room, alice, "v1")
|> Map.put(:origin_server_ts, 0) |> Map.put(:origin_server_ts, timestamp.(0))
|> Map.put(:event_id, "create") |> Map.put(:event_id, "create")
) )
@ -48,7 +50,7 @@ Repo.insert!(
Event.join(room, alice) Event.join(room, alice)
|> Map.put(:prev_events, ["create"]) |> Map.put(:prev_events, ["create"])
|> Map.put(:auth_events, ["create"]) |> Map.put(:auth_events, ["create"])
|> Map.put(:origin_server_ts, 1) |> Map.put(:origin_server_ts, timestamp.(1))
|> Map.put(:event_id, "join_alice") |> Map.put(:event_id, "join_alice")
) )
@ -56,7 +58,7 @@ Repo.insert!(
Event.join(room, bob) Event.join(room, bob)
|> Map.put(:prev_events, ["join_alice"]) |> Map.put(:prev_events, ["join_alice"])
|> Map.put(:auth_events, ["create"]) |> Map.put(:auth_events, ["create"])
|> Map.put(:origin_server_ts, 2) |> Map.put(:origin_server_ts, timestamp.(2))
|> Map.put(:event_id, "join_bob") |> Map.put(:event_id, "join_bob")
) )
@ -64,7 +66,7 @@ Repo.insert!(
Event.join(room, charlie) Event.join(room, charlie)
|> Map.put(:prev_events, ["join_bob"]) |> Map.put(:prev_events, ["join_bob"])
|> Map.put(:auth_events, ["create"]) |> Map.put(:auth_events, ["create"])
|> Map.put(:origin_server_ts, 3) |> Map.put(:origin_server_ts, timestamp.(3))
|> Map.put(:event_id, "join_charlie") |> Map.put(:event_id, "join_charlie")
) )
@ -75,7 +77,7 @@ Repo.insert!(
event event
|> Map.put(:prev_events, ["join_alice"]) |> Map.put(:prev_events, ["join_alice"])
|> Map.put(:auth_events, ["create", "join_alice"]) |> Map.put(:auth_events, ["create", "join_alice"])
|> Map.put(:origin_server_ts, 4) |> Map.put(:origin_server_ts, timestamp.(4))
|> Map.put(:event_id, "a") |> Map.put(:event_id, "a")
) )
@ -90,7 +92,7 @@ Repo.insert!(
event event
|> Map.put(:prev_events, ["a"]) |> Map.put(:prev_events, ["a"])
|> Map.put(:auth_events, ["create", "join_bob", "a"]) |> Map.put(:auth_events, ["create", "join_bob", "a"])
|> Map.put(:origin_server_ts, 5) |> Map.put(:origin_server_ts, timestamp.(5))
|> Map.put(:event_id, "b") |> Map.put(:event_id, "b")
) )
@ -98,6 +100,6 @@ Repo.insert!(
Event.topic(room, alice, "sneed") Event.topic(room, alice, "sneed")
|> Map.put(:prev_events, ["a"]) |> Map.put(:prev_events, ["a"])
|> Map.put(:auth_events, ["create", "join_alice", "a"]) |> Map.put(:auth_events, ["create", "join_alice", "a"])
|> Map.put(:origin_server_ts, 5) |> Map.put(:origin_server_ts, timestamp.(5))
|> Map.put(:event_id, "fork") |> Map.put(:event_id, "fork")
) )