diff options
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/utils.ex | 104 | ||||
| -rw-r--r-- | lib/pleroma/web/admin_api/views/report_view.ex | 8 | ||||
| -rw-r--r-- | test/web/activity_pub/utils_test.exs | 43 | ||||
| -rw-r--r-- | test/web/admin_api/admin_api_controller_test.exs | 16 | 
5 files changed, 74 insertions, 99 deletions
| diff --git a/CHANGELOG.md b/CHANGELOG.md index e44c892ab..d0ac33b32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).  - Mastodon API: `pleroma.thread_muted` to the Status entity  - Mastodon API: Mark the direct conversation as read for the author when they send a new direct message  - Mastodon API, streaming: Add `pleroma.direct_conversation_id` to the `conversation` stream event payload. +- Admin API: Render whole status in grouped reports  </details>  ### Added @@ -82,6 +83,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).  - Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`)  - Mastodon API: Inability to get some local users by nickname in `/api/v1/accounts/:id_or_nickname` +- AdminAPI: If some status received reports both in the "new" format and "old" format it was considered reports on two different statuses (in the context of grouped reports)  - Admin API: Error when trying to update reports in the "old" format  </details> diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 01aacbde3..962f02a05 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -788,63 +788,73 @@ defmodule Pleroma.Web.ActivityPub.Utils do      ActivityPub.fetch_activities([], params, :offset)    end -  @spec get_reports_grouped_by_status(%{required(:activity) => String.t()}) :: %{ -          required(:groups) => [ -            %{ -              required(:date) => String.t(), -              required(:account) => %{}, -              required(:status) => %{}, -              required(:actors) => [%User{}], -              required(:reports) => [%Activity{}] -            } -          ], -          required(:total) => integer -        } -  def get_reports_grouped_by_status(groups) do -    parsed_groups = -      groups -      |> Enum.map(fn entry -> -        activity = -          case Jason.decode(entry.activity) do -            {:ok, activity} -> activity -            _ -> build_flag_object(entry.activity) -          end - -        parse_report_group(activity) -      end) - -    %{ -      groups: parsed_groups -    } -  end -    def parse_report_group(activity) do      reports = get_reports_by_status_id(activity["id"])      max_date = Enum.max_by(reports, &NaiveDateTime.from_iso8601!(&1.data["published"]))      actors = Enum.map(reports, & &1.user_actor) +    {deleted, status} = get_status_data(activity)      %{        date: max_date.data["published"],        account: activity["actor"], -      status: %{ -        id: activity["id"], -        content: activity["content"], -        published: activity["published"] -      }, +      status: status, +      status_deleted: deleted,        actors: Enum.uniq(actors),        reports: reports      }    end +  defp get_status_data(activity) do +    case Activity.get_by_ap_id(activity["id"]) do +      %Activity{} = act -> +        {false, act} + +      _ -> +        {true, +         %{ +           id: activity["id"], +           content: activity["content"], +           published: activity["published"] +         }} +    end +  end +    def get_reports_by_status_id(ap_id) do      from(a in Activity,        where: fragment("(?)->>'type' = 'Flag'", a.data), -      where: fragment("(?)->'object' @> ?", a.data, ^[%{id: ap_id}]) +      where: fragment("(?)->'object' @> ?", a.data, ^[%{id: ap_id}]), +      or_where: fragment("(?)->'object' @> ?", a.data, ^[ap_id])      )      |> Activity.with_preloaded_user_actor()      |> Repo.all()    end +  @spec get_reports_grouped_by_status(%{required(:activity) => String.t()}) :: %{ +          required(:groups) => [ +            %{ +              required(:date) => String.t(), +              required(:account) => %{}, +              required(:status) => %{}, +              required(:actors) => [%User{}], +              required(:reports) => [%Activity{}] +            } +          ], +          required(:total) => integer +        } +  def get_reports_grouped_by_status(activity_ids) do +    parsed_groups = +      activity_ids +      |> Enum.map(fn id -> +        id +        |> build_flag_object() +        |> parse_report_group() +      end) + +    %{ +      groups: parsed_groups +    } +  end +    @spec get_reported_activities() :: [            %{              required(:activity) => String.t(), @@ -852,17 +862,23 @@ defmodule Pleroma.Web.ActivityPub.Utils do            }          ]    def get_reported_activities do -    from(a in Activity, -      where: fragment("(?)->>'type' = 'Flag'", a.data), +    reported_activities_query = +      from(a in Activity, +        where: fragment("(?)->>'type' = 'Flag'", a.data), +        select: %{ +          activity: fragment("jsonb_array_elements((? #- '{object,0}')->'object')", a.data) +        }, +        group_by: fragment("activity") +      ) + +    from(a in subquery(reported_activities_query), +      distinct: true,        select: %{ -        date: fragment("max(?->>'published') date", a.data), -        activity: -          fragment("jsonb_array_elements_text((? #- '{object,0}')->'object') activity", a.data) -      }, -      group_by: fragment("activity"), -      order_by: fragment("date DESC") +        id: fragment("COALESCE(?->>'id'::text, ? #>> '{}')", a.activity, a.activity) +      }      )      |> Repo.all() +    |> Enum.map(& &1.id)    end    def update_report_state(%Activity{} = activity, state) diff --git a/lib/pleroma/web/admin_api/views/report_view.ex b/lib/pleroma/web/admin_api/views/report_view.ex index ca88595c7..45ce75272 100644 --- a/lib/pleroma/web/admin_api/views/report_view.ex +++ b/lib/pleroma/web/admin_api/views/report_view.ex @@ -45,10 +45,16 @@ defmodule Pleroma.Web.AdminAPI.ReportView do    def render("index_grouped.json", %{groups: groups}) do      reports =        Enum.map(groups, fn group -> +        status = +          if group[:status_deleted], +            do: group[:status], +            else: StatusView.render("show.json", %{activity: group[:status]}) +          %{            date: group[:date],            account: group[:account], -          status: group[:status], +          status: status, +          status_deleted: group[:status_deleted],            actors: Enum.map(group[:actors], &merge_account_views/1),            reports:              group[:reports] diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs index 1feb076ba..586eb1d2f 100644 --- a/test/web/activity_pub/utils_test.exs +++ b/test/web/activity_pub/utils_test.exs @@ -636,47 +636,4 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do        assert updated_object.data["announcement_count"] == 1      end    end - -  describe "get_reports_grouped_by_status/1" do -    setup do -      [reporter, target_user] = insert_pair(:user) -      first_status = insert(:note_activity, user: target_user) -      second_status = insert(:note_activity, user: target_user) - -      CommonAPI.report(reporter, %{ -        "account_id" => target_user.id, -        "comment" => "I feel offended", -        "status_ids" => [first_status.id] -      }) - -      CommonAPI.report(reporter, %{ -        "account_id" => target_user.id, -        "comment" => "I feel offended2", -        "status_ids" => [second_status.id] -      }) - -      data = [%{activity: first_status.data["id"]}, %{activity: second_status.data["id"]}] - -      {:ok, -       %{ -         first_status: first_status, -         second_status: second_status, -         data: data -       }} -    end - -    test "works for deprecated reports format", %{ -      first_status: first_status, -      second_status: second_status, -      data: data -    } do -      groups = Utils.get_reports_grouped_by_status(data).groups - -      first_group = Enum.find(groups, &(&1.status.id == first_status.data["id"])) -      second_group = Enum.find(groups, &(&1.status.id == second_status.data["id"])) - -      assert first_group.status.id == first_status.data["id"] -      assert second_group.status.id == second_status.data["id"] -    end -  end  end diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index bb2ca6a62..12dba7773 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -15,6 +15,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do    alias Pleroma.UserInviteToken    alias Pleroma.Web.ActivityPub.Relay    alias Pleroma.Web.CommonAPI +  alias Pleroma.Web.MastodonAPI.StatusView    alias Pleroma.Web.MediaProxy    import Pleroma.Factory @@ -1638,14 +1639,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        assert length(response["reports"]) == 3 -      first_group = -        Enum.find(response["reports"], &(&1["status"]["id"] == first_status.data["id"])) +      first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id)) -      second_group = -        Enum.find(response["reports"], &(&1["status"]["id"] == second_status.data["id"])) +      second_group = Enum.find(response["reports"], &(&1["status"]["id"] == second_status.id)) -      third_group = -        Enum.find(response["reports"], &(&1["status"]["id"] == third_status.data["id"])) +      third_group = Enum.find(response["reports"], &(&1["status"]["id"] == third_status.id))        assert length(first_group["reports"]) == 3        assert length(second_group["reports"]) == 2 @@ -1656,11 +1654,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                   NaiveDateTime.from_iso8601!(act.data["published"])                 end).data["published"] -      assert first_group["status"] == %{ -               "id" => first_status.data["id"], -               "content" => first_status.object.data["content"], -               "published" => first_status.object.data["published"] -             } +      assert first_group["status"] == StatusView.render("show.json", %{activity: first_status})        assert first_group["account"]["id"] == target_user.id | 
