forked from AkkomaGang/akkoma
ActivityPub Controller: Actually pass for_user to following/followers
views and give 403 errors when trying to request hidden follower pages when unauthenticated
This commit is contained in:
parent
1f6ac7680d
commit
97b79efbcd
3 changed files with 102 additions and 14 deletions
|
@ -103,43 +103,57 @@ def activity(conn, %{"uuid" => uuid}) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def following(conn, %{"nickname" => nickname, "page" => page}) do
|
def following(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "page" => page}) do
|
||||||
with %User{} = user <- User.get_cached_by_nickname(nickname),
|
with %User{} = user <- User.get_cached_by_nickname(nickname),
|
||||||
{:ok, user} <- User.ensure_keys_present(user) do
|
{user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user),
|
||||||
|
{:show_follows, true} <-
|
||||||
|
{:show_follows, (for_user && for_user == user) || !user.info.hide_follows} do
|
||||||
{page, _} = Integer.parse(page)
|
{page, _} = Integer.parse(page)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_resp_header("content-type", "application/activity+json")
|
|> put_resp_header("content-type", "application/activity+json")
|
||||||
|> json(UserView.render("following.json", %{user: user, page: page}))
|
|> json(UserView.render("following.json", %{user: user, page: page, for: for_user}))
|
||||||
end
|
else
|
||||||
end
|
{:show_follows, _} ->
|
||||||
|
|
||||||
def following(conn, %{"nickname" => nickname}) do
|
|
||||||
with %User{} = user <- User.get_cached_by_nickname(nickname),
|
|
||||||
{:ok, user} <- User.ensure_keys_present(user) do
|
|
||||||
conn
|
conn
|
||||||
|> put_resp_header("content-type", "application/activity+json")
|
|> put_resp_header("content-type", "application/activity+json")
|
||||||
|> json(UserView.render("following.json", %{user: user}))
|
|> send_resp(403, "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def followers(conn, %{"nickname" => nickname, "page" => page}) do
|
def following(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname}) do
|
||||||
with %User{} = user <- User.get_cached_by_nickname(nickname),
|
with %User{} = user <- User.get_cached_by_nickname(nickname),
|
||||||
{:ok, user} <- User.ensure_keys_present(user) do
|
{user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user) do
|
||||||
|
conn
|
||||||
|
|> put_resp_header("content-type", "application/activity+json")
|
||||||
|
|> json(UserView.render("following.json", %{user: user, for: for_user}))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def followers(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "page" => page}) do
|
||||||
|
with %User{} = user <- User.get_cached_by_nickname(nickname),
|
||||||
|
{user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user),
|
||||||
|
{:show_followers, true} <-
|
||||||
|
{:show_followers, (for_user && for_user == user) || !user.info.hide_followers} do
|
||||||
{page, _} = Integer.parse(page)
|
{page, _} = Integer.parse(page)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_resp_header("content-type", "application/activity+json")
|
|> put_resp_header("content-type", "application/activity+json")
|
||||||
|> json(UserView.render("followers.json", %{user: user, page: page}))
|
|> json(UserView.render("followers.json", %{user: user, page: page, for: for_user}))
|
||||||
|
else
|
||||||
|
{:show_followers, _} ->
|
||||||
|
conn
|
||||||
|
|> put_resp_header("content-type", "application/activity+json")
|
||||||
|
|> send_resp(403, "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def followers(conn, %{"nickname" => nickname}) do
|
def followers(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname}) do
|
||||||
with %User{} = user <- User.get_cached_by_nickname(nickname),
|
with %User{} = user <- User.get_cached_by_nickname(nickname),
|
||||||
{:ok, user} <- User.ensure_keys_present(user) do
|
{user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user) do
|
||||||
conn
|
conn
|
||||||
|> put_resp_header("content-type", "application/activity+json")
|
|> put_resp_header("content-type", "application/activity+json")
|
||||||
|> json(UserView.render("followers.json", %{user: user}))
|
|> json(UserView.render("followers.json", %{user: user, for: for_user}))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -325,4 +339,17 @@ defp set_requester_reachable(%Plug.Conn{} = conn, _) do
|
||||||
|
|
||||||
conn
|
conn
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user) do
|
||||||
|
{:ok, new_user} = User.ensure_keys_present(user)
|
||||||
|
|
||||||
|
for_user =
|
||||||
|
if new_user != user and match?(%User{}, for_user) do
|
||||||
|
User.get_cached_by_nickname(for_user.nickname)
|
||||||
|
else
|
||||||
|
for_user
|
||||||
|
end
|
||||||
|
|
||||||
|
{new_user, for_user}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -623,8 +623,6 @@ defmodule Pleroma.Web.Router do
|
||||||
# XXX: not really ostatus
|
# XXX: not really ostatus
|
||||||
pipe_through(:ostatus)
|
pipe_through(:ostatus)
|
||||||
|
|
||||||
get("/users/:nickname/followers", ActivityPubController, :followers)
|
|
||||||
get("/users/:nickname/following", ActivityPubController, :following)
|
|
||||||
get("/users/:nickname/outbox", ActivityPubController, :outbox)
|
get("/users/:nickname/outbox", ActivityPubController, :outbox)
|
||||||
get("/objects/:uuid/likes", ActivityPubController, :object_likes)
|
get("/objects/:uuid/likes", ActivityPubController, :object_likes)
|
||||||
end
|
end
|
||||||
|
@ -656,6 +654,12 @@ defmodule Pleroma.Web.Router do
|
||||||
pipe_through(:oauth_write)
|
pipe_through(:oauth_write)
|
||||||
post("/users/:nickname/outbox", ActivityPubController, :update_outbox)
|
post("/users/:nickname/outbox", ActivityPubController, :update_outbox)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scope [] do
|
||||||
|
pipe_through(:oauth_read_or_public)
|
||||||
|
get("/users/:nickname/followers", ActivityPubController, :followers)
|
||||||
|
get("/users/:nickname/following", ActivityPubController, :following)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/relay", Pleroma.Web.ActivityPub do
|
scope "/relay", Pleroma.Web.ActivityPub do
|
||||||
|
|
|
@ -12,6 +12,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
||||||
alias Pleroma.Web.ActivityPub.ObjectView
|
alias Pleroma.Web.ActivityPub.ObjectView
|
||||||
alias Pleroma.Web.ActivityPub.UserView
|
alias Pleroma.Web.ActivityPub.UserView
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
setup_all do
|
setup_all do
|
||||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||||
|
@ -564,6 +565,34 @@ test "it returns returns a uri if the user has 'hide_followers' set", %{conn: co
|
||||||
assert is_binary(result["first"])
|
assert is_binary(result["first"])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it returns a 403 error on pages, if the user has 'hide_followers' set and the request is not authenticated",
|
||||||
|
%{conn: conn} do
|
||||||
|
user = insert(:user, %{info: %{hide_followers: true}})
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/users/#{user.nickname}/followers?page=1")
|
||||||
|
|
||||||
|
assert result.status == 403
|
||||||
|
assert result.resp_body == ""
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it renders the page, if the user has 'hide_followers' set and the request is authenticated with the same user",
|
||||||
|
%{conn: conn} do
|
||||||
|
user = insert(:user, %{info: %{hide_followers: true}})
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/users/#{user.nickname}/followers?page=1")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
assert result["totalItems"] == 1
|
||||||
|
assert result["orderedItems"] == [other_user.ap_id]
|
||||||
|
end
|
||||||
|
|
||||||
test "it works for more than 10 users", %{conn: conn} do
|
test "it works for more than 10 users", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
|
@ -618,6 +647,34 @@ test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} do
|
||||||
assert is_binary(result["first"])
|
assert is_binary(result["first"])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it returns a 403 error on pages, if the user has 'hide_follows' set and the request is not authenticated",
|
||||||
|
%{conn: conn} do
|
||||||
|
user = insert(:user, %{info: %{hide_follows: true}})
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> get("/users/#{user.nickname}/following?page=1")
|
||||||
|
|
||||||
|
assert result.status == 403
|
||||||
|
assert result.resp_body == ""
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it renders the page, if the user has 'hide_follows' set and the request is authenticated with the same user",
|
||||||
|
%{conn: conn} do
|
||||||
|
user = insert(:user, %{info: %{hide_follows: true}})
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/users/#{user.nickname}/following?page=1")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
assert result["totalItems"] == 1
|
||||||
|
assert result["orderedItems"] == [other_user.ap_id]
|
||||||
|
end
|
||||||
|
|
||||||
test "it works for more than 10 users", %{conn: conn} do
|
test "it works for more than 10 users", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue