Browse Source

Merge branch 'cancel-follow-request' into 'develop'

Add support for cancellation of a follow request

Closes #1522

See merge request pleroma/pleroma!2175
floki-fast_html-2-electric-boogalo
Haelwenn 4 years ago
parent
commit
1262357ddb
7 changed files with 115 additions and 11 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +1
    -1
      lib/pleroma/following_relationship.ex
  3. +33
    -10
      lib/pleroma/user.ex
  4. +9
    -0
      lib/pleroma/web/activity_pub/utils.ex
  5. +17
    -0
      test/web/activity_pub/activity_pub_test.exs
  6. +44
    -0
      test/web/common_api/common_api_test.exs
  7. +10
    -0
      test/web/mastodon_api/controllers/account_controller_test.exs

+ 1
- 0
CHANGELOG.md View File

@@ -121,6 +121,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- OTP releases: Not being able to configure OAuth expired token cleanup interval
- OTP releases: Not being able to configure HTML sanitization policy
- Favorites timeline now ordered by favorite date instead of post date
- Support for cancellation of a follow request
<details>
<summary>API Changes</summary>



+ 1
- 1
lib/pleroma/following_relationship.ex View File

@@ -58,8 +58,8 @@ defmodule Pleroma.FollowingRelationship do

def unfollow(%User{} = follower, %User{} = following) do
case get(follower, following) do
nil -> {:ok, nil}
%__MODULE__{} = following_relationship -> Repo.delete(following_relationship)
_ -> {:ok, nil}
end
end



+ 33
- 10
lib/pleroma/user.ex View File

@@ -647,25 +647,48 @@ defmodule Pleroma.User do
end
end

def unfollow(%User{ap_id: ap_id}, %User{ap_id: ap_id}) do
{:error, "Not subscribed!"}
end

def unfollow(%User{} = follower, %User{} = followed) do
if following?(follower, followed) and follower.ap_id != followed.ap_id do
FollowingRelationship.unfollow(follower, followed)
case get_follow_state(follower, followed) do
state when state in ["accept", "pending"] ->
FollowingRelationship.unfollow(follower, followed)
{:ok, followed} = update_follower_count(followed)

{:ok, followed} = update_follower_count(followed)
{:ok, follower} =
follower
|> update_following_count()
|> set_cache()

{:ok, follower} =
follower
|> update_following_count()
|> set_cache()
{:ok, follower, Utils.fetch_latest_follow(follower, followed)}

{:ok, follower, Utils.fetch_latest_follow(follower, followed)}
else
{:error, "Not subscribed!"}
nil ->
{:error, "Not subscribed!"}
end
end

defdelegate following?(follower, followed), to: FollowingRelationship

def get_follow_state(%User{} = follower, %User{} = following) do
following_relationship = FollowingRelationship.get(follower, following)

case {following_relationship, following.local} do
{nil, false} ->
case Utils.fetch_latest_follow(follower, following) do
%{data: %{"state" => state}} when state in ["pending", "accept"] -> state
_ -> nil
end

{%{state: state}, _} ->
state

{nil, _} ->
nil
end
end

def locked?(%User{} = user) do
user.locked || false
end


+ 9
- 0
lib/pleroma/web/activity_pub/utils.ex View File

@@ -490,6 +490,15 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|> Repo.one()
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
%{data: %{"object" => object_ap_id}} = Activity.get_by_id(internal_activity_id)



+ 17
- 0
test/web/activity_pub/activity_pub_test.exs View File

@@ -1174,6 +1174,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert embedded_object["object"] == followed.ap_id
assert embedded_object["id"] == follow_activity.data["id"]
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

describe "blocking / unblocking" do


+ 44
- 0
test/web/common_api/common_api_test.exs View File

@@ -551,6 +551,50 @@ defmodule Pleroma.Web.CommonAPITest do

refute User.subscribed_to?(follower, followed)
end

test "cancels a pending follow for a local user" do
follower = insert(:user)
followed = insert(:user, locked: true)

assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
CommonAPI.follow(follower, followed)

assert User.get_follow_state(follower, followed) == "pending"
assert {:ok, follower} = CommonAPI.unfollow(follower, followed)
assert User.get_follow_state(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

test "cancels a pending follow for a remote user" do
follower = insert(:user)
followed = insert(:user, locked: true, local: false, ap_enabled: true)

assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
CommonAPI.follow(follower, followed)

assert User.get_follow_state(follower, followed) == "pending"
assert {:ok, follower} = CommonAPI.unfollow(follower, followed)
assert User.get_follow_state(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

describe "accept_follow_request/2" do


+ 10
- 0
test/web/mastodon_api/controllers/account_controller_test.exs View File

@@ -457,6 +457,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert id == to_string(other_user.id)
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
%{conn: conn} = oauth_access(["follow", "read:statuses"])
followed = insert(:user)


Loading…
Cancel
Save