Merge branch 'fix/2411-mutes-api' into 'develop'

Support for with_relationships parameter

Closes #2411

See merge request pleroma/pleroma!3290
This commit is contained in:
feld 2021-02-02 18:08:46 +00:00
commit 0888815000
5 changed files with 154 additions and 10 deletions

View file

@ -51,6 +51,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- WebPush: Introduce `pleroma:chat_mention` and `pleroma:emoji_reaction` notification types. - WebPush: Introduce `pleroma:chat_mention` and `pleroma:emoji_reaction` notification types.
- Mastodon API: Add monthly active users to `/api/v1/instance` (`pleroma.stats.mau`). - Mastodon API: Add monthly active users to `/api/v1/instance` (`pleroma.stats.mau`).
- Mastodon API: Home, public, hashtag & list timelines accept `only_media`, `remote` & `local` parameters for filtration. - Mastodon API: Home, public, hashtag & list timelines accept `only_media`, `remote` & `local` parameters for filtration.
- Mastodon API: `/api/v1/accounts/:id` & `/api/v1/mutes` endpoints accept `with_relationships` parameter and return filled `pleroma.relationship` field.
</details> </details>
### Fixed ### Fixed

View file

@ -70,6 +70,13 @@ The `id` parameter can also be the `nickname` of the user. This only works in th
- `exclude_replies`: exclude replies - `exclude_replies`: exclude replies
- `exclude_visibilities`: exclude visibilities - `exclude_visibilities`: exclude visibilities
Endpoints which accept `with_relationships` parameter:
- `/api/v1/accounts/:id`
- `/api/v1/accounts/:id/followers`
- `/api/v1/accounts/:id/following`
- `/api/v1/mutes`
Has these additional fields under the `pleroma` object: Has these additional fields under the `pleroma` object:
- `ap_id`: nullable URL string, ActivityPub id of the user - `ap_id`: nullable URL string, ActivityPub id of the user

View file

@ -99,7 +99,10 @@ def show_operation do
summary: "Account", summary: "Account",
operationId: "AccountController.show", operationId: "AccountController.show",
description: "View information about a profile.", description: "View information about a profile.",
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}], parameters: [
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
with_relationships_param()
],
responses: %{ responses: %{
200 => Operation.response("Account", "application/json", Account), 200 => Operation.response("Account", "application/json", Account),
401 => Operation.response("Error", "application/json", ApiError), 401 => Operation.response("Error", "application/json", ApiError),
@ -347,7 +350,7 @@ def mutes_operation do
operationId: "AccountController.mutes", operationId: "AccountController.mutes",
description: "Accounts the user has muted.", description: "Accounts the user has muted.",
security: [%{"oAuth" => ["follow", "read:mutes"]}], security: [%{"oAuth" => ["follow", "read:mutes"]}],
parameters: pagination_params(), parameters: [with_relationships_param() | pagination_params()],
responses: %{ responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts()) 200 => Operation.response("Accounts", "application/json", array_of_accounts())
} }

View file

@ -269,10 +269,14 @@ def relationships(%{assigns: %{user: user}} = conn, %{id: id}) do
def relationships(%{assigns: %{user: _user}} = conn, _), do: json(conn, []) def relationships(%{assigns: %{user: _user}} = conn, _), do: json(conn, [])
@doc "GET /api/v1/accounts/:id" @doc "GET /api/v1/accounts/:id"
def show(%{assigns: %{user: for_user}} = conn, %{id: nickname_or_id}) do def show(%{assigns: %{user: for_user}} = conn, %{id: nickname_or_id} = params) do
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id, for: for_user), with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id, for: for_user),
:visible <- User.visible_for(user, for_user) do :visible <- User.visible_for(user, for_user) do
render(conn, "show.json", user: user, for: for_user) render(conn, "show.json",
user: user,
for: for_user,
embed_relationships: embed_relationships?(params)
)
else else
error -> user_visibility_error(conn, error) error -> user_visibility_error(conn, error)
end end
@ -454,7 +458,12 @@ def mutes(%{assigns: %{user: user}} = conn, params) do
conn conn
|> add_link_headers(users) |> add_link_headers(users)
|> render("index.json", users: users, for: user, as: :user) |> render("index.json",
users: users,
for: user,
as: :user,
embed_relationships: embed_relationships?(params)
)
end end
@doc "GET /api/v1/blocks" @doc "GET /api/v1/blocks"

View file

