logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git
commit: f0e6cff58365791f3bfa79117351ee2e705d1b6b
parent 4200a063408966b1e14e79b18c96ce59af23ec35
Author: lain <lain@soykaf.club>
Date:   Tue,  5 Jan 2021 12:42:30 +0100

Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into 1526-account-aliases

Diffstat:

MCHANGELOG.md1+
Mconfig/test.exs4++++
Mdocs/API/admin_api.md1+
Alib/pleroma/logging.ex7+++++++
Mlib/pleroma/web/activity_pub/activity_pub.ex13++++++++++++-
Alib/pleroma/web/activity_pub/activity_pub/streaming.ex12++++++++++++
Mlib/pleroma/web/activity_pub/side_effects.ex8+++++---
Mlib/pleroma/web/admin_api/controllers/admin_api_controller.ex3++-
Mlib/pleroma/web/admin_api/views/moderation_log_view.ex1+
Mlib/pleroma/web/admin_api/views/report_view.ex3+--
Atest/pleroma/web/activity_pub/side_effects/delete_test.exs147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/pleroma/web/activity_pub/side_effects_test.exs110-------------------------------------------------------------------------------
Mtest/pleroma/web/admin_api/controllers/admin_api_controller_test.exs16+++++++++++++---
Mtest/pleroma/web/admin_api/views/moderation_log_view_test.exs5+++++
Mtest/pleroma/web/admin_api/views/report_view_test.exs25+++++++++++++++++++++++++
Mtest/support/conn_case.ex2++
Mtest/support/data_case.ex2++
Mtest/support/mocks.ex7++++++-
18 files changed, 246 insertions(+), 121 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - **Breaking:** Changed `mix pleroma.user toggle_confirmed` to `mix pleroma.user confirm` - Search: When using Postgres 11+, Pleroma will use the `websearch_to_tsvector` function to parse search queries. - Emoji: Support the full Unicode 13.1 set of Emoji for reactions, plus regional indicators. +- Admin API: Reports now ordered by newest ### Added diff --git a/config/test.exs b/config/test.exs @@ -134,6 +134,10 @@ config :pleroma, :pipeline, config :pleroma, :cachex, provider: Pleroma.CachexMock +config :pleroma, :side_effects, + ap_streamer: Pleroma.Web.ActivityPub.ActivityPubMock, + logger: Pleroma.LoggerMock + if File.exists?("./config/test.secret.exs") do import_config "test.secret.exs" else diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md @@ -1123,6 +1123,7 @@ Loads json generated from `config/descriptions.exs`. ```json [ { + "id": 1234, "data": { "actor": { "id": 1, diff --git a/lib/pleroma/logging.ex b/lib/pleroma/logging.ex @@ -0,0 +1,7 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Logging do + @callback error(String.t()) :: any() +end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -33,6 +33,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do require Pleroma.Constants @behaviour Pleroma.Web.ActivityPub.ActivityPub.Persisting + @behaviour Pleroma.Web.ActivityPub.ActivityPub.Streaming defp get_recipients(%{"type" => "Create"} = data) do to = Map.get(data, "to", []) @@ -224,6 +225,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do Streamer.stream("participation", participations) end + @impl true def stream_out_participations(%Object{data: %{"context" => context}}, user) do with %Conversation{} = conversation <- Conversation.get_for_ap_id(context) do conversation = Repo.preload(conversation, :participations) @@ -240,8 +242,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end end + @impl true def stream_out_participations(_, _), do: :noop + @impl true def stream_out(%Activity{data: %{"type" => data_type}} = activity) when data_type in ["Create", "Announce", "Delete"] do activity @@ -249,6 +253,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> Streamer.stream(activity) end + @impl true def stream_out(_activity) do :noop end @@ -603,12 +608,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> Map.put(:muting_user, reading_user) end + pagination_type = + cond do + !Map.has_key?(params, :offset) -> :keyset + true -> :offset + end + %{ godmode: params[:godmode], reading_user: reading_user } |> user_activities_recipients() - |> fetch_activities(params) + |> fetch_activities(params, pagination_type) |> Enum.reverse() end diff --git a/lib/pleroma/web/activity_pub/activity_pub/streaming.ex b/lib/pleroma/web/activity_pub/activity_pub/streaming.ex @@ -0,0 +1,12 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ActivityPub.Streaming do + alias Pleroma.Activity + alias Pleroma.Object + alias Pleroma.User + + @callback stream_out(Activity.t()) :: any() + @callback stream_out_participations(Object.t(), User.t()) :: any() +end diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex @@ -28,6 +28,8 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do require Logger @cachex Pleroma.Config.get([:cachex, :provider], Cachex) + @ap_streamer Pleroma.Config.get([:side_effects, :ap_streamer], ActivityPub) + @logger Pleroma.Config.get([:side_effects, :logger], Logger) @behaviour Pleroma.Web.ActivityPub.SideEffects.Handling @@ -287,12 +289,12 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do MessageReference.delete_for_object(deleted_object) - ActivityPub.stream_out(object) - ActivityPub.stream_out_participations(deleted_object, user) + @ap_streamer.stream_out(object) + @ap_streamer.stream_out_participations(deleted_object, user) :ok else {:actor, _} -> - Logger.error("The object doesn't have an actor: #{inspect(deleted_object)}") + @logger.error("The object doesn't have an actor: #{inspect(deleted_object)}") :no_object_actor end diff --git a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -103,11 +103,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do godmode = params["godmode"] == "true" || params["godmode"] == true with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do - {_, page_size} = page_params(params) + {page, page_size} = page_params(params) activities = ActivityPub.fetch_user_activities(user, nil, %{ limit: page_size, + offset: (page - 1) * page_size, godmode: godmode, exclude_reblogs: not with_reblogs }) diff --git a/lib/pleroma/web/admin_api/views/moderation_log_view.ex b/lib/pleroma/web/admin_api/views/moderation_log_view.ex @@ -21,6 +21,7 @@ defmodule Pleroma.Web.AdminAPI.ModerationLogView do |> DateTime.to_unix() %{ + id: log_entry.id, data: log_entry.data, time: time, message: ModerationLog.get_log_entry_message(log_entry) diff --git a/lib/pleroma/web/admin_api/views/report_view.ex b/lib/pleroma/web/admin_api/views/report_view.ex @@ -19,8 +19,7 @@ defmodule Pleroma.Web.AdminAPI.ReportView do reports: reports[:items] |> Enum.map(&Report.extract_report_info/1) - |> Enum.map(&render(__MODULE__, "show.json", &1)) - |> Enum.reverse(), + |> Enum.map(&render(__MODULE__, "show.json", &1)), total: reports[:total] } end diff --git a/test/pleroma/web/activity_pub/side_effects/delete_test.exs b/test/pleroma/web/activity_pub/side_effects/delete_test.exs @@ -0,0 +1,147 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.SideEffects.DeleteTest do + use Oban.Testing, repo: Pleroma.Repo + use Pleroma.DataCase, async: true + + alias Pleroma.Activity + alias Pleroma.Object + alias Pleroma.Repo + alias Pleroma.Tests.ObanHelpers + alias Pleroma.User + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.Builder + alias Pleroma.Web.ActivityPub.SideEffects + alias Pleroma.Web.CommonAPI + + alias Pleroma.LoggerMock + alias Pleroma.Web.ActivityPub.ActivityPubMock + + import Mox + import Pleroma.Factory + + describe "user deletion" do + setup do + user = insert(:user) + + {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id) + {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true) + + %{ + user: user, + delete_user: delete_user + } + end + + test "it handles user deletions", %{delete_user: delete, user: user} do + {:ok, _delete, _} = SideEffects.handle(delete) + ObanHelpers.perform_all() + + assert User.get_cached_by_ap_id(user.ap_id).deactivated + end + end + + describe "object deletion" do + setup do + user = insert(:user) + other_user = insert(:user) + + {:ok, op} = CommonAPI.post(other_user, %{status: "big oof"}) + {:ok, post} = CommonAPI.post(user, %{status: "hey", in_reply_to_id: op}) + {:ok, favorite} = CommonAPI.favorite(user, post.id) + object = Object.normalize(post) + {:ok, delete_data, _meta} = Builder.delete(user, object.data["id"]) + {:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true) + + %{ + user: user, + delete: delete, + post: post, + object: object, + op: op, + favorite: favorite + } + end + + test "it handles object deletions", %{ + delete: delete, + post: post, + object: object, + user: user, + op: op, + favorite: favorite + } do + object_id = object.id + user_id = user.id + + ActivityPubMock + |> expect(:stream_out, fn ^delete -> nil end) + |> expect(:stream_out_participations, fn %Object{id: ^object_id}, %User{id: ^user_id} -> + nil + end) + + {:ok, _delete, _} = SideEffects.handle(delete) + user = User.get_cached_by_ap_id(object.data["actor"]) + + object = Object.get_by_id(object.id) + assert object.data["type"] == "Tombstone" + refute Activity.get_by_id(post.id) + refute Activity.get_by_id(favorite.id) + + user = User.get_by_id(user.id) + assert user.note_count == 0 + + object = Object.normalize(op.data["object"], false) + + assert object.data["repliesCount"] == 0 + end + + test "it handles object deletions when the object itself has been pruned", %{ + delete: delete, + post: post, + object: object, + user: user, + op: op + } do + object_id = object.id + user_id = user.id + + ActivityPubMock + |> expect(:stream_out, fn ^delete -> nil end) + |> expect(:stream_out_participations, fn %Object{id: ^object_id}, %User{id: ^user_id} -> + nil + end) + + {:ok, _delete, _} = SideEffects.handle(delete) + user = User.get_cached_by_ap_id(object.data["actor"]) + + object = Object.get_by_id(object.id) + assert object.data["type"] == "Tombstone" + refute Activity.get_by_id(post.id) + + user = User.get_by_id(user.id) + assert user.note_count == 0 + + object = Object.normalize(op.data["object"], false) + + assert object.data["repliesCount"] == 0 + end + + test "it logs issues with objects deletion", %{ + delete: delete, + object: object + } do + {:ok, _object} = + object + |> Object.change(%{data: Map.delete(object.data, "actor")}) + |> Repo.update() + + LoggerMock + |> expect(:error, fn str -> assert str =~ "The object doesn't have an actor" end) + + {:error, :no_object_actor} = SideEffects.handle(delete) + end + end +end diff --git a/test/pleroma/web/activity_pub/side_effects_test.exs b/test/pleroma/web/activity_pub/side_effects_test.exs @@ -19,7 +19,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do alias Pleroma.Web.ActivityPub.SideEffects alias Pleroma.Web.CommonAPI - import ExUnit.CaptureLog import Mock import Pleroma.Factory @@ -131,115 +130,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do end end - describe "delete objects" do - setup do - user = insert(:user) - other_user = insert(:user) - - {:ok, op} = CommonAPI.post(other_user, %{status: "big oof"}) - {:ok, post} = CommonAPI.post(user, %{status: "hey", in_reply_to_id: op}) - {:ok, favorite} = CommonAPI.favorite(user, post.id) - object = Object.normalize(post) - {:ok, delete_data, _meta} = Builder.delete(user, object.data["id"]) - {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id) - {:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true) - {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true) - - %{ - user: user, - delete: delete, - post: post, - object: object, - delete_user: delete_user, - op: op, - favorite: favorite - } - end - - test "it handles object deletions", %{ - delete: delete, - post: post, - object: object, - user: user, - op: op, - favorite: favorite - } do - with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough], - stream_out: fn _ -> nil end, - stream_out_participations: fn _, _ -> nil end do - {:ok, delete, _} = SideEffects.handle(delete) - user = User.get_cached_by_ap_id(object.data["actor"]) - - assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete)) - assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user)) - end - - object = Object.get_by_id(object.id) - assert object.data["type"] == "Tombstone" - refute Activity.get_by_id(post.id) - refute Activity.get_by_id(favorite.id) - - user = User.get_by_id(user.id) - assert user.note_count == 0 - - object = Object.normalize(op.data["object"], false) - - assert object.data["repliesCount"] == 0 - end - - test "it handles object deletions when the object itself has been pruned", %{ - delete: delete, - post: post, - object: object, - user: user, - op: op - } do - with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough], - stream_out: fn _ -> nil end, - stream_out_participations: fn _, _ -> nil end do - {:ok, delete, _} = SideEffects.handle(delete) - user = User.get_cached_by_ap_id(object.data["actor"]) - - assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete)) - assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user)) - end - - object = Object.get_by_id(object.id) - assert object.data["type"] == "Tombstone" - refute Activity.get_by_id(post.id) - - user = User.get_by_id(user.id) - assert user.note_count == 0 - - object = Object.normalize(op.data["object"], false) - - assert object.data["repliesCount"] == 0 - end - - test "it handles user deletions", %{delete_user: delete, user: user} do - {:ok, _delete, _} = SideEffects.handle(delete) - ObanHelpers.perform_all() - - assert User.get_cached_by_ap_id(user.ap_id).deactivated - end - - test "it logs issues with objects deletion", %{ - delete: delete, - object: object - } do - {:ok, object} = - object - |> Object.change(%{data: Map.delete(object.data, "actor")}) - |> Repo.update() - - Object.invalid_object_cache(object) - - assert capture_log(fn -> - {:error, :no_object_actor} = SideEffects.handle(delete) - end) =~ "object doesn't have an actor" - end - end - describe "EmojiReact objects" do setup do poster = insert(:user) diff --git a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs @@ -422,10 +422,20 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do assert json_response(conn, 200) |> length() == 3 end - test "renders user's statuses with a limit", %{conn: conn, user: user} do - conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2") + test "renders user's statuses with pagination", %{conn: conn, user: user} do + conn1 = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=1") - assert json_response(conn, 200) |> length() == 2 + response1 = json_response(conn1, 200) + + assert response1 |> length() == 1 + + conn2 = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=2") + + response2 = json_response(conn2, 200) + + assert response2 |> length() == 1 + + refute response1 == response2 end test "doesn't return private statuses by default", %{conn: conn, user: user} do diff --git a/test/pleroma/web/admin_api/views/moderation_log_view_test.exs b/test/pleroma/web/admin_api/views/moderation_log_view_test.exs @@ -9,6 +9,7 @@ defmodule Pleroma.Web.AdminAPI.ModerationLogViewTest do describe "renders `report_note_delete` log messages" do setup do log1 = %Pleroma.ModerationLog{ + id: 1, data: %{ "action" => "report_note_delete", "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, @@ -21,6 +22,7 @@ defmodule Pleroma.Web.AdminAPI.ModerationLogViewTest do } log2 = %Pleroma.ModerationLog{ + id: 2, data: %{ "action" => "report_note_delete", "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, @@ -42,6 +44,7 @@ defmodule Pleroma.Web.AdminAPI.ModerationLogViewTest do ) == %{ items: [ %{ + id: 1, data: %{ "action" => "report_note_delete", "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, @@ -59,6 +62,7 @@ defmodule Pleroma.Web.AdminAPI.ModerationLogViewTest do time: 1_605_622_400 }, %{ + id: 2, data: %{ "action" => "report_note_delete", "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, @@ -82,6 +86,7 @@ defmodule Pleroma.Web.AdminAPI.ModerationLogViewTest do test "renders `report_note_delete` log message", %{log1: log} do assert ModerationLogView.render("show.json", %{log_entry: log}) == %{ + id: 1, data: %{ "action" => "report_note_delete", "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, diff --git a/test/pleroma/web/admin_api/views/report_view_test.exs b/test/pleroma/web/admin_api/views/report_view_test.exs @@ -143,4 +143,29 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do assert %{} = ReportView.render("show.json", Report.extract_report_info(activity)) end + + test "reports are ordered newest first" do + user = insert(:user) + other_user = insert(:user) + + {:ok, report1} = + CommonAPI.report(user, %{ + account_id: other_user.id, + comment: "first report" + }) + + {:ok, report2} = + CommonAPI.report(user, %{ + account_id: other_user.id, + comment: "second report" + }) + + %{reports: rendered} = + ReportView.render("index.json", + reports: Pleroma.Web.ActivityPub.Utils.get_reports(%{}, 1, 50) + ) + + assert report2.id == rendered |> Enum.at(0) |> Map.get(:id) + assert report1.id == rendered |> Enum.at(1) |> Map.get(:id) + end end diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex @@ -138,6 +138,8 @@ defmodule Pleroma.Web.ConnCase do Pleroma.DataCase.stub_pipeline() + Mox.verify_on_exit!() + {:ok, conn: Phoenix.ConnTest.build_conn()} end end diff --git a/test/support/data_case.ex b/test/support/data_case.ex @@ -85,6 +85,8 @@ defmodule Pleroma.DataCase do stub_pipeline() + Mox.verify_on_exit!() + :ok end diff --git a/test/support/mocks.ex b/test/support/mocks.ex @@ -13,7 +13,10 @@ Mox.defmock(Pleroma.Web.ActivityPub.MRFMock, ) Mox.defmock(Pleroma.Web.ActivityPub.ActivityPubMock, - for: Pleroma.Web.ActivityPub.ActivityPub.Persisting + for: [ + Pleroma.Web.ActivityPub.ActivityPub.Persisting, + Pleroma.Web.ActivityPub.ActivityPub.Streaming + ] ) Mox.defmock(Pleroma.Web.ActivityPub.SideEffectsMock, @@ -23,3 +26,5 @@ Mox.defmock(Pleroma.Web.ActivityPub.SideEffectsMock, Mox.defmock(Pleroma.Web.FederatorMock, for: Pleroma.Web.Federator.Publishing) Mox.defmock(Pleroma.ConfigMock, for: Pleroma.Config.Getting) + +Mox.defmock(Pleroma.LoggerMock, for: Pleroma.Logging)