Merge branch 'feature/mastoapi-accounts-external' into 'develop'

Mastdon API: Add ability to get a remote account by nickname to `/api/v1/accounts/:id`

See merge request pleroma/pleroma!1622
This commit is contained in:
Haelwenn 2019-09-05 12:48:27 +00:00
commit fe7cf44c40
5 changed files with 131 additions and 24 deletions

View file

@ -0,0 +1,40 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Plugs.TrailingFormatPlug do
@moduledoc "Calls TrailingFormatPlug for specific paths. Ideally we would just do this in the router, but TrailingFormatPlug needs to be called before Plug.Parsers."
@behaviour Plug
@paths [
"/api/statusnet",
"/api/statuses",
"/api/qvitter",
"/api/search",
"/api/account",
"/api/friends",
"/api/mutes",
"/api/media",
"/api/favorites",
"/api/blocks",
"/api/friendships",
"/api/users",
"/users",
"/nodeinfo",
"/api/help",
"/api/externalprofile",
"/notice"
]
def init(opts) do
TrailingFormatPlug.init(opts)
end
for path <- @paths do
def call(%{request_path: unquote(path) <> _} = conn, opts) do
TrailingFormatPlug.call(conn, opts)
end
end
def call(conn, _opts), do: conn
end

View file

@ -569,8 +569,22 @@ defmodule Pleroma.User do
end) end)
end end
def get_cached_by_nickname_or_id(nickname_or_id) do def get_cached_by_nickname_or_id(nickname_or_id, opts \\ []) do
get_cached_by_id(nickname_or_id) || get_cached_by_nickname(nickname_or_id) restrict_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
cond do
is_integer(nickname_or_id) or Pleroma.FlakeId.is_flake_id?(nickname_or_id) ->
get_cached_by_id(nickname_or_id) || get_cached_by_nickname(nickname_or_id)
restrict_to_local == false ->
get_cached_by_nickname(nickname_or_id)
restrict_to_local == :unauthenticated and match?(%User{}, opts[:for]) ->
get_cached_by_nickname(nickname_or_id)
true ->
nil
end
end end
def get_by_nickname(nickname) do def get_by_nickname(nickname) do

View file

@ -57,7 +57,7 @@ defmodule Pleroma.Web.Endpoint do
plug(Phoenix.CodeReloader) plug(Phoenix.CodeReloader)
end end
plug(TrailingFormatPlug) plug(Pleroma.Plugs.TrailingFormatPlug)
plug(Plug.RequestId) plug(Plug.RequestId)
plug(Plug.Logger) plug(Plug.Logger)

View file

@ -290,7 +290,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end end
def user(%{assigns: %{user: for_user}} = conn, %{"id" => nickname_or_id}) do def user(%{assigns: %{user: for_user}} = conn, %{"id" => nickname_or_id}) do
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id), with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id, for: for_user),
true <- User.auth_active?(user) || user.id == for_user.id || User.superuser?(for_user) do true <- User.auth_active?(user) || user.id == for_user.id || User.superuser?(for_user) do
account = AccountView.render("account.json", %{user: user, for: for_user}) account = AccountView.render("account.json", %{user: user, for: for_user})
json(conn, account) json(conn, account)
@ -390,7 +390,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end end
def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do
with %User{} = user <- User.get_cached_by_nickname_or_id(params["id"]) do with %User{} = user <- User.get_cached_by_nickname_or_id(params["id"], for: reading_user) do
params = params =
params params
|> Map.put("tag", params["tagged"]) |> Map.put("tag", params["tagged"])

View file

@ -1675,32 +1675,85 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
end end
end end
test "account fetching", %{conn: conn} do describe "account fetching" do
user = insert(:user) test "works by id" do
user = insert(:user)
conn = conn =
conn build_conn()
|> get("/api/v1/accounts/#{user.id}") |> get("/api/v1/accounts/#{user.id}")
assert %{"id" => id} = json_response(conn, 200) assert %{"id" => id} = json_response(conn, 200)
assert id == to_string(user.id) assert id == to_string(user.id)
conn = conn =
build_conn() build_conn()
|> get("/api/v1/accounts/-1") |> get("/api/v1/accounts/-1")
assert %{"error" => "Can't find user"} = json_response(conn, 404) assert %{"error" => "Can't find user"} = json_response(conn, 404)
end end
test "account fetching also works nickname", %{conn: conn} do test "works by nickname" do
user = insert(:user) user = insert(:user)
conn = conn =
conn build_conn()
|> get("/api/v1/accounts/#{user.nickname}") |> get("/api/v1/accounts/#{user.nickname}")
assert %{"id" => id} = json_response(conn, 200) assert %{"id" => id} = json_response(conn, 200)
assert id == user.id assert id == user.id
end
test "works by nickname for remote users" do
limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
Pleroma.Config.put([:instance, :limit_to_local_content], false)
user = insert(:user, nickname: "user@example.com", local: false)
conn =
build_conn()
|> get("/api/v1/accounts/#{user.nickname}")
Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
assert %{"id" => id} = json_response(conn, 200)
assert id == user.id
end
test "respects limit_to_local_content == :all for remote user nicknames" do
limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
Pleroma.Config.put([:instance, :limit_to_local_content], :all)
user = insert(:user, nickname: "user@example.com", local: false)
conn =
build_conn()
|> get("/api/v1/accounts/#{user.nickname}")
Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
assert json_response(conn, 404)
end
test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
user = insert(:user, nickname: "user@example.com", local: false)
reading_user = insert(:user)
conn =
build_conn()
|> get("/api/v1/accounts/#{user.nickname}")
assert json_response(conn, 404)
conn =
build_conn()
|> assign(:user, reading_user)
|> get("/api/v1/accounts/#{user.nickname}")
Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
assert %{"id" => id} = json_response(conn, 200)
assert id == user.id
end
end end
test "mascot upload", %{conn: conn} do test "mascot upload", %{conn: conn} do