aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrinpatch <rinpatch@sdf.org>2019-07-12 20:54:20 +0300
committerrinpatch <rinpatch@sdf.org>2019-07-12 20:54:20 +0300
commit97b79efbcd4ad829a575019f842e7dcd7548266a (patch)
tree072a08d269951ccb14d3d32869d6a2fad9ebbc2b
parent1f6ac7680d1ae07be7c7dfd81a8cec2ba52f1c82 (diff)
downloadpleroma-97b79efbcd4ad829a575019f842e7dcd7548266a.tar.gz
ActivityPub Controller: Actually pass for_user to following/followers
views and give 403 errors when trying to request hidden follower pages when unauthenticated
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex51
-rw-r--r--lib/pleroma/web/router.ex8
-rw-r--r--test/web/activity_pub/activity_pub_controller_test.exs57
3 files changed, 102 insertions, 14 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index cf5176201..e2af4ad1a 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -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
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index d53fa8a35..e03a3a2e5 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -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
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
index cbc25bcdb..452172bb4 100644
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/web/activity_pub/activity_pub_controller_test.exs
@@ -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)