logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://anongit.hacktivis.me/git/pleroma.git/
commit: 0ec0ad85598ef42ca05d6407868bb5a2fd3ce18f
parent f1d588fd6a04945aa45bd4d1711d142de2e67c43
Author: floatingghost <hannah@coffee-and-dreams.uk>
Date:   Sat,  4 Feb 2023 20:51:17 +0000

paginate follow requests (#460)

matches https://docs.joinmastodon.org/methods/follow_requests/#get mostly

Co-authored-by: FloatingGhost <hannah@coffee-and-dreams.uk>
Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/460
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>

Diffstat:

Mlib/pleroma/following_relationship.ex18++++++++----------
Mlib/pleroma/user.ex10++++++++--
Mlib/pleroma/web/api_spec/operations/follow_request_operation.ex19+++++++++++++++++++
Mlib/pleroma/web/api_spec/operations/pleroma_follow_request_operation.ex21++++++++++++++++++++-
Mlib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex15++++++++++++---
Mlib/pleroma/web/mastodon_api/views/account_view.ex3++-
Mlib/pleroma/web/pleroma_api/controllers/follow_request_controller.ex10+++++++++-
Mtest/pleroma/web/mastodon_api/controllers/follow_request_controller_test.exs22++++++++++++++++++++++
8 files changed, 100 insertions(+), 18 deletions(-)

diff --git a/lib/pleroma/following_relationship.ex b/lib/pleroma/following_relationship.ex @@ -147,24 +147,22 @@ defmodule Pleroma.FollowingRelationship do |> Repo.aggregate(:count, :id) end - def get_follow_requests(%User{id: id}) do + def get_follow_requests_query(%User{id: id}) do __MODULE__ - |> join(:inner, [r], f in assoc(r, :follower)) + |> join(:inner, [r], f in assoc(r, :follower), as: :follower) |> where([r], r.state == ^:follow_pending) |> where([r], r.following_id == ^id) - |> where([r, f], f.is_active == true) - |> select([r, f], f) - |> Repo.all() + |> where([r, follower: f], f.is_active == true) + |> select([r, follower: f], f) end - def get_outgoing_follow_requests(%User{id: id}) do + def get_outgoing_follow_requests_query(%User{id: id}) do __MODULE__ - |> join(:inner, [r], f in assoc(r, :following)) + |> join(:inner, [r], f in assoc(r, :following), as: :following) |> where([r], r.state == ^:follow_pending) |> where([r], r.follower_id == ^id) - |> where([r, f], f.is_active == true) - |> select([r, f], f) - |> Repo.all() + |> where([r, following: f], f.is_active == true) + |> select([r, following: f], f) end def following?(%User{id: follower_id}, %User{id: followed_id}) do diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex @@ -287,8 +287,14 @@ defmodule Pleroma.User do defdelegate following(user), to: FollowingRelationship defdelegate following?(follower, followed), to: FollowingRelationship defdelegate following_ap_ids(user), to: FollowingRelationship - defdelegate get_follow_requests(user), to: FollowingRelationship - defdelegate get_outgoing_follow_requests(user), to: FollowingRelationship + defdelegate get_follow_requests_query(user), to: FollowingRelationship + defdelegate get_outgoing_follow_requests_query(user), to: FollowingRelationship + + def get_follow_requests(user) do + get_follow_requests_query(user) + |> Repo.all() + end + defdelegate search(query, opts \\ []), to: User.Search @doc """ diff --git a/lib/pleroma/web/api_spec/operations/follow_request_operation.ex b/lib/pleroma/web/api_spec/operations/follow_request_operation.ex @@ -19,6 +19,7 @@ defmodule Pleroma.Web.ApiSpec.FollowRequestOperation do summary: "Retrieve follow requests", security: [%{"oAuth" => ["read:follows", "follow"]}], operationId: "FollowRequestController.index", + parameters: pagination_params(), responses: %{ 200 => Operation.response("Array of Account", "application/json", %Schema{ @@ -62,4 +63,22 @@ defmodule Pleroma.Web.ApiSpec.FollowRequestOperation do required: true ) end + + defp pagination_params do + [ + Operation.parameter(:max_id, :query, :string, "Return items older than this ID"), + Operation.parameter( + :since_id, + :query, + :string, + "Return the oldest items newer than this ID" + ), + Operation.parameter( + :limit, + :query, + %Schema{type: :integer, default: 20}, + "Maximum number of items to return. Will be ignored if it's more than 40" + ) + ] + end end diff --git a/lib/pleroma/web/api_spec/operations/pleroma_follow_request_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_follow_request_operation.ex @@ -17,7 +17,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaFollowRequestOperation do tags: ["Follow requests"], summary: "Retrieve outgoing follow requests", security: [%{"oAuth" => ["read:follows", "follow"]}], - operationId: "PleromaFollowRequestController.outgoing", + operationId: "PleromaFollowRequestController.outgoing",, + parameters: pagination_params(), responses: %{ 200 => Operation.response("Array of Account", "application/json", %Schema{ @@ -28,4 +29,22 @@ defmodule Pleroma.Web.ApiSpec.PleromaFollowRequestOperation do } } end + + defp pagination_params do + [ + Operation.parameter(:max_id, :query, :string, "Return items older than this ID"), + Operation.parameter( + :since_id, + :query, + :string, + "Return the oldest items newer than this ID" + ), + Operation.parameter( + :limit, + :query, + %Schema{type: :integer, default: 20}, + "Maximum number of items to return. Will be ignored if it's more than 40" + ) + ] + end end diff --git a/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex b/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex @@ -5,6 +5,10 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestController do use Pleroma.Web, :controller + import Pleroma.Web.ControllerHelper, + only: [add_link_headers: 2] + + alias Pleroma.Pagination alias Pleroma.User alias Pleroma.Web.CommonAPI alias Pleroma.Web.Plugs.OAuthScopesPlug @@ -24,10 +28,15 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestController do defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.FollowRequestOperation @doc "GET /api/v1/follow_requests" - def index(%{assigns: %{user: followed}} = conn, _params) do - follow_requests = User.get_follow_requests(followed) + def index(%{assigns: %{user: followed}} = conn, params) do + follow_requests = + followed + |> User.get_follow_requests_query() + |> Pagination.fetch_paginated(params, :keyset, :follower) - render(conn, "index.json", for: followed, users: follow_requests, as: :user) + conn + |> add_link_headers(follow_requests) + |> render("index.json", for: followed, users: follow_requests, as: :user) end @doc "POST /api/v1/follow_requests/:id/authorize" diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -356,7 +356,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do %User{id: user_id} ) do count = - User.get_follow_requests(user) + user + |> User.get_follow_requests() |> length() data diff --git a/lib/pleroma/web/pleroma_api/controllers/follow_request_controller.ex b/lib/pleroma/web/pleroma_api/controllers/follow_request_controller.ex @@ -5,6 +5,10 @@ defmodule Pleroma.Web.PleromaAPI.FollowRequestController do use Pleroma.Web, :controller + import Pleroma.Web.ControllerHelper, + only: [add_link_headers: 2] + + alias Pleroma.Pagination alias Pleroma.User alias Pleroma.Web.Plugs.OAuthScopesPlug @@ -18,10 +22,14 @@ defmodule Pleroma.Web.PleromaAPI.FollowRequestController do @doc "GET /api/v1/pleroma/outgoing_follow_requests" def outgoing(%{assigns: %{user: follower}} = conn, _params) do - follow_requests = User.get_outgoing_follow_requests(follower) + follow_requests = + follower + |> User.get_outgoing_follow_requests_query() + |> Pagination.fetch_paginated(params, :keyset, :follower) conn |> put_view(Pleroma.Web.MastodonAPI.FollowRequestView) + |> add_link_headers(follow_requests) |> render("index.json", for: follower, users: follow_requests, as: :user) end end diff --git a/test/pleroma/web/mastodon_api/controllers/follow_request_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/follow_request_controller_test.exs @@ -10,6 +10,11 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do import Pleroma.Factory + defp extract_next_link_header(header) do + [_, next_link] = Regex.run(~r{<(?<next_link>.*)>; rel="next"}, header) + next_link + end + describe "locked accounts" do setup do user = insert(:user, is_locked: true) @@ -31,6 +36,23 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do assert to_string(other_user.id) == relationship["id"] end + test "/api/v1/follow_requests paginates", %{user: user, conn: conn} do + for _ <- 1..21 do + other_user = insert(:user) + {:ok, _, _, _activity} = CommonAPI.follow(other_user, user) + {:ok, _, _} = User.follow(other_user, user, :follow_pending) + end + + conn = get(conn, "/api/v1/follow_requests") + assert length(json_response_and_validate_schema(conn, 200)) == 20 + assert [link_header] = get_resp_header(conn, "link") + assert link_header =~ "rel=\"next\"" + next_link = extract_next_link_header(link_header) + assert next_link =~ "/api/v1/follow_requests" + conn = get(conn, next_link) + assert length(json_response_and_validate_schema(conn, 200)) == 1 + end + test "/api/v1/follow_requests/:id/authorize works", %{user: user, conn: conn} do other_user = insert(:user)