Unilateral remove from followers (#232)
from https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3647/ Co-authored-by: marcin mikołajczak <git@mkljczk.pl> Co-authored-by: Tusooa Zhu <tusooa@kazv.moe> Co-authored-by: FloatingGhost <hannah@coffee-and-dreams.uk> Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/232
This commit is contained in:
parent
5231d436d1
commit
f36d14818d
|
@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
- Officially supported docker release
|
- Officially supported docker release
|
||||||
|
- Ability to remove followers unilaterally without a block
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
- Follows no longer override domain blocks, a domain block is final
|
- Follows no longer override domain blocks, a domain block is final
|
||||||
|
|
|
@ -334,6 +334,22 @@ def unblock_operation do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_from_followers_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Account actions"],
|
||||||
|
summary: "Remove from followers",
|
||||||
|
operationId: "AccountController.remove_from_followers",
|
||||||
|
security: [%{"oAuth" => ["follow", "write:follows"]}],
|
||||||
|
description: "Remove the given account from followers",
|
||||||
|
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Relationship", "application/json", AccountRelationship),
|
||||||
|
400 => Operation.response("Error", "application/json", ApiError),
|
||||||
|
404 => Operation.response("Error", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def note_operation do
|
def note_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Account actions"],
|
tags: ["Account actions"],
|
||||||
|
|
|
@ -76,15 +76,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
%{scopes: ["follow", "write:follows"]} when action in [:follow_by_uri, :follow, :unfollow]
|
%{scopes: ["follow", "write:follows"]}
|
||||||
|
when action in [:follow_by_uri, :follow, :unfollow, :remove_from_followers]
|
||||||
)
|
)
|
||||||
|
|
||||||
plug(OAuthScopesPlug, %{scopes: ["follow", "read:mutes"]} when action == :mutes)
|
plug(OAuthScopesPlug, %{scopes: ["follow", "read:mutes"]} when action == :mutes)
|
||||||
|
|
||||||
plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action in [:mute, :unmute])
|
plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action in [:mute, :unmute])
|
||||||
|
|
||||||
@relationship_actions [:follow, :unfollow]
|
@relationship_actions [:follow, :unfollow, :remove_from_followers]
|
||||||
@needs_account ~W(followers following lists follow unfollow mute unmute block unblock note)a
|
@needs_account ~W(followers following lists follow unfollow mute unmute block unblock note remove_from_followers)a
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
RateLimiter,
|
RateLimiter,
|
||||||
|
@ -447,6 +448,20 @@ def note(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc "POST /api/v1/accounts/:id/remove_from_followers"
|
||||||
|
def remove_from_followers(%{assigns: %{user: %{id: id}, account: %{id: id}}}, _params) do
|
||||||
|
{:error, "Can not unfollow yourself"}
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_from_followers(%{assigns: %{user: followed, account: follower}} = conn, _params) do
|
||||||
|
with {:ok, follower} <- CommonAPI.reject_follow_request(follower, followed) do
|
||||||
|
render(conn, "relationship.json", user: followed, target: follower)
|
||||||
|
else
|
||||||
|
nil ->
|
||||||
|
render_error(conn, :not_found, "Record not found")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@doc "POST /api/v1/follows"
|
@doc "POST /api/v1/follows"
|
||||||
def follow_by_uri(%{body_params: %{uri: uri}} = conn, _) do
|
def follow_by_uri(%{body_params: %{uri: uri}} = conn, _) do
|
||||||
case User.get_cached_by_nickname(uri) do
|
case User.get_cached_by_nickname(uri) do
|
||||||
|
|
|
@ -509,6 +509,7 @@ defmodule Pleroma.Web.Router do
|
||||||
post("/accounts/:id/mute", AccountController, :mute)
|
post("/accounts/:id/mute", AccountController, :mute)
|
||||||
post("/accounts/:id/unmute", AccountController, :unmute)
|
post("/accounts/:id/unmute", AccountController, :unmute)
|
||||||
post("/accounts/:id/note", AccountController, :note)
|
post("/accounts/:id/note", AccountController, :note)
|
||||||
|
post("/accounts/:id/remove_from_followers", AccountController, :remove_from_followers)
|
||||||
|
|
||||||
get("/conversations", ConversationController, :index)
|
get("/conversations", ConversationController, :index)
|
||||||
post("/conversations/:id/read", ConversationController, :mark_as_read)
|
post("/conversations/:id/read", ConversationController, :mark_as_read)
|
||||||
|
|
|
@ -311,7 +311,7 @@ test "local users do not automatically follow local locked accounts" do
|
||||||
describe "unfollow/2" do
|
describe "unfollow/2" do
|
||||||
setup do: clear_config([:instance, :external_user_synchronization])
|
setup do: clear_config([:instance, :external_user_synchronization])
|
||||||
|
|
||||||
test "unfollow with syncronizes external user" do
|
test "unfollow with synchronizes external user" do
|
||||||
clear_config([:instance, :external_user_synchronization], true)
|
clear_config([:instance, :external_user_synchronization], true)
|
||||||
|
|
||||||
followed =
|
followed =
|
||||||
|
@ -2260,7 +2260,7 @@ test "updates the counters normally on following/getting a follow when disabled"
|
||||||
assert other_user.follower_count == 1
|
assert other_user.follower_count == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
test "syncronizes the counters with the remote instance for the followed when enabled" do
|
test "synchronizes the counters with the remote instance for the followed when enabled" do
|
||||||
clear_config([:instance, :external_user_synchronization], false)
|
clear_config([:instance, :external_user_synchronization], false)
|
||||||
|
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
@ -2282,7 +2282,7 @@ test "syncronizes the counters with the remote instance for the followed when en
|
||||||
assert other_user.follower_count == 437
|
assert other_user.follower_count == 437
|
||||||
end
|
end
|
||||||
|
|
||||||
test "syncronizes the counters with the remote instance for the follower when enabled" do
|
test "synchronizes the counters with the remote instance for the follower when enabled" do
|
||||||
clear_config([:instance, :external_user_synchronization], false)
|
clear_config([:instance, :external_user_synchronization], false)
|
||||||
|
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
|
@ -1632,7 +1632,7 @@ test "fetches only public posts for other users" do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "fetch_follow_information_for_user" do
|
describe "fetch_follow_information_for_user" do
|
||||||
test "syncronizes following/followers counters" do
|
test "synchronizes following/followers counters" do
|
||||||
user =
|
user =
|
||||||
insert(:user,
|
insert(:user,
|
||||||
local: false,
|
local: false,
|
||||||
|
|
|
@ -1921,4 +1921,48 @@ test "create a note on a user" do
|
||||||
|> get("/api/v1/accounts/relationships?id=#{other_user.id}")
|
|> get("/api/v1/accounts/relationships?id=#{other_user.id}")
|
||||||
|> json_response_and_validate_schema(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "remove from followers" do
|
||||||
|
setup do: oauth_access(["follow"])
|
||||||
|
|
||||||
|
test "removing user from followers", %{conn: conn, user: user} do
|
||||||
|
%{id: other_user_id} = other_user = insert(:user)
|
||||||
|
|
||||||
|
CommonAPI.follow(other_user, user)
|
||||||
|
|
||||||
|
assert %{"id" => ^other_user_id, "followed_by" => false} =
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/accounts/#{other_user_id}/remove_from_followers")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
refute User.following?(other_user, user)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "removing remote user from followers", %{conn: conn, user: user} do
|
||||||
|
%{id: other_user_id} = other_user = insert(:user, local: false)
|
||||||
|
|
||||||
|
CommonAPI.follow(other_user, user)
|
||||||
|
|
||||||
|
assert User.following?(other_user, user)
|
||||||
|
|
||||||
|
assert %{"id" => ^other_user_id, "followed_by" => false} =
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/accounts/#{other_user_id}/remove_from_followers")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
refute User.following?(other_user, user)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "removing user from followers errors", %{user: user, conn: conn} do
|
||||||
|
# self remove
|
||||||
|
conn_res = post(conn, "/api/v1/accounts/#{user.id}/remove_from_followers")
|
||||||
|
|
||||||
|
assert %{"error" => "Can not unfollow yourself"} =
|
||||||
|
json_response_and_validate_schema(conn_res, 400)
|
||||||
|
|
||||||
|
# remove non existing user
|
||||||
|
conn_res = post(conn, "/api/v1/accounts/doesntexist/remove_from_followers")
|
||||||
|
assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue