This commit is contained in:
Maksim Pechnikov 2020-11-25 16:44:11 +03:00
parent 66f411fba0
commit fb72f2034a
2 changed files with 113 additions and 237 deletions

View file

@ -12,6 +12,26 @@ defmodule Pleroma.ModerationLog do
import Ecto.Query import Ecto.Query
@type t :: %__MODULE__{}
@type log_subject :: Activity.t() | User.t() | list(User.t())
@type log_params :: %{
required(:actor) => User.t(),
required(:action) => String.t(),
optional(:subject) => log_subject(),
optional(:subject_actor) => User.t(),
optional(:subject_id) => String.t(),
optional(:subjects) => list(User.t()),
optional(:permission) => String.t(),
optional(:text) => String.t(),
optional(:sensitive) => String.t(),
optional(:visibility) => String.t(),
optional(:followed) => User.t(),
optional(:follower) => User.t(),
optional(:nicknames) => list(String.t()),
optional(:tags) => list(String.t()),
optional(:target) => String.t()
}
schema "moderation_log" do schema "moderation_log" do
field(:data, :map) field(:data, :map)
@ -90,212 +110,105 @@ defp parse_datetime(datetime) do
parsed_datetime parsed_datetime
end end
@spec insert_log(%{actor: User, subject: [User], action: String.t(), permission: String.t()}) :: defp prepare_log_data(%{actor: actor, action: action} = attrs) do
{:ok, ModerationLog} | {:error, any} %{
def insert_log(%{ "actor" => user_to_map(actor),
actor: %User{} = actor, "action" => action,
subject: subjects, "message" => ""
action: action,
permission: permission
}) do
%ModerationLog{
data: %{
"actor" => user_to_map(actor),
"subject" => user_to_map(subjects),
"action" => action,
"permission" => permission,
"message" => ""
}
} }
|> insert_log_entry_with_message() |> Pleroma.Maps.put_if_present("subject_actor", user_to_map(attrs[:subject_actor]))
end end
@spec insert_log(%{actor: User, subject: User, action: String.t()}) :: defp prepare_log_data(attrs), do: attrs
{:ok, ModerationLog} | {:error, any}
def insert_log( @spec insert_log(log_params()) :: {:ok, ModerationLog} | {:error, any}
%{ def insert_log(%{actor: %User{}, subject: subjects, permission: permission} = attrs) do
actor: %User{} = actor, data =
action: "report_update", attrs
subject: %Activity{data: %{"type" => "Flag"}} = subject |> prepare_log_data
} = attrs |> Map.merge(%{"subject" => user_to_map(subjects), "permission" => permission})
) do
%ModerationLog{ insert_log_entry_with_message(%ModerationLog{data: data})
data: %{ end
"actor" => user_to_map(actor),
"action" => "report_update", def insert_log(%{actor: %User{}, action: action, subject: %Activity{} = subject} = attrs)
"subject" => report_to_map(subject), when action in ["report_note_delete", "report_update", "report_note"] do
"subject_actor" => user_to_map(attrs[:subject_actor]), data =
"message" => "" attrs
} |> prepare_log_data
} |> Pleroma.Maps.put_if_present("text", attrs[:text])
|> insert_log_entry_with_message() |> Map.merge(%{"subject" => report_to_map(subject)})
insert_log_entry_with_message(%ModerationLog{data: data})
end end
@spec insert_log(%{actor: User, subject: Activity, action: String.t(), text: String.t()}) ::
{:ok, ModerationLog} | {:error, any}
def insert_log( def insert_log(
%{ %{
actor: %User{} = actor, actor: %User{},
action: "report_note", action: action,
subject: %Activity{} = subject, subject: %Activity{} = subject,
text: text sensitive: sensitive,
visibility: visibility
} = attrs } = attrs
) do )
%ModerationLog{ when action == "status_update" do
data: %{ data =
"actor" => user_to_map(actor), attrs
"action" => "report_note", |> prepare_log_data
"subject" => report_to_map(subject), |> Map.merge(%{
"subject_actor" => user_to_map(attrs[:subject_actor]),
"text" => text
}
}
|> insert_log_entry_with_message()
end
@spec insert_log(%{actor: User, subject: Activity, action: String.t(), text: String.t()}) ::
{:ok, ModerationLog} | {:error, any}
def insert_log(
%{
actor: %User{} = actor,
action: "report_note_delete",
subject: %Activity{} = subject,
text: text
} = attrs
) do
%ModerationLog{
data: %{
"actor" => user_to_map(actor),
"action" => "report_note_delete",
"subject" => report_to_map(subject),
"subject_actor" => user_to_map(attrs[:subject_actor]),
"text" => text
}
}
|> insert_log_entry_with_message()
end
@spec insert_log(%{
actor: User,
subject: Activity,
action: String.t(),
sensitive: String.t(),
visibility: String.t()
}) :: {:ok, ModerationLog} | {:error, any}
def insert_log(%{
actor: %User{} = actor,
action: "status_update",
subject: %Activity{} = subject,
sensitive: sensitive,
visibility: visibility
}) do
%ModerationLog{
data: %{
"actor" => user_to_map(actor),
"action" => "status_update",
"subject" => status_to_map(subject), "subject" => status_to_map(subject),
"sensitive" => sensitive, "sensitive" => sensitive,
"visibility" => visibility, "visibility" => visibility
"message" => "" })
}
} insert_log_entry_with_message(%ModerationLog{data: data})
|> insert_log_entry_with_message()
end end
@spec insert_log(%{actor: User, action: String.t(), subject_id: String.t()}) :: def insert_log(%{actor: %User{}, action: action, subject_id: subject_id} = attrs)
{:ok, ModerationLog} | {:error, any} when action == "status_delete" do
def insert_log(%{ data =
actor: %User{} = actor, attrs
action: "status_delete", |> prepare_log_data
subject_id: subject_id |> Map.merge(%{"subject_id" => subject_id})
}) do
%ModerationLog{ insert_log_entry_with_message(%ModerationLog{data: data})
data: %{
"actor" => user_to_map(actor),
"action" => "status_delete",
"subject_id" => subject_id,
"message" => ""
}
}
|> insert_log_entry_with_message()
end end
@spec insert_log(%{actor: User, subject: User, action: String.t()}) :: def insert_log(%{actor: %User{}, subject: subject, action: _action} = attrs) do
{:ok, ModerationLog} | {:error, any} data =
def insert_log(%{actor: %User{} = actor, subject: subject, action: action}) do attrs
%ModerationLog{ |> prepare_log_data
data: %{ |> Map.merge(%{"subject" => user_to_map(subject)})
"actor" => user_to_map(actor),
"action" => action, insert_log_entry_with_message(%ModerationLog{data: data})
"subject" => user_to_map(subject),
"message" => ""
}
}
|> insert_log_entry_with_message()
end end
@spec insert_log(%{actor: User, subjects: [User], action: String.t()}) :: def insert_log(%{actor: %User{}, subjects: subjects, action: _action} = attrs) do
{:ok, ModerationLog} | {:error, any} data =
def insert_log(%{actor: %User{} = actor, subjects: subjects, action: action}) do attrs
subjects = Enum.map(subjects, &user_to_map/1) |> prepare_log_data
|> Map.merge(%{"subjects" => user_to_map(subjects)})
%ModerationLog{ insert_log_entry_with_message(%ModerationLog{data: data})
data: %{
"actor" => user_to_map(actor),
"action" => action,
"subjects" => subjects,
"message" => ""
}
}
|> insert_log_entry_with_message()
end end
@spec insert_log(%{actor: User, action: String.t(), followed: User, follower: User}) :: def insert_log(
{:ok, ModerationLog} | {:error, any} %{
def insert_log(%{ actor: %User{},
actor: %User{} = actor, followed: %User{} = followed,
followed: %User{} = followed, follower: %User{} = follower,
follower: %User{} = follower, action: action
action: "follow" } = attrs
}) do )
%ModerationLog{ when action in ["unfollow", "follow"] do
data: %{ data =
"actor" => user_to_map(actor), attrs
"action" => "follow", |> prepare_log_data
"followed" => user_to_map(followed), |> Map.merge(%{"followed" => user_to_map(followed), "follower" => user_to_map(follower)})
"follower" => user_to_map(follower),
"message" => "" insert_log_entry_with_message(%ModerationLog{data: data})
}
}
|> insert_log_entry_with_message()
end end
@spec insert_log(%{actor: User, action: String.t(), followed: User, follower: User}) ::
{:ok, ModerationLog} | {:error, any}
def insert_log(%{
actor: %User{} = actor,
followed: %User{} = followed,
follower: %User{} = follower,
action: "unfollow"
}) do
%ModerationLog{
data: %{
"actor" => user_to_map(actor),
"action" => "unfollow",
"followed" => user_to_map(followed),
"follower" => user_to_map(follower),
"message" => ""
}
}
|> insert_log_entry_with_message()
end
@spec insert_log(%{
actor: User,
action: String.t(),
nicknames: [String.t()],
tags: [String.t()]
}) :: {:ok, ModerationLog} | {:error, any}
def insert_log(%{ def insert_log(%{
actor: %User{} = actor, actor: %User{} = actor,
nicknames: nicknames, nicknames: nicknames,
@ -314,27 +227,16 @@ def insert_log(%{
|> insert_log_entry_with_message() |> insert_log_entry_with_message()
end end
@spec insert_log(%{actor: User, action: String.t(), target: String.t()}) :: def insert_log(%{actor: %User{}, action: action, target: target} = attrs)
{:ok, ModerationLog} | {:error, any}
def insert_log(%{
actor: %User{} = actor,
action: action,
target: target
})
when action in ["relay_follow", "relay_unfollow"] do when action in ["relay_follow", "relay_unfollow"] do
%ModerationLog{ data =
data: %{ attrs
"actor" => user_to_map(actor), |> prepare_log_data
"action" => action, |> Map.merge(%{"target" => target})
"target" => target,
"message" => "" insert_log_entry_with_message(%ModerationLog{data: data})
}
}
|> insert_log_entry_with_message()
end end
@spec insert_log(%{actor: User, action: String.t(), subject_id: String.t()}) ::
{:ok, ModerationLog} | {:error, any}
def insert_log(%{actor: %User{} = actor, action: "chat_message_delete", subject_id: subject_id}) do def insert_log(%{actor: %User{} = actor, action: "chat_message_delete", subject_id: subject_id}) do
%ModerationLog{ %ModerationLog{
data: %{ data: %{
@ -367,20 +269,14 @@ defp user_to_map(%User{} = user) do
defp user_to_map(_), do: nil defp user_to_map(_), do: nil
defp report_to_map(%Activity{} = report) do defp report_to_map(%Activity{} = report) do
%{ %{"type" => "report", "id" => report.id, "state" => report.data["state"]}
"type" => "report",
"id" => report.id,
"state" => report.data["state"]
}
end end
defp status_to_map(%Activity{} = status) do defp status_to_map(%Activity{} = status) do
%{ %{"type" => "status", "id" => status.id}
"type" => "status",
"id" => status.id
}
end end
@spec get_log_entry_message(ModerationLog.t()) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -392,7 +288,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} made @#{follower_nickname} #{action} @#{followed_nickname}" "@#{actor_nickname} made @#{follower_nickname} #{action} @#{followed_nickname}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -403,7 +298,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} deleted users: #{users_to_nicknames_string(subjects)}" "@#{actor_nickname} deleted users: #{users_to_nicknames_string(subjects)}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -414,7 +308,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} created users: #{users_to_nicknames_string(subjects)}" "@#{actor_nickname} created users: #{users_to_nicknames_string(subjects)}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -425,7 +318,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} activated users: #{users_to_nicknames_string(users)}" "@#{actor_nickname} activated users: #{users_to_nicknames_string(users)}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -436,7 +328,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} deactivated users: #{users_to_nicknames_string(users)}" "@#{actor_nickname} deactivated users: #{users_to_nicknames_string(users)}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -447,7 +338,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} approved users: #{users_to_nicknames_string(users)}" "@#{actor_nickname} approved users: #{users_to_nicknames_string(users)}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -461,7 +351,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} added tags: #{tags_string} to users: #{nicknames_to_string(nicknames)}" "@#{actor_nickname} added tags: #{tags_string} to users: #{nicknames_to_string(nicknames)}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -475,7 +364,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} removed tags: #{tags_string} from users: #{nicknames_to_string(nicknames)}" "@#{actor_nickname} removed tags: #{tags_string} from users: #{nicknames_to_string(nicknames)}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -487,7 +375,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} made #{users_to_nicknames_string(users)} #{permission}" "@#{actor_nickname} made #{users_to_nicknames_string(users)} #{permission}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -499,7 +386,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} revoked #{permission} role from #{users_to_nicknames_string(users)}" "@#{actor_nickname} revoked #{permission} role from #{users_to_nicknames_string(users)}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -510,7 +396,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} followed relay: #{target}" "@#{actor_nickname} followed relay: #{target}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -521,7 +406,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} unfollowed relay: #{target}" "@#{actor_nickname} unfollowed relay: #{target}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message( def get_log_entry_message(
%ModerationLog{ %ModerationLog{
data: %{ data: %{
@ -536,7 +420,6 @@ def get_log_entry_message(
" with '#{state}' state" " with '#{state}' state"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message( def get_log_entry_message(
%ModerationLog{ %ModerationLog{
data: %{ data: %{
@ -551,7 +434,6 @@ def get_log_entry_message(
subject_actor_nickname(log, " on user ") subject_actor_nickname(log, " on user ")
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message( def get_log_entry_message(
%ModerationLog{ %ModerationLog{
data: %{ data: %{
@ -566,7 +448,6 @@ def get_log_entry_message(
subject_actor_nickname(log, " on user ") subject_actor_nickname(log, " on user ")
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -579,7 +460,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} updated status ##{subject_id}, set visibility: '#{visibility}'" "@#{actor_nickname} updated status ##{subject_id}, set visibility: '#{visibility}'"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -592,7 +472,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} updated status ##{subject_id}, set sensitive: '#{sensitive}'" "@#{actor_nickname} updated status ##{subject_id}, set sensitive: '#{sensitive}'"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -607,7 +486,6 @@ def get_log_entry_message(%ModerationLog{
}'" }'"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -618,7 +496,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} deleted status ##{subject_id}" "@#{actor_nickname} deleted status ##{subject_id}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -629,7 +506,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} forced password reset for users: #{users_to_nicknames_string(subjects)}" "@#{actor_nickname} forced password reset for users: #{users_to_nicknames_string(subjects)}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -640,7 +516,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} confirmed email for users: #{users_to_nicknames_string(subjects)}" "@#{actor_nickname} confirmed email for users: #{users_to_nicknames_string(subjects)}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -653,7 +528,6 @@ def get_log_entry_message(%ModerationLog{
}" }"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},
@ -664,7 +538,6 @@ def get_log_entry_message(%ModerationLog{
"@#{actor_nickname} updated users: #{users_to_nicknames_string(subjects)}" "@#{actor_nickname} updated users: #{users_to_nicknames_string(subjects)}"
end end
@spec get_log_entry_message(ModerationLog) :: String.t()
def get_log_entry_message(%ModerationLog{ def get_log_entry_message(%ModerationLog{
data: %{ data: %{
"actor" => %{"nickname" => actor_nickname}, "actor" => %{"nickname" => actor_nickname},

View file

@ -182,12 +182,14 @@ test "logging relay unfollow", %{moderator: moderator} do
end end
test "logging report update", %{moderator: moderator} do test "logging report update", %{moderator: moderator} do
user = insert(:user)
report = %Activity{ report = %Activity{
id: "9m9I1F4p8ftrTP6QTI", id: "9m9I1F4p8ftrTP6QTI",
data: %{ data: %{
"type" => "Flag", "type" => "Flag",
"state" => "resolved", "state" => "resolved",
"actor" => "http://localhost:4000/users/max" "actor" => user.ap_id
} }
} }
@ -195,13 +197,14 @@ test "logging report update", %{moderator: moderator} do
ModerationLog.insert_log(%{ ModerationLog.insert_log(%{
actor: moderator, actor: moderator,
action: "report_update", action: "report_update",
subject: report subject: report,
subject_actor: user
}) })
log = Repo.one(ModerationLog) log = Repo.one(ModerationLog)
assert log.data["message"] == assert log.data["message"] ==
"@#{moderator.nickname} updated report ##{report.id} with 'resolved' state" "@#{moderator.nickname} updated report ##{report.id} (on user @#{user.nickname}) with 'resolved' state"
end end
test "logging report response", %{moderator: moderator} do test "logging report response", %{moderator: moderator} do