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>
This commit is contained in:
parent
f1d588fd6a
commit
0ec0ad8559
8 changed files with 100 additions and 18 deletions
|
|
@ -147,24 +147,22 @@ defmodule Pleroma.FollowingRelationship do
|
||||||
|> Repo.aggregate(:count, :id)
|
|> Repo.aggregate(:count, :id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_follow_requests(%User{id: id}) do
|
def get_follow_requests_query(%User{id: id}) do
|
||||||
__MODULE__
|
__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.state == ^:follow_pending)
|
||||||
|> where([r], r.following_id == ^id)
|
|> where([r], r.following_id == ^id)
|
||||||
|> where([r, f], f.is_active == true)
|
|> where([r, follower: f], f.is_active == true)
|
||||||
|> select([r, f], f)
|
|> select([r, follower: f], f)
|
||||||
|> Repo.all()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_outgoing_follow_requests(%User{id: id}) do
|
def get_outgoing_follow_requests_query(%User{id: id}) do
|
||||||
__MODULE__
|
__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.state == ^:follow_pending)
|
||||||
|> where([r], r.follower_id == ^id)
|
|> where([r], r.follower_id == ^id)
|
||||||
|> where([r, f], f.is_active == true)
|
|> where([r, following: f], f.is_active == true)
|
||||||
|> select([r, f], f)
|
|> select([r, following: f], f)
|
||||||
|> Repo.all()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def following?(%User{id: follower_id}, %User{id: followed_id}) do
|
def following?(%User{id: follower_id}, %User{id: followed_id}) do
|
||||||
|
|
|
||||||
|
|
@ -287,8 +287,14 @@ defmodule Pleroma.User do
|
||||||
defdelegate following(user), to: FollowingRelationship
|
defdelegate following(user), to: FollowingRelationship
|
||||||
defdelegate following?(follower, followed), to: FollowingRelationship
|
defdelegate following?(follower, followed), to: FollowingRelationship
|
||||||
defdelegate following_ap_ids(user), to: FollowingRelationship
|
defdelegate following_ap_ids(user), to: FollowingRelationship
|
||||||
defdelegate get_follow_requests(user), to: FollowingRelationship
|
defdelegate get_follow_requests_query(user), to: FollowingRelationship
|
||||||
defdelegate get_outgoing_follow_requests(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
|
defdelegate search(query, opts \\ []), to: User.Search
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ defmodule Pleroma.Web.ApiSpec.FollowRequestOperation do
|
||||||
summary: "Retrieve follow requests",
|
summary: "Retrieve follow requests",
|
||||||
security: [%{"oAuth" => ["read:follows", "follow"]}],
|
security: [%{"oAuth" => ["read:follows", "follow"]}],
|
||||||
operationId: "FollowRequestController.index",
|
operationId: "FollowRequestController.index",
|
||||||
|
parameters: pagination_params(),
|
||||||
responses: %{
|
responses: %{
|
||||||
200 =>
|
200 =>
|
||||||
Operation.response("Array of Account", "application/json", %Schema{
|
Operation.response("Array of Account", "application/json", %Schema{
|
||||||
|
|
@ -62,4 +63,22 @@ defmodule Pleroma.Web.ApiSpec.FollowRequestOperation do
|
||||||
required: true
|
required: true
|
||||||
)
|
)
|
||||||
end
|
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
|
end
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaFollowRequestOperation do
|
||||||
tags: ["Follow requests"],
|
tags: ["Follow requests"],
|
||||||
summary: "Retrieve outgoing follow requests",
|
summary: "Retrieve outgoing follow requests",
|
||||||
security: [%{"oAuth" => ["read:follows", "follow"]}],
|
security: [%{"oAuth" => ["read:follows", "follow"]}],
|
||||||
operationId: "PleromaFollowRequestController.outgoing",
|
operationId: "PleromaFollowRequestController.outgoing",,
|
||||||
|
parameters: pagination_params(),
|
||||||
responses: %{
|
responses: %{
|
||||||
200 =>
|
200 =>
|
||||||
Operation.response("Array of Account", "application/json", %Schema{
|
Operation.response("Array of Account", "application/json", %Schema{
|
||||||
|
|
@ -28,4 +29,22 @@ defmodule Pleroma.Web.ApiSpec.PleromaFollowRequestOperation do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
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
|
end
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,10 @@
|
||||||
defmodule Pleroma.Web.MastodonAPI.FollowRequestController do
|
defmodule Pleroma.Web.MastodonAPI.FollowRequestController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
import Pleroma.Web.ControllerHelper,
|
||||||
|
only: [add_link_headers: 2]
|
||||||
|
|
||||||
|
alias Pleroma.Pagination
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
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
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.FollowRequestOperation
|
||||||
|
|
||||||
@doc "GET /api/v1/follow_requests"
|
@doc "GET /api/v1/follow_requests"
|
||||||
def index(%{assigns: %{user: followed}} = conn, _params) do
|
def index(%{assigns: %{user: followed}} = conn, params) do
|
||||||
follow_requests = User.get_follow_requests(followed)
|
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
|
end
|
||||||
|
|
||||||
@doc "POST /api/v1/follow_requests/:id/authorize"
|
@doc "POST /api/v1/follow_requests/:id/authorize"
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
||||||
%User{id: user_id}
|
%User{id: user_id}
|
||||||
) do
|
) do
|
||||||
count =
|
count =
|
||||||
User.get_follow_requests(user)
|
user
|
||||||
|
|> User.get_follow_requests()
|
||||||
|> length()
|
|> length()
|
||||||
|
|
||||||
data
|
data
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,10 @@
|
||||||
defmodule Pleroma.Web.PleromaAPI.FollowRequestController do
|
defmodule Pleroma.Web.PleromaAPI.FollowRequestController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
import Pleroma.Web.ControllerHelper,
|
||||||
|
only: [add_link_headers: 2]
|
||||||
|
|
||||||
|
alias Pleroma.Pagination
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||||
|
|
||||||
|
|
@ -18,10 +22,14 @@ defmodule Pleroma.Web.PleromaAPI.FollowRequestController do
|
||||||
|
|
||||||
@doc "GET /api/v1/pleroma/outgoing_follow_requests"
|
@doc "GET /api/v1/pleroma/outgoing_follow_requests"
|
||||||
def outgoing(%{assigns: %{user: follower}} = conn, _params) do
|
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
|
conn
|
||||||
|> put_view(Pleroma.Web.MastodonAPI.FollowRequestView)
|
|> put_view(Pleroma.Web.MastodonAPI.FollowRequestView)
|
||||||
|
|> add_link_headers(follow_requests)
|
||||||
|> render("index.json", for: follower, users: follow_requests, as: :user)
|
|> render("index.json", for: follower, users: follow_requests, as: :user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,11 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
|
||||||
|
|
||||||
import Pleroma.Factory
|
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
|
describe "locked accounts" do
|
||||||
setup do
|
setup do
|
||||||
user = insert(:user, is_locked: true)
|
user = insert(:user, is_locked: true)
|
||||||
|
|
@ -31,6 +36,23 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
|
||||||
assert to_string(other_user.id) == relationship["id"]
|
assert to_string(other_user.id) == relationship["id"]
|
||||||
end
|
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
|
test "/api/v1/follow_requests/:id/authorize works", %{user: user, conn: conn} do
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue