diff --git a/lib/matrix_server.ex b/lib/matrix_server.ex index 9442f48..d3f085c 100644 --- a/lib/matrix_server.ex +++ b/lib/matrix_server.ex @@ -126,4 +126,12 @@ defmodule MatrixServer do ArgumentError -> false end end + + def min_datetime(datetime1, datetime2) do + if DateTime.compare(datetime1, datetime2) == :gt do + datetime2 + else + datetime1 + end + end end diff --git a/lib/matrix_server/room_server.ex b/lib/matrix_server/room_server.ex index b1def28..78d2ee0 100644 --- a/lib/matrix_server/room_server.ex +++ b/lib/matrix_server/room_server.ex @@ -46,6 +46,10 @@ defmodule MatrixServer.RoomServer do GenServer.call(pid, {:create_room, account, input}) end + def server_in_room(pid, domain) do + GenServer.call(pid, {:server_in_room, domain}) + end + ### Implementation @impl true @@ -120,6 +124,18 @@ defmodule MatrixServer.RoomServer do 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: # 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 diff --git a/lib/matrix_server/schema/event.ex b/lib/matrix_server/schema/event.ex index e1ab0b2..f95349a 100644 --- a/lib/matrix_server/schema/event.ex +++ b/lib/matrix_server/schema/event.ex @@ -8,7 +8,7 @@ defmodule MatrixServer.Event do @primary_key {:event_id, :string, []} schema "events" do field :type, :string - field :origin_server_ts, :integer + field :origin_server_ts, :utc_datetime_usec field :state_key, :string field :sender, :string field :content, :map @@ -27,7 +27,7 @@ defmodule MatrixServer.Event do room_id: room_id, sender: MatrixServer.get_mxid(localpart), event_id: generate_event_id(), - origin_server_ts: System.os_time(:millisecond), + origin_server_ts: DateTime.utc_now(), prev_events: [], auth_events: [] } diff --git a/lib/matrix_server/schema/server_key_info.ex b/lib/matrix_server/schema/server_key_info.ex index f064878..9248697 100644 --- a/lib/matrix_server/schema/server_key_info.ex +++ b/lib/matrix_server/schema/server_key_info.ex @@ -10,7 +10,7 @@ defmodule MatrixServer.ServerKeyInfo do @primary_key {:server_name, :string, []} schema "server_key_info" do - field :valid_until, :integer + field :valid_until, :utc_datetime has_many :signing_keys, SigningKey, foreign_key: :server_name end @@ -34,31 +34,33 @@ defmodule MatrixServer.ServerKeyInfo do defp refresh_signing_keys(server_name) do # 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) with {:ok, %GetSigningKeys{ server_name: server_name, verify_keys: verify_keys, - valid_until_ts: valid_until - }} <- - HTTPClient.get_signing_keys(client) do + valid_until_ts: valid_until_ts + }} <- HTTPClient.get_signing_keys(client), + {:ok, valid_until} <- DateTime.from_unix(valid_until_ts) do signing_keys = Enum.map(verify_keys, fn {key_id, %{"key" => key}} -> [server_name: server_name, signing_key_id: key_id, signing_key: key] end) # 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 {:ok, %{new_ski: ski}} -> {:ok, ski} {:error, _} -> :error end else - :error -> - :error + _ -> :error end end diff --git a/lib/matrix_server_web/federation/controllers/key_controller.ex b/lib/matrix_server_web/federation/controllers/key_controller.ex index 9a2eece..4d14175 100644 --- a/lib/matrix_server_web/federation/controllers/key_controller.ex +++ b/lib/matrix_server_web/federation/controllers/key_controller.ex @@ -5,8 +5,6 @@ defmodule MatrixServerWeb.Federation.KeyController do alias MatrixServer.KeyServer - @key_valid_time_ms 1000 * 60 * 24 * 30 - def get_signing_keys(conn, _params) do keys = KeyServer.get_own_signing_keys() @@ -14,11 +12,15 @@ defmodule MatrixServerWeb.Federation.KeyController do {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: MatrixServer.server_name(), verify_keys: 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 diff --git a/priv/repo/migrations/20210816144214_change_timestamps_to_datetime.exs b/priv/repo/migrations/20210816144214_change_timestamps_to_datetime.exs new file mode 100644 index 0000000..e4e3eae --- /dev/null +++ b/priv/repo/migrations/20210816144214_change_timestamps_to_datetime.exs @@ -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 diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 7b6d604..4e7c0ae 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -1,5 +1,7 @@ alias MatrixServer.{Repo, Room, Event, Account, Device} +timestamp = fn n -> DateTime.from_unix!(n, :microsecond) end + Repo.insert!(%Account{ localpart: "chuck", password_hash: Bcrypt.hash_pwd_salt("sneed") @@ -40,7 +42,7 @@ room = Repo.insert!( Event.create_room(room, alice, "v1") - |> Map.put(:origin_server_ts, 0) + |> Map.put(:origin_server_ts, timestamp.(0)) |> Map.put(:event_id, "create") ) @@ -48,7 +50,7 @@ Repo.insert!( Event.join(room, alice) |> Map.put(:prev_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") ) @@ -56,7 +58,7 @@ Repo.insert!( Event.join(room, bob) |> Map.put(:prev_events, ["join_alice"]) |> Map.put(:auth_events, ["create"]) - |> Map.put(:origin_server_ts, 2) + |> Map.put(:origin_server_ts, timestamp.(2)) |> Map.put(:event_id, "join_bob") ) @@ -64,7 +66,7 @@ Repo.insert!( Event.join(room, charlie) |> Map.put(:prev_events, ["join_bob"]) |> Map.put(:auth_events, ["create"]) - |> Map.put(:origin_server_ts, 3) + |> Map.put(:origin_server_ts, timestamp.(3)) |> Map.put(:event_id, "join_charlie") ) @@ -75,7 +77,7 @@ Repo.insert!( event |> Map.put(:prev_events, ["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") ) @@ -90,7 +92,7 @@ Repo.insert!( event |> Map.put(:prev_events, ["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") ) @@ -98,6 +100,6 @@ Repo.insert!( Event.topic(room, alice, "sneed") |> Map.put(:prev_events, ["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") )