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_note",
132 subject: %Activity{} = subject,
137 "actor" => user_to_map(actor),
138 "action" => "report_note",
139 "subject" => report_to_map(subject),
143 |> insert_log_entry_with_message()
146 @spec insert_log(%{actor: User, subject: Activity, action: String.t(), text: String.t()}) ::
147 {:ok, ModerationLog} | {:error, any}
149 actor: %User{} = actor,
150 action: "report_note_delete",
151 subject: %Activity{} = subject,
156 "actor" => user_to_map(actor),
157 "action" => "report_note_delete",
158 "subject" => report_to_map(subject),
162 |> insert_log_entry_with_message()
169 sensitive: String.t(),
170 visibility: String.t()
171 }) :: {:ok, ModerationLog} | {:error, any}
173 actor: %User{} = actor,
174 action: "status_update",
175 subject: %Activity{} = subject,
176 sensitive: sensitive,
177 visibility: visibility
181 "actor" => user_to_map(actor),
182 "action" => "status_update",
183 "subject" => status_to_map(subject),
184 "sensitive" => sensitive,
185 "visibility" => visibility,
189 |> insert_log_entry_with_message()
192 @spec insert_log(%{actor: User, action: String.t(), subject_id: String.t()}) ::
193 {:ok, ModerationLog} | {:error, any}
195 actor: %User{} = actor,
196 action: "status_delete",
197 subject_id: subject_id
201 "actor" => user_to_map(actor),
202 "action" => "status_delete",
203 "subject_id" => subject_id,
207 |> insert_log_entry_with_message()
210 @spec insert_log(%{actor: User, subject: User, action: String.t()}) ::
211 {:ok, ModerationLog} | {:error, any}
212 def insert_log(%{actor: %User{} = actor, subject: subject, action: action}) do
215 "actor" => user_to_map(actor),
217 "subject" => user_to_map(subject),
221 |> insert_log_entry_with_message()
224 @spec insert_log(%{actor: User, subjects: [User], action: String.t()}) ::
225 {:ok, ModerationLog} | {:error, any}
226 def insert_log(%{actor: %User{} = actor, subjects: subjects, action: action}) do
227 subjects = Enum.map(subjects, &user_to_map/1)
231 "actor" => user_to_map(actor),
233 "subjects" => subjects,
237 |> insert_log_entry_with_message()
240 @spec insert_log(%{actor: User, action: String.t(), followed: User, follower: User}) ::
241 {:ok, ModerationLog} | {:error, any}
243 actor: %User{} = actor,
244 followed: %User{} = followed,
245 follower: %User{} = follower,
250 "actor" => user_to_map(actor),
251 "action" => "follow",
252 "followed" => user_to_map(followed),
253 "follower" => user_to_map(follower),
257 |> insert_log_entry_with_message()
260 @spec insert_log(%{actor: User, action: String.t(), followed: User, follower: User}) ::
261 {:ok, ModerationLog} | {:error, any}
263 actor: %User{} = actor,
264 followed: %User{} = followed,
265 follower: %User{} = follower,
270 "actor" => user_to_map(actor),
271 "action" => "unfollow",
272 "followed" => user_to_map(followed),
273 "follower" => user_to_map(follower),
277 |> insert_log_entry_with_message()
283 nicknames: [String.t()],
285 }) :: {:ok, ModerationLog} | {:error, any}
287 actor: %User{} = actor,
288 nicknames: nicknames,
294 "actor" => user_to_map(actor),
295 "nicknames" => nicknames,
301 |> insert_log_entry_with_message()
304 @spec insert_log(%{actor: User, action: String.t(), target: String.t()}) ::
305 {:ok, ModerationLog} | {:error, any}
307 actor: %User{} = actor,
311 when action in ["relay_follow", "relay_unfollow"] do
314 "actor" => user_to_map(actor),
320 |> insert_log_entry_with_message()
323 @spec insert_log_entry_with_message(ModerationLog) :: {:ok, ModerationLog} | {:error, any}
324 defp insert_log_entry_with_message(entry) do
325 entry.data["message"]
326 |> put_in(get_log_entry_message(entry))
330 defp user_to_map(users) when is_list(users) do
331 users |> Enum.map(&user_to_map/1)
334 defp user_to_map(%User{} = user) do
337 |> Map.take([:id, :nickname])
338 |> Map.new(fn {k, v} -> {Atom.to_string(k), v} end)
339 |> Map.put("type", "user")
342 defp report_to_map(%Activity{} = report) do
346 "state" => report.data["state"]
350 defp status_to_map(%Activity{} = status) do
357 def get_log_entry_message(%ModerationLog{
359 "actor" => %{"nickname" => actor_nickname},
361 "followed" => %{"nickname" => followed_nickname},
362 "follower" => %{"nickname" => follower_nickname}
365 "@#{actor_nickname} made @#{follower_nickname} #{action} @#{followed_nickname}"
368 @spec get_log_entry_message(ModerationLog) :: String.t()
369 def get_log_entry_message(%ModerationLog{
371 "actor" => %{"nickname" => actor_nickname},
372 "action" => "delete",
373 "subject" => subjects
376 "@#{actor_nickname} deleted users: #{users_to_nicknames_string(subjects)}"
379 @spec get_log_entry_message(ModerationLog) :: String.t()
380 def get_log_entry_message(%ModerationLog{
382 "actor" => %{"nickname" => actor_nickname},
383 "action" => "create",
384 "subjects" => subjects
387 "@#{actor_nickname} created users: #{users_to_nicknames_string(subjects)}"
390 @spec get_log_entry_message(ModerationLog) :: String.t()
391 def get_log_entry_message(%ModerationLog{
393 "actor" => %{"nickname" => actor_nickname},
394 "action" => "activate",
399 get_log_entry_message(%ModerationLog{
401 "actor" => %{"nickname" => actor_nickname},
402 "action" => "activate",
408 @spec get_log_entry_message(ModerationLog) :: String.t()
409 def get_log_entry_message(%ModerationLog{
411 "actor" => %{"nickname" => actor_nickname},
412 "action" => "activate",
416 "@#{actor_nickname} activated users: #{users_to_nicknames_string(users)}"
419 @spec get_log_entry_message(ModerationLog) :: String.t()
420 def get_log_entry_message(%ModerationLog{
422 "actor" => %{"nickname" => actor_nickname},
423 "action" => "deactivate",
428 get_log_entry_message(%ModerationLog{
430 "actor" => %{"nickname" => actor_nickname},
431 "action" => "deactivate",
437 @spec get_log_entry_message(ModerationLog) :: String.t()
438 def get_log_entry_message(%ModerationLog{
440 "actor" => %{"nickname" => actor_nickname},
441 "action" => "deactivate",
445 "@#{actor_nickname} deactivated users: #{users_to_nicknames_string(users)}"
448 @spec get_log_entry_message(ModerationLog) :: String.t()
449 def get_log_entry_message(%ModerationLog{
451 "actor" => %{"nickname" => actor_nickname},
452 "nicknames" => nicknames,
457 tags_string = tags |> Enum.join(", ")
459 "@#{actor_nickname} added tags: #{tags_string} to users: #{nicknames_to_string(nicknames)}"
462 @spec get_log_entry_message(ModerationLog) :: String.t()
463 def get_log_entry_message(%ModerationLog{
465 "actor" => %{"nickname" => actor_nickname},
466 "nicknames" => nicknames,
471 tags_string = tags |> Enum.join(", ")
473 "@#{actor_nickname} removed tags: #{tags_string} from users: #{nicknames_to_string(nicknames)}"
476 @spec get_log_entry_message(ModerationLog) :: String.t()
477 def get_log_entry_message(%ModerationLog{
479 "actor" => %{"nickname" => actor_nickname},
482 "permission" => permission
486 get_log_entry_message(%ModerationLog{
488 "actor" => %{"nickname" => actor_nickname},
491 "permission" => permission
496 @spec get_log_entry_message(ModerationLog) :: String.t()
497 def get_log_entry_message(%ModerationLog{
499 "actor" => %{"nickname" => actor_nickname},
502 "permission" => permission
505 "@#{actor_nickname} made #{users_to_nicknames_string(users)} #{permission}"
508 @spec get_log_entry_message(ModerationLog) :: String.t()
509 def get_log_entry_message(%ModerationLog{
511 "actor" => %{"nickname" => actor_nickname},
512 "action" => "revoke",
514 "permission" => permission
518 get_log_entry_message(%ModerationLog{
520 "actor" => %{"nickname" => actor_nickname},
521 "action" => "revoke",
523 "permission" => permission
528 @spec get_log_entry_message(ModerationLog) :: String.t()
529 def get_log_entry_message(%ModerationLog{
531 "actor" => %{"nickname" => actor_nickname},
532 "action" => "revoke",
534 "permission" => permission
537 "@#{actor_nickname} revoked #{permission} role from #{users_to_nicknames_string(users)}"
540 @spec get_log_entry_message(ModerationLog) :: String.t()
541 def get_log_entry_message(%ModerationLog{
543 "actor" => %{"nickname" => actor_nickname},
544 "action" => "relay_follow",
548 "@#{actor_nickname} followed relay: #{target}"
551 @spec get_log_entry_message(ModerationLog) :: String.t()
552 def get_log_entry_message(%ModerationLog{
554 "actor" => %{"nickname" => actor_nickname},
555 "action" => "relay_unfollow",
559 "@#{actor_nickname} unfollowed relay: #{target}"
562 @spec get_log_entry_message(ModerationLog) :: String.t()
563 def get_log_entry_message(%ModerationLog{
565 "actor" => %{"nickname" => actor_nickname},
566 "action" => "report_update",
567 "subject" => %{"id" => subject_id, "state" => state, "type" => "report"}
570 "@#{actor_nickname} updated report ##{subject_id} with '#{state}' state"
573 @spec get_log_entry_message(ModerationLog) :: String.t()
574 def get_log_entry_message(%ModerationLog{
576 "actor" => %{"nickname" => actor_nickname},
577 "action" => "report_note",
578 "subject" => %{"id" => subject_id, "type" => "report"},
582 "@#{actor_nickname} added note '#{text}' to report ##{subject_id}"
585 @spec get_log_entry_message(ModerationLog) :: String.t()
586 def get_log_entry_message(%ModerationLog{
588 "actor" => %{"nickname" => actor_nickname},
589 "action" => "report_note_delete",
590 "subject" => %{"id" => subject_id, "type" => "report"},
594 "@#{actor_nickname} deleted note '#{text}' from report ##{subject_id}"
597 @spec get_log_entry_message(ModerationLog) :: String.t()
598 def get_log_entry_message(%ModerationLog{
600 "actor" => %{"nickname" => actor_nickname},
601 "action" => "status_update",
602 "subject" => %{"id" => subject_id, "type" => "status"},
604 "visibility" => visibility
607 "@#{actor_nickname} updated status ##{subject_id}, set visibility: '#{visibility}'"
610 @spec get_log_entry_message(ModerationLog) :: String.t()
611 def get_log_entry_message(%ModerationLog{
613 "actor" => %{"nickname" => actor_nickname},
614 "action" => "status_update",
615 "subject" => %{"id" => subject_id, "type" => "status"},
616 "sensitive" => sensitive,
620 "@#{actor_nickname} updated status ##{subject_id}, set sensitive: '#{sensitive}'"
623 @spec get_log_entry_message(ModerationLog) :: String.t()
624 def get_log_entry_message(%ModerationLog{
626 "actor" => %{"nickname" => actor_nickname},
627 "action" => "status_update",
628 "subject" => %{"id" => subject_id, "type" => "status"},
629 "sensitive" => sensitive,
630 "visibility" => visibility
633 "@#{actor_nickname} updated status ##{subject_id}, set sensitive: '#{sensitive}', visibility: '#{
638 @spec get_log_entry_message(ModerationLog) :: String.t()
639 def get_log_entry_message(%ModerationLog{
641 "actor" => %{"nickname" => actor_nickname},
642 "action" => "status_delete",
643 "subject_id" => subject_id
646 "@#{actor_nickname} deleted status ##{subject_id}"
649 @spec get_log_entry_message(ModerationLog) :: String.t()
650 def get_log_entry_message(%ModerationLog{
652 "actor" => %{"nickname" => actor_nickname},
653 "action" => "force_password_reset",
654 "subject" => subjects
657 "@#{actor_nickname} forced password reset for users: #{users_to_nicknames_string(subjects)}"
660 @spec get_log_entry_message(ModerationLog) :: String.t()
661 def get_log_entry_message(%ModerationLog{
663 "actor" => %{"nickname" => actor_nickname},
664 "action" => "confirm_email",
665 "subject" => subjects
668 "@#{actor_nickname} confirmed email for users: #{users_to_nicknames_string(subjects)}"
671 @spec get_log_entry_message(ModerationLog) :: String.t()
672 def get_log_entry_message(%ModerationLog{
674 "actor" => %{"nickname" => actor_nickname},
675 "action" => "resend_confirmation_email",
676 "subject" => subjects
679 "@#{actor_nickname} re-sent confirmation email for users: #{
680 users_to_nicknames_string(subjects)
684 defp nicknames_to_string(nicknames) do
686 |> Enum.map(&"@#{&1}")
690 defp users_to_nicknames_string(users) do
692 |> Enum.map(&"@#{&1["nickname"]}")