1 defmodule Pleroma.ModerationLog do
5 alias Pleroma.ModerationLog
11 schema "moderation_log" do
17 def get_all(params) do
20 |> maybe_filter_by_date(params)
21 |> maybe_filter_by_user(params)
22 |> maybe_filter_by_search(params)
24 query_with_pagination = base_query |> paginate_query(params)
27 items: Repo.all(query_with_pagination),
28 count: Repo.aggregate(base_query, :count, :id)
32 defp maybe_filter_by_date(query, %{start_date: nil, end_date: nil}), do: query
34 defp maybe_filter_by_date(query, %{start_date: start_date, end_date: nil}) do
36 where: q.inserted_at >= ^parse_datetime(start_date)
40 defp maybe_filter_by_date(query, %{start_date: nil, end_date: end_date}) do
42 where: q.inserted_at <= ^parse_datetime(end_date)
46 defp maybe_filter_by_date(query, %{start_date: start_date, end_date: end_date}) do
48 where: q.inserted_at >= ^parse_datetime(start_date),
49 where: q.inserted_at <= ^parse_datetime(end_date)
53 defp maybe_filter_by_user(query, %{user_id: nil}), do: query
55 defp maybe_filter_by_user(query, %{user_id: user_id}) do
57 where: fragment("(?)->'actor'->>'id' = ?", q.data, ^user_id)
61 defp maybe_filter_by_search(query, %{search: search}) when is_nil(search) or search == "",
64 defp maybe_filter_by_search(query, %{search: search}) do
66 where: fragment("(?)->>'message' ILIKE ?", q.data, ^"%#{search}%")
70 defp paginate_query(query, %{page: page, page_size: page_size}) do
73 offset: ^((page - 1) * page_size)
79 order_by: [desc: q.inserted_at]
83 defp parse_datetime(datetime) do
84 {:ok, parsed_datetime, _} = DateTime.from_iso8601(datetime)
89 @spec insert_log(%{actor: User, subject: [User], action: String.t(), permission: String.t()}) ::
90 {:ok, ModerationLog} | {:error, any}
92 actor: %User{} = actor,
95 permission: permission
99 "actor" => user_to_map(actor),
100 "subject" => user_to_map(subjects),
102 "permission" => permission,
106 |> insert_log_entry_with_message()
109 @spec insert_log(%{actor: User, subject: User, action: String.t()}) ::
110 {:ok, ModerationLog} | {:error, any}
112 actor: %User{} = actor,
113 action: "report_update",
114 subject: %Activity{data: %{"type" => "Flag"}} = subject
118 "actor" => user_to_map(actor),
119 "action" => "report_update",
120 "subject" => report_to_map(subject),
124 |> insert_log_entry_with_message()
127 @spec insert_log(%{actor: User, subject: Activity, action: String.t(), text: String.t()}) ::
128 {:ok, ModerationLog} | {:error, any}
130 actor: %User{} = actor,
131 action: "report_response",
132 subject: %Activity{} = subject,
137 "actor" => user_to_map(actor),
138 "action" => "report_response",
139 "subject" => report_to_map(subject),
144 |> insert_log_entry_with_message()
151 sensitive: String.t(),
152 visibility: String.t()
153 }) :: {:ok, ModerationLog} | {:error, any}
155 actor: %User{} = actor,
156 action: "status_update",
157 subject: %Activity{} = subject,
158 sensitive: sensitive,
159 visibility: visibility
163 "actor" => user_to_map(actor),
164 "action" => "status_update",
165 "subject" => status_to_map(subject),
166 "sensitive" => sensitive,
167 "visibility" => visibility,
171 |> insert_log_entry_with_message()
174 @spec insert_log(%{actor: User, action: String.t(), subject_id: String.t()}) ::
175 {:ok, ModerationLog} | {:error, any}
177 actor: %User{} = actor,
178 action: "status_delete",
179 subject_id: subject_id
183 "actor" => user_to_map(actor),
184 "action" => "status_delete",
185 "subject_id" => subject_id,
189 |> insert_log_entry_with_message()
192 @spec insert_log(%{actor: User, subject: User, action: String.t()}) ::
193 {:ok, ModerationLog} | {:error, any}
194 def insert_log(%{actor: %User{} = actor, subject: subject, action: action}) do
197 "actor" => user_to_map(actor),
199 "subject" => user_to_map(subject),
203 |> insert_log_entry_with_message()
206 @spec insert_log(%{actor: User, subjects: [User], action: String.t()}) ::
207 {:ok, ModerationLog} | {:error, any}
208 def insert_log(%{actor: %User{} = actor, subjects: subjects, action: action}) do
209 subjects = Enum.map(subjects, &user_to_map/1)
213 "actor" => user_to_map(actor),
215 "subjects" => subjects,
219 |> insert_log_entry_with_message()
222 @spec insert_log(%{actor: User, action: String.t(), followed: User, follower: User}) ::
223 {:ok, ModerationLog} | {:error, any}
225 actor: %User{} = actor,
226 followed: %User{} = followed,
227 follower: %User{} = follower,
232 "actor" => user_to_map(actor),
233 "action" => "follow",
234 "followed" => user_to_map(followed),
235 "follower" => user_to_map(follower),
239 |> insert_log_entry_with_message()
242 @spec insert_log(%{actor: User, action: String.t(), followed: User, follower: User}) ::
243 {:ok, ModerationLog} | {:error, any}
245 actor: %User{} = actor,
246 followed: %User{} = followed,
247 follower: %User{} = follower,
252 "actor" => user_to_map(actor),
253 "action" => "unfollow",
254 "followed" => user_to_map(followed),
255 "follower" => user_to_map(follower),
259 |> insert_log_entry_with_message()
265 nicknames: [String.t()],
267 }) :: {:ok, ModerationLog} | {:error, any}
269 actor: %User{} = actor,
270 nicknames: nicknames,
276 "actor" => user_to_map(actor),
277 "nicknames" => nicknames,
283 |> insert_log_entry_with_message()
286 @spec insert_log(%{actor: User, action: String.t(), target: String.t()}) ::
287 {:ok, ModerationLog} | {:error, any}
289 actor: %User{} = actor,
293 when action in ["relay_follow", "relay_unfollow"] do
296 "actor" => user_to_map(actor),
302 |> insert_log_entry_with_message()
305 @spec insert_log_entry_with_message(ModerationLog) :: {:ok, ModerationLog} | {:error, any}
306 defp insert_log_entry_with_message(entry) do
307 entry.data["message"]
308 |> put_in(get_log_entry_message(entry))
312 defp user_to_map(users) when is_list(users) do
313 users |> Enum.map(&user_to_map/1)
316 defp user_to_map(%User{} = user) do
319 |> Map.take([:id, :nickname])
320 |> Map.new(fn {k, v} -> {Atom.to_string(k), v} end)
321 |> Map.put("type", "user")
324 defp report_to_map(%Activity{} = report) do
328 "state" => report.data["state"]
332 defp status_to_map(%Activity{} = status) do
339 def get_log_entry_message(%ModerationLog{
341 "actor" => %{"nickname" => actor_nickname},
343 "followed" => %{"nickname" => followed_nickname},
344 "follower" => %{"nickname" => follower_nickname}
347 "@#{actor_nickname} made @#{follower_nickname} #{action} @#{followed_nickname}"
350 @spec get_log_entry_message(ModerationLog) :: String.t()
351 def get_log_entry_message(%ModerationLog{
353 "actor" => %{"nickname" => actor_nickname},
354 "action" => "delete",
355 "subject" => subjects
358 "@#{actor_nickname} deleted users: #{users_to_nicknames_string(subjects)}"
361 @spec get_log_entry_message(ModerationLog) :: String.t()
362 def get_log_entry_message(%ModerationLog{
364 "actor" => %{"nickname" => actor_nickname},
365 "action" => "create",
366 "subjects" => subjects
369 "@#{actor_nickname} created users: #{users_to_nicknames_string(subjects)}"
372 @spec get_log_entry_message(ModerationLog) :: String.t()
373 def get_log_entry_message(%ModerationLog{
375 "actor" => %{"nickname" => actor_nickname},
376 "action" => "activate",
380 "@#{actor_nickname} activated users: #{users_to_nicknames_string(users)}"
383 @spec get_log_entry_message(ModerationLog) :: String.t()
384 def get_log_entry_message(%ModerationLog{
386 "actor" => %{"nickname" => actor_nickname},
387 "action" => "deactivate",
391 "@#{actor_nickname} deactivated users: #{users_to_nicknames_string(users)}"
394 @spec get_log_entry_message(ModerationLog) :: String.t()
395 def get_log_entry_message(%ModerationLog{
397 "actor" => %{"nickname" => actor_nickname},
398 "nicknames" => nicknames,
403 tags_string = tags |> Enum.join(", ")
405 "@#{actor_nickname} added tags: #{tags_string} to users: #{nicknames_to_string(nicknames)}"
408 @spec get_log_entry_message(ModerationLog) :: String.t()
409 def get_log_entry_message(%ModerationLog{
411 "actor" => %{"nickname" => actor_nickname},
412 "nicknames" => nicknames,
417 tags_string = tags |> Enum.join(", ")
419 "@#{actor_nickname} removed tags: #{tags_string} from users: #{nicknames_to_string(nicknames)}"
422 @spec get_log_entry_message(ModerationLog) :: String.t()
423 def get_log_entry_message(%ModerationLog{
425 "actor" => %{"nickname" => actor_nickname},
428 "permission" => permission
431 "@#{actor_nickname} made #{users_to_nicknames_string(users)} #{permission}"
434 @spec get_log_entry_message(ModerationLog) :: String.t()
435 def get_log_entry_message(%ModerationLog{
437 "actor" => %{"nickname" => actor_nickname},
438 "action" => "revoke",
440 "permission" => permission
443 "@#{actor_nickname} revoked #{permission} role from #{users_to_nicknames_string(users)}"
446 @spec get_log_entry_message(ModerationLog) :: String.t()
447 def get_log_entry_message(%ModerationLog{
449 "actor" => %{"nickname" => actor_nickname},
450 "action" => "relay_follow",
454 "@#{actor_nickname} followed relay: #{target}"
457 @spec get_log_entry_message(ModerationLog) :: String.t()
458 def get_log_entry_message(%ModerationLog{
460 "actor" => %{"nickname" => actor_nickname},
461 "action" => "relay_unfollow",
465 "@#{actor_nickname} unfollowed relay: #{target}"
468 @spec get_log_entry_message(ModerationLog) :: String.t()
469 def get_log_entry_message(%ModerationLog{
471 "actor" => %{"nickname" => actor_nickname},
472 "action" => "report_update",
473 "subject" => %{"id" => subject_id, "state" => state, "type" => "report"}
476 "@#{actor_nickname} updated report ##{subject_id} with '#{state}' state"
479 @spec get_log_entry_message(ModerationLog) :: String.t()
480 def get_log_entry_message(%ModerationLog{
482 "actor" => %{"nickname" => actor_nickname},
483 "action" => "report_response",
484 "subject" => %{"id" => subject_id, "type" => "report"},
488 "@#{actor_nickname} responded with '#{text}' to report ##{subject_id}"
491 @spec get_log_entry_message(ModerationLog) :: String.t()
492 def get_log_entry_message(%ModerationLog{
494 "actor" => %{"nickname" => actor_nickname},
495 "action" => "status_update",
496 "subject" => %{"id" => subject_id, "type" => "status"},
498 "visibility" => visibility
501 "@#{actor_nickname} updated status ##{subject_id}, set visibility: '#{visibility}'"
504 @spec get_log_entry_message(ModerationLog) :: String.t()
505 def get_log_entry_message(%ModerationLog{
507 "actor" => %{"nickname" => actor_nickname},
508 "action" => "status_update",
509 "subject" => %{"id" => subject_id, "type" => "status"},
510 "sensitive" => sensitive,
514 "@#{actor_nickname} updated status ##{subject_id}, set sensitive: '#{sensitive}'"
517 @spec get_log_entry_message(ModerationLog) :: String.t()
518 def get_log_entry_message(%ModerationLog{
520 "actor" => %{"nickname" => actor_nickname},
521 "action" => "status_update",
522 "subject" => %{"id" => subject_id, "type" => "status"},
523 "sensitive" => sensitive,
524 "visibility" => visibility
527 "@#{actor_nickname} updated status ##{subject_id}, set sensitive: '#{sensitive}', visibility: '#{
532 @spec get_log_entry_message(ModerationLog) :: String.t()
533 def get_log_entry_message(%ModerationLog{
535 "actor" => %{"nickname" => actor_nickname},
536 "action" => "status_delete",
537 "subject_id" => subject_id
540 "@#{actor_nickname} deleted status ##{subject_id}"
543 @spec get_log_entry_message(ModerationLog) :: String.t()
544 def get_log_entry_message(%ModerationLog{
546 "actor" => %{"nickname" => actor_nickname},
547 "action" => "force_password_reset",
548 "subject" => subjects
551 "@#{actor_nickname} force password reset for users: #{users_to_nicknames_string(subjects)}"
554 defp nicknames_to_string(nicknames) do
556 |> Enum.map(&"@#{&1}")
560 defp users_to_nicknames_string(users) do
562 |> Enum.map(&"@#{&1["nickname"]}")