Add function to calculate content hash of an event
Add function to redact an event
This commit is contained in:
parent
1a5b66a3d7
commit
0c40c26bca
3 changed files with 108 additions and 1 deletions
|
@ -47,4 +47,11 @@ defmodule MatrixServer do
|
||||||
end)
|
end)
|
||||||
|> is_boolean()
|
|> is_boolean()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# https://matrix.org/docs/spec/appendices#unpadded-base64
|
||||||
|
def unpadded_base64(data) do
|
||||||
|
data
|
||||||
|
|> Base.encode64()
|
||||||
|
|> String.trim_trailing("=")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,8 +3,9 @@ defmodule MatrixServer.Event do
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
alias MatrixServer.{Repo, Room, Event, Account}
|
alias MatrixServer.{Repo, Room, Event, Account, OrderedMap}
|
||||||
|
|
||||||
|
@schema_meta_fields [:__meta__]
|
||||||
@primary_key {:event_id, :string, []}
|
@primary_key {:event_id, :string, []}
|
||||||
schema "events" do
|
schema "events" do
|
||||||
field :type, :string
|
field :type, :string
|
||||||
|
@ -268,4 +269,76 @@ defmodule MatrixServer.Event do
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def calculate_content_hash(event) do
|
||||||
|
result =
|
||||||
|
event
|
||||||
|
|> to_map()
|
||||||
|
|> Map.drop([:unsigned, :signature, :hashes])
|
||||||
|
|> OrderedMap.from_map()
|
||||||
|
|> Jason.encode()
|
||||||
|
|
||||||
|
case result do
|
||||||
|
{:ok, json} ->
|
||||||
|
:crypto.hash(:sha256, json)
|
||||||
|
|> MatrixServer.unpadded_base64()
|
||||||
|
|
||||||
|
error ->
|
||||||
|
error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def redact(%Event{type: type, content: content} = event) do
|
||||||
|
redacted_event =
|
||||||
|
event
|
||||||
|
|> to_map()
|
||||||
|
|> Map.take([
|
||||||
|
:event_id,
|
||||||
|
:type,
|
||||||
|
:room_id,
|
||||||
|
:sender,
|
||||||
|
:state_key,
|
||||||
|
:content,
|
||||||
|
:hashes,
|
||||||
|
:signatures,
|
||||||
|
:depth,
|
||||||
|
:prev_events,
|
||||||
|
:prev_state,
|
||||||
|
:auth_events,
|
||||||
|
:origin,
|
||||||
|
:origin_server_ts,
|
||||||
|
:membership
|
||||||
|
])
|
||||||
|
|
||||||
|
%{redacted_event | content: redact_content(type, content)}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp redact_content("m.room.member", content), do: Map.take(["membership"])
|
||||||
|
defp redact_content("m.room.create", content), do: Map.take(["creator"])
|
||||||
|
defp redact_content("m.room.join_rules", content), do: Map.take(["join_rule"])
|
||||||
|
defp redact_content("m.room.aliases", content), do: Map.take(["aliases"])
|
||||||
|
defp redact_content("m.room.history_visibility", content), do: Map.take(["history_visibility"])
|
||||||
|
|
||||||
|
defp redact_content("m.room.power_levels", content),
|
||||||
|
do:
|
||||||
|
Map.take([
|
||||||
|
"ban",
|
||||||
|
"events",
|
||||||
|
"events_default",
|
||||||
|
"kick",
|
||||||
|
"redact",
|
||||||
|
"state_default",
|
||||||
|
"users",
|
||||||
|
"users_default"
|
||||||
|
])
|
||||||
|
|
||||||
|
# https://stackoverflow.com/questions/41523762/41671211
|
||||||
|
def to_map(event) do
|
||||||
|
association_fields = event.__struct__.__schema__(:associations)
|
||||||
|
waste_fields = association_fields ++ @schema_meta_fields
|
||||||
|
|
||||||
|
event
|
||||||
|
|> Map.from_struct()
|
||||||
|
|> Map.drop(waste_fields)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
27
lib/matrix_server/ordered_map.ex
Normal file
27
lib/matrix_server/ordered_map.ex
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# https://github.com/michalmuskala/jason/issues/69
|
||||||
|
defmodule MatrixServer.OrderedMap do
|
||||||
|
alias MatrixServer.OrderedMap
|
||||||
|
|
||||||
|
defstruct pairs: []
|
||||||
|
|
||||||
|
defimpl Jason.Encoder, for: OrderedMap do
|
||||||
|
def encode(%{pairs: pairs}, opts) do
|
||||||
|
Jason.Encode.keyword(pairs, opts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def from_map(map) do
|
||||||
|
pairs =
|
||||||
|
map
|
||||||
|
|> Enum.map(fn
|
||||||
|
{k, v} when is_map(v) ->
|
||||||
|
{k, from_map(v)}
|
||||||
|
|
||||||
|
x ->
|
||||||
|
x
|
||||||
|
end)
|
||||||
|
|> Enum.sort()
|
||||||
|
|
||||||
|
%OrderedMap{pairs: pairs}
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue