views and give 403 errors when trying to request hidden follower pages when unauthenticatedtags/v1.1.4
@@ -103,43 +103,57 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do | |||
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), | |||
{: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) | |||
conn | |||
|> 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})) | |||
else | |||
{:show_follows, _} -> | |||
conn | |||
|> put_resp_header("content-type", "application/activity+json") | |||
|> send_resp(403, "") | |||
end | |||
end | |||
def following(conn, %{"nickname" => nickname}) do | |||
def following(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname}) do | |||
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})) | |||
|> json(UserView.render("following.json", %{user: user, for: for_user})) | |||
end | |||
end | |||
def followers(conn, %{"nickname" => nickname, "page" => page}) do | |||
def followers(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "page" => page}) do | |||
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_followers, true} <- | |||
{:show_followers, (for_user && for_user == user) || !user.info.hide_followers} do | |||
{page, _} = Integer.parse(page) | |||
conn | |||
|> 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 | |||
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), | |||
{: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("followers.json", %{user: user})) | |||
|> json(UserView.render("followers.json", %{user: user, for: for_user})) | |||
end | |||
end | |||
@@ -325,4 +339,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do | |||
conn | |||
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 |
@@ -623,8 +623,6 @@ defmodule Pleroma.Web.Router do | |||
# XXX: not really ostatus | |||
pipe_through(:ostatus) | |||
get("/users/:nickname/followers", ActivityPubController, :followers) | |||
get("/users/:nickname/following", ActivityPubController, :following) | |||
get("/users/:nickname/outbox", ActivityPubController, :outbox) | |||
get("/objects/:uuid/likes", ActivityPubController, :object_likes) | |||
end | |||
@@ -656,6 +654,12 @@ defmodule Pleroma.Web.Router do | |||
pipe_through(:oauth_write) | |||
post("/users/:nickname/outbox", ActivityPubController, :update_outbox) | |||
end | |||
scope [] do | |||
pipe_through(:oauth_read_or_public) | |||
get("/users/:nickname/followers", ActivityPubController, :followers) | |||
get("/users/:nickname/following", ActivityPubController, :following) | |||
end | |||
end | |||
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.UserView | |||
alias Pleroma.Web.ActivityPub.Utils | |||
alias Pleroma.Web.CommonAPI | |||
setup_all do | |||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) | |||
@@ -564,6 +565,34 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do | |||
assert is_binary(result["first"]) | |||
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 | |||
user = insert(:user) | |||
@@ -618,6 +647,34 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do | |||
assert is_binary(result["first"]) | |||
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 | |||
user = insert(:user) | |||