@ -29,6 +29,45 @@ test "works by id" do
|> json_response_and_validate_schema(404) |> json_response_and_validate_schema(404)
end end
test "relationship field" do
%{conn: conn, user: user} = oauth_access(["read"])
other_user = insert(:user)
response =
conn
|> get("/api/v1/accounts/#{other_user.id}")
|> json_response_and_validate_schema(200)
assert response["id"] == other_user.id
assert response["pleroma"]["relationship"] == %{}
assert %{"pleroma" => %{"relationship" => %{"following" => false, "followed_by" => false}}} =
conn
|> get("/api/v1/accounts/#{other_user.id}?with_relationships=true")
|> json_response_and_validate_schema(200)
{:ok, _, %{id: other_id}} = User.follow(user, other_user)
assert %{
"id" => ^other_id,
"pleroma" => %{"relationship" => %{"following" => true, "followed_by" => false}}
} =
conn
|> get("/api/v1/accounts/#{other_id}?with_relationships=true")
|> json_response_and_validate_schema(200)
{:ok, _, _} = User.follow(other_user, user)
assert %{
"id" => ^other_id,
"pleroma" => %{"relationship" => %{"following" => true, "followed_by" => true}}
} =
conn
|> get("/api/v1/accounts/#{other_id}?with_relationships=true")
|> json_response_and_validate_schema(200)
end
test "works by nickname" do test "works by nickname" do
user = insert(:user) user = insert(:user)
@ -590,6 +629,45 @@ test "getting followers", %{user: user, conn: conn} do
assert [%{"id" => ^user_id}] = json_response_and_validate_schema(conn, 200) assert [%{"id" => ^user_id}] = json_response_and_validate_schema(conn, 200)
end end
test "following with relationship", %{conn: conn, user: user} do
other_user = insert(:user)
{:ok, %{id: id}, _} = User.follow(other_user, user)
assert [
%{
"id" => ^id,
"pleroma" => %{
"relationship" => %{
"id" => ^id,
"following" => false,
"followed_by" => true
}
}
}
] =
conn
|> get("/api/v1/accounts/#{user.id}/followers?with_relationships=true")
|> json_response_and_validate_schema(200)
{:ok, _, _} = User.follow(user, other_user)
assert [
%{
"id" => ^id,
"pleroma" => %{
"relationship" => %{
"id" => ^id,
"following" => true,
"followed_by" => true
}
}
}
] =
conn
|> get("/api/v1/accounts/#{user.id}/followers?with_relationships=true")
|> json_response_and_validate_schema(200)
end
test "getting followers, hide_followers", %{user: user, conn: conn} do test "getting followers, hide_followers", %{user: user, conn: conn} do
other_user = insert(:user, hide_followers: true) other_user = insert(:user, hide_followers: true)
{:ok, _user, _other_user} = User.follow(user, other_user) {:ok, _user, _other_user} = User.follow(user, other_user)
@ -660,6 +738,24 @@ test "getting following", %{user: user, conn: conn} do
assert id == to_string(other_user.id) assert id == to_string(other_user.id)
end end
test "following with relationship", %{conn: conn, user: user} do
other_user = insert(:user)
{:ok, user, other_user} = User.follow(user, other_user)
conn = get(conn, "/api/v1/accounts/#{user.id}/following?with_relationships=true")
id = other_user.id
assert [
%{
"id" => ^id,
"pleroma" => %{
"relationship" => %{"id" => ^id, "following" => true, "followed_by" => false}
}
}
] = json_response_and_validate_schema(conn, 200)
end
test "getting following, hide_follows, other user requesting" do test "getting following, hide_follows, other user requesting" do
user = insert(:user, hide_follows: true) user = insert(:user, hide_follows: true)
other_user = insert(:user) other_user = insert(:user)
@ -1565,7 +1661,6 @@ test "getting a list of mutes" do
result = result =
conn conn
|> assign(:user, user)
|> get("/api/v1/mutes") |> get("/api/v1/mutes")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
@ -1573,7 +1668,6 @@ test "getting a list of mutes" do
result = result =
conn conn
|> assign(:user, user)
|> get("/api/v1/mutes?limit=1") |> get("/api/v1/mutes?limit=1")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
@ -1581,7 +1675,6 @@ test "getting a list of mutes" do
result = result =
conn conn
|> assign(:user, user)
|> get("/api/v1/mutes?since_id=#{id1}") |> get("/api/v1/mutes?since_id=#{id1}")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
@ -1589,7 +1682,6 @@ test "getting a list of mutes" do
result = result =
conn conn
|> assign(:user, user)
|> get("/api/v1/mutes?since_id=#{id1}&max_id=#{id3}") |> get("/api/v1/mutes?since_id=#{id1}&max_id=#{id3}")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
@ -1597,13 +1689,45 @@ test "getting a list of mutes" do
result = result =
conn conn
|> assign(:user, user)
|> get("/api/v1/mutes?since_id=#{id1}&limit=1") |> get("/api/v1/mutes?since_id=#{id1}&limit=1")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
assert [%{"id" => ^id2}] = result assert [%{"id" => ^id2}] = result
end end
test "list of mutes with with_relationships parameter" do
%{user: user, conn: conn} = oauth_access(["read:mutes"])
%{id: id1} = other_user1 = insert(:user)
%{id: id2} = other_user2 = insert(:user)
%{id: id3} = other_user3 = insert(:user)
{:ok, _, _} = User.follow(other_user1, user)
{:ok, _, _} = User.follow(other_user2, user)
{:ok, _, _} = User.follow(other_user3, user)
{:ok, _} = User.mute(user, other_user1)
{:ok, _} = User.mute(user, other_user2)
{:ok, _} = User.mute(user, other_user3)
assert [
%{
"id" => ^id1,
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
},
%{
"id" => ^id2,
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
},
%{
"id" => ^id3,
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
}
] =
conn
|> get("/api/v1/mutes?with_relationships=true")
|> json_response_and_validate_schema(200)
end
test "getting a list of blocks" do test "getting a list of blocks" do
%{user: user, conn: conn} = oauth_access(["read:blocks"]) %{user: user, conn: conn} = oauth_access(["read:blocks"])
%{id: id1} = other_user1 = insert(:user) %{id: id1} = other_user1 = insert(:user)