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)
|
||||
|> is_boolean()
|
||||
end
|
||||
|
||||
# https://matrix.org/docs/spec/appendices#unpadded-base64
|
||||
def unpadded_base64(data) do
|
||||
data
|
||||
|> Base.encode64()
|
||||
|> String.trim_trailing("=")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,8 +3,9 @@ defmodule MatrixServer.Event do
|
|||
|
||||
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, []}
|
||||
schema "events" do
|
||||
field :type, :string
|
||||
|
@ -268,4 +269,76 @@ defmodule MatrixServer.Event do
|
|||
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
|
||||
|
|
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