From: Maxim Filippov Date: Mon, 4 Nov 2019 23:12:48 +0000 (+0300) Subject: Merge branch 'develop' into feature/reports-groups-and-multiple-state-update X-Git-Url: https://git.squeep.com/?a=commitdiff_plain;h=43ea16870fe60578a6528e1f01bfaab68943a1bc;p=akkoma Merge branch 'develop' into feature/reports-groups-and-multiple-state-update --- 43ea16870fe60578a6528e1f01bfaab68943a1bc diff --cc CHANGELOG.md index c51807c80,77edf7bf0..64a28218d --- a/CHANGELOG.md +++ b/CHANGELOG.md @@@ -14,10 -46,13 +46,14 @@@ The format is based on [Keep a Changelo - Mastodon API: Add `upload_limit`, `avatar_upload_limit`, `background_upload_limit`, and `banner_upload_limit` to `/api/v1/instance` - Mastodon API: Add `pleroma.unread_conversation_count` to the Account entity - OAuth: support for hierarchical permissions / [Mastodon 2.4.3 OAuth permissions](https://docs.joinmastodon.org/api/permissions/) - - Authentication: Added rate limit for password-authorized actions / login existence checks - Metadata Link: Atom syndication Feed - - Mix task to re-count statuses for all users (`mix pleroma.count_statuses`) + - Mastodon API: Add `exclude_visibilities` parameter to the timeline and notification endpoints + - Admin API: `/users/:nickname/toggle_activation` endpoint is now deprecated in favor of: `/users/activate`, `/users/deactivate`, both accept `nicknames` array + - Admin API: `POST/DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group` are deprecated in favor of: `POST/DELETE /api/pleroma/admin/users/permission_group/:permission_group` (both accept `nicknames` array), `DELETE /api/pleroma/admin/users` (`nickname` query param or `nickname` sent in JSON body) is deprecated in favor of: `DELETE /api/pleroma/admin/users` (`nicknames` query array param or `nicknames` sent in JSON body). + - Admin API: Add `GET /api/pleroma/admin/relay` endpoint - lists all followed relays + - Pleroma API: `POST /api/v1/pleroma/conversations/read` to mark all conversations as read + - Mastodon API: Add `/api/v1/markers` for managing timeline read markers +- Admin API: Add ability to fetch reports, grouped by status `GET /api/pleroma/admin/grouped_reports` ### Changed - **Breaking:** Elixir >=1.8 is now required (was >= 1.7) diff --cc docs/API/admin_api.md index e8232225c,e64ae6429..9499d0140 --- a/docs/API/admin_api.md +++ b/docs/API/admin_api.md @@@ -156,10 -170,20 +165,22 @@@ Note: Available `:permission_group` is - Params: none - Response: - On failure: `{"error": "…"}` - - On success: JSON of the `user.info` + - On success: JSON of the user + + ## `POST /api/pleroma/admin/users/permission_group/:permission_group` + + ### Add users to permission group + + - Params: + - `nicknames`: nicknames array + - Response: + - On failure: `{"error": "…"}` + - On success: JSON of the user + + ## DEPRECATED `DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group` +## `DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group` + ### Remove user from permission group - Params: none @@@ -216,7 -289,15 +284,15 @@@ - Response: - On success: URL of the unfollowed relay + ## `GET /api/pleroma/admin/relay` + + ### List Relays + + - Params: none + - Response: + - On success: JSON array of relays + -## `/api/pleroma/admin/users/invite_token` +## `POST /api/pleroma/admin/users/invite_token` ### Create an account registration invite token diff --cc lib/pleroma/web/activity_pub/utils.ex index f2beb0809,d812fd734..57349e304 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@@ -12,8 -11,8 +12,9 @@@ defmodule Pleroma.Web.ActivityPub.Util alias Pleroma.Repo alias Pleroma.User alias Pleroma.Web + alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Visibility + alias Pleroma.Web.AdminAPI.AccountView alias Pleroma.Web.Endpoint alias Pleroma.Web.Router.Helpers @@@ -659,94 -679,21 +681,107 @@@ end #### Report-related helpers - + def get_reports(params, page, page_size) do + params = + params + |> Map.put("type", "Flag") + |> Map.put("skip_preload", true) + |> Map.put("total", true) + |> Map.put("limit", page_size) + |> Map.put("offset", (page - 1) * page_size) + + ActivityPub.fetch_activities([], params, :offset) + end + + @spec get_reports_grouped_by_status() :: %{ + required(:groups) => [ + %{ + required(:date) => String.t(), + required(:account) => %User{}, + required(:status) => %Activity{}, + required(:actors) => [%User{}], + required(:reports) => [%Activity{}] + } + ], + required(:total) => integer + } + def get_reports_grouped_by_status do + paginated_activities = get_reported_status_ids() + + groups = + paginated_activities + |> Enum.map(fn entry -> + status = + Activity + |> Queries.by_ap_id(entry[:activity_id]) + |> Activity.with_preloaded_object(:left) + |> Activity.with_preloaded_user_actor() + |> Repo.one() + + reports = get_reports_by_status_id(status.data["id"]) + + max_date = + Enum.max_by(reports, &Pleroma.Web.CommonAPI.Utils.to_masto_date(&1.data["published"])).data[ + "published" + ] + + actors = Enum.map(reports, & &1.user_actor) + + %{ + date: max_date, + account: status.user_actor, + status: status, + actors: actors, + reports: reports + } + end) + + %{ + groups: groups + } + end + + def get_reports_by_status_id(status_id) do + from(a in Activity, + where: fragment("(?)->>'type' = 'Flag'", a.data), + where: fragment("(?)->'object' \\? (?)", a.data, ^status_id) + ) + |> Activity.with_preloaded_user_actor() + |> Repo.all() + end + + @spec get_reported_status_ids() :: %{ + required(:items) => [%Activity{}], + required(:total) => integer + } + def get_reported_status_ids do + from(a in Activity, + where: fragment("(?)->>'type' = 'Flag'", a.data), + select: %{ + date: fragment("max(?->>'published') date", a.data), + activity_id: + fragment("jsonb_array_elements_text((? #- '{object,0}')->'object') activity_id", a.data) + }, + group_by: fragment("activity_id"), + order_by: fragment("date DESC") + ) + |> Repo.all() + end + def update_report_state(%Activity{} = activity, state) + when state in @strip_status_report_states do + {:ok, stripped_activity} = strip_report_status_data(activity) + + new_data = + activity.data + |> Map.put("state", state) + |> Map.put("object", stripped_activity.data["object"]) + + activity + |> Changeset.change(data: new_data) + |> Repo.update() + end + def update_report_state(%Activity{} = activity, state) when state in @supported_report_states do new_data = Map.put(activity.data, "state", state) @@@ -755,20 -702,16 +790,28 @@@ |> Repo.update() end + def update_report_state(activity_ids, state) when state in @supported_report_states do + activities_num = length(activity_ids) + + from(a in Activity, where: a.id in ^activity_ids) + |> update(set: [data: fragment("jsonb_set(data, '{state}', ?)", ^state)]) + |> Repo.update_all([]) + |> case do + {^activities_num, _} -> :ok + _ -> {:error, activity_ids} + end + end + def update_report_state(_, _), do: {:error, "Unsupported state"} + def strip_report_status_data(activity) do + [actor | reported_activities] = activity.data["object"] + stripped_activities = Enum.map(reported_activities, & &1["id"]) + new_data = put_in(activity.data, ["object"], [actor | stripped_activities]) + + {:ok, %{activity | data: new_data}} + end + def update_activity_visibility(activity, visibility) when visibility in @valid_visibilities do [to, cc, recipients] = activity diff --cc test/web/admin_api/admin_api_controller_test.exs index daa0631db,045c87e95..35367bed3 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@@ -1224,9 -1312,9 +1312,9 @@@ defmodule Pleroma.Web.AdminAPI.AdminAPI end end - describe "PUT /api/pleroma/admin/reports/:id" do + describe "PATCH /api/pleroma/admin/reports" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) [reporter, target_user] = insert_pair(:user) activity = insert(:note_activity, user: target_user) @@@ -1461,77 -1492,10 +1549,77 @@@ end end - # + describe "GET /api/pleroma/admin/grouped_reports" do + setup %{conn: conn} do + admin = insert(:user, info: %{is_admin: true}) + [reporter, target_user] = insert_pair(:user) + + date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!() + date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!() + date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!() + + first_status = + insert(:note_activity, user: target_user, data_attrs: %{"published" => date1}) + + second_status = + insert(:note_activity, user: target_user, data_attrs: %{"published" => date2}) + + third_status = + insert(:note_activity, user: target_user, data_attrs: %{"published" => date3}) + + %{ + conn: assign(conn, :user, admin), + reporter: reporter, + target_user: target_user, + first_status: first_status, + second_status: second_status, + third_status: third_status + } + end + + test "returns reports grouped by status", %{ + conn: conn, + reporter: reporter, + target_user: target_user, + first_status: first_status, + second_status: second_status, + third_status: third_status + } do + {:ok, %{id: _}} = + CommonAPI.report(reporter, %{ + "account_id" => target_user.id, + "status_ids" => [first_status.id, second_status.id, third_status.id] + }) + + {:ok, %{id: _}} = + CommonAPI.report(reporter, %{ + "account_id" => target_user.id, + "status_ids" => [first_status.id, second_status.id] + }) + + {:ok, %{id: _}} = + CommonAPI.report(reporter, %{ + "account_id" => target_user.id, + "status_ids" => [first_status.id] + }) + + response = + conn + |> get("/api/pleroma/admin/grouped_reports") + |> json_response(:ok) + + assert length(response["reports"]) == 3 + [third_group, second_group, first_group] = response["reports"] + + assert length(third_group["reports"]) == 3 + assert length(second_group["reports"]) == 2 + assert length(first_group["reports"]) == 1 + end + end + describe "POST /api/pleroma/admin/reports/:id/respond" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) %{conn: assign(conn, :user, admin), admin: admin} end