Add support for cancellation of a follow request

This commit is contained in:
Egor Kislitsyn 2020-02-04 20:35:32 +04:00
parent c27d1d65bf
commit 8c71f7e11a
5 changed files with 75 additions and 10 deletions

View File

@ -647,10 +647,14 @@ def follow(%User{} = follower, %User{} = followed, state \\ "accept") do
end end
end end
def unfollow(%User{} = follower, %User{} = followed) do def unfollow(%User{ap_id: ap_id}, %User{ap_id: ap_id}) do
if following?(follower, followed) and follower.ap_id != followed.ap_id do {:error, "Not subscribed!"}
FollowingRelationship.unfollow(follower, followed) end
def unfollow(%User{} = follower, %User{} = followed) do
case FollowingRelationship.get(follower, followed) do
%{state: state} when state in ["accept", "pending"] ->
FollowingRelationship.unfollow(follower, followed)
{:ok, followed} = update_follower_count(followed) {:ok, followed} = update_follower_count(followed)
{:ok, follower} = {:ok, follower} =
@ -659,7 +663,8 @@ def unfollow(%User{} = follower, %User{} = followed) do
|> set_cache() |> set_cache()
{:ok, follower, Utils.fetch_latest_follow(follower, followed)} {:ok, follower, Utils.fetch_latest_follow(follower, followed)}
else
nil ->
{:error, "Not subscribed!"} {:error, "Not subscribed!"}
end end
end end

View File

@ -490,6 +490,15 @@ def fetch_latest_follow(%User{ap_id: follower_id}, %User{ap_id: followed_id}) do
|> Repo.one() |> Repo.one()
end end
def fetch_latest_undo(%User{ap_id: ap_id}) do
"Undo"
|> Activity.Queries.by_type()
|> where(actor: ^ap_id)
|> order_by([activity], fragment("? desc nulls last", activity.id))
|> limit(1)
|> Repo.one()
end
def get_latest_reaction(internal_activity_id, %{ap_id: ap_id}, emoji) do def get_latest_reaction(internal_activity_id, %{ap_id: ap_id}, emoji) do
%{data: %{"object" => object_ap_id}} = Activity.get_by_id(internal_activity_id) %{data: %{"object" => object_ap_id}} = Activity.get_by_id(internal_activity_id)

View File

@ -1174,6 +1174,23 @@ test "creates an undo activity for the last follow" do
assert embedded_object["object"] == followed.ap_id assert embedded_object["object"] == followed.ap_id
assert embedded_object["id"] == follow_activity.data["id"] assert embedded_object["id"] == follow_activity.data["id"]
end end
test "creates an undo activity for a pending follow request" do
follower = insert(:user)
followed = insert(:user, %{locked: true})
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
{:ok, activity} = ActivityPub.unfollow(follower, followed)
assert activity.data["type"] == "Undo"
assert activity.data["actor"] == follower.ap_id
embedded_object = activity.data["object"]
assert is_map(embedded_object)
assert embedded_object["type"] == "Follow"
assert embedded_object["object"] == followed.ap_id
assert embedded_object["id"] == follow_activity.data["id"]
end
end end
describe "blocking / unblocking" do describe "blocking / unblocking" do

View File

@ -536,6 +536,30 @@ test "also unsubscribes a user" do
refute User.subscribed_to?(follower, followed) refute User.subscribed_to?(follower, followed)
end end
test "cancels a pending follow" do
follower = insert(:user)
followed = insert(:user, locked: true)
assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
CommonAPI.follow(follower, followed)
assert %{state: "pending"} = Pleroma.FollowingRelationship.get(follower, followed)
assert {:ok, follower} = CommonAPI.unfollow(follower, followed)
assert Pleroma.FollowingRelationship.get(follower, followed) == nil
assert %{id: ^activity_id, data: %{"state" => "cancelled"}} =
Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(follower, followed)
assert %{
data: %{
"type" => "Undo",
"object" => %{"type" => "Follow", "state" => "cancelled"}
}
} = Pleroma.Web.ActivityPub.Utils.fetch_latest_undo(follower)
end
end end
describe "accept_follow_request/2" do describe "accept_follow_request/2" do

View File

@ -457,6 +457,16 @@ test "following / unfollowing a user", %{conn: conn} do
assert id == to_string(other_user.id) assert id == to_string(other_user.id)
end end
test "cancelling follow request", %{conn: conn} do
%{id: other_user_id} = insert(:user, %{locked: true})
assert %{"id" => ^other_user_id, "following" => false, "requested" => true} =
conn |> post("/api/v1/accounts/#{other_user_id}/follow") |> json_response(:ok)
assert %{"id" => ^other_user_id, "following" => false, "requested" => false} =
conn |> post("/api/v1/accounts/#{other_user_id}/unfollow") |> json_response(:ok)
end
test "following without reblogs" do test "following without reblogs" do
%{conn: conn} = oauth_access(["follow", "read:statuses"]) %{conn: conn} = oauth_access(["follow", "read:statuses"])
followed = insert(:user) followed = insert(:user)