logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma
commit: 48a03156465ec5c653101a57d4c899d0c6ffe1cf
parent: 6ab58fdfa1ce2a4afbedb8c018b2ec617348e640
Author: kaniini <nenolod@gmail.com>
Date:   Wed,  5 Dec 2018 21:41:53 +0000

Merge branch 'follower-hiding' into 'develop'

Network hiding

Closes #356

See merge request pleroma/pleroma!490

Diffstat:

Mlib/pleroma/user/info.ex2++
Mlib/pleroma/web/activity_pub/views/user_view.ex12++++++------
Mlib/pleroma/web/mastodon_api/mastodon_api_controller.ex19++++++++++++++++---
Mlib/pleroma/web/twitter_api/twitter_api_controller.ex22++++++++++++++++++----
Mtest/web/activity_pub/activity_pub_controller_test.exs28++++++++++++++++++++++++++++
Mtest/web/mastodon_api/mastodon_api_controller_test.exs50++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/web/twitter_api/twitter_api_controller_test.exs121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 241 insertions(+), 13 deletions(-)

diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex @@ -24,6 +24,7 @@ defmodule Pleroma.User.Info do field(:topic, :string, default: nil) field(:hub, :string, default: nil) field(:salmon, :string, default: nil) + field(:hide_network, :boolean, default: false) # Found in the wild # ap_id -> Where is this used? @@ -135,6 +136,7 @@ defmodule Pleroma.User.Info do :no_rich_text, :default_scope, :banner, + :hide_network, :background ]) end diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -82,7 +82,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do query = from(user in query, select: [:ap_id]) following = Repo.all(query) - collection(following, "#{user.ap_id}/following", page) + collection(following, "#{user.ap_id}/following", page, !user.info.hide_network) |> Map.merge(Utils.make_json_ld_header()) end @@ -95,7 +95,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do "id" => "#{user.ap_id}/following", "type" => "OrderedCollection", "totalItems" => length(following), - "first" => collection(following, "#{user.ap_id}/following", 1) + "first" => collection(following, "#{user.ap_id}/following", 1, !user.info.hide_network) } |> Map.merge(Utils.make_json_ld_header()) end @@ -105,7 +105,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do query = from(user in query, select: [:ap_id]) followers = Repo.all(query) - collection(followers, "#{user.ap_id}/followers", page) + collection(followers, "#{user.ap_id}/followers", page, !user.info.hide_network) |> Map.merge(Utils.make_json_ld_header()) end @@ -118,7 +118,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do "id" => "#{user.ap_id}/followers", "type" => "OrderedCollection", "totalItems" => length(followers), - "first" => collection(followers, "#{user.ap_id}/followers", 1) + "first" => collection(followers, "#{user.ap_id}/followers", 1, !user.info.hide_network) } |> Map.merge(Utils.make_json_ld_header()) end @@ -172,7 +172,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do end end - def collection(collection, iri, page, total \\ nil) do + def collection(collection, iri, page, show_items \\ true, total \\ nil) do offset = (page - 1) * 10 items = Enum.slice(collection, offset, 10) items = Enum.map(items, fn user -> user.ap_id end) @@ -183,7 +183,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do "type" => "OrderedCollectionPage", "partOf" => iri, "totalItems" => total, - "orderedItems" => items + "orderedItems" => if(show_items, do: items, else: []) } if offset < total do diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -502,17 +502,30 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) end - # TODO: Pagination - def followers(conn, %{"id" => id}) do + def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do with %User{} = user <- Repo.get(User, id), {:ok, followers} <- User.get_followers(user) do + followers = + cond do + for_user && user.id == for_user.id -> followers + user.info.hide_network -> [] + true -> followers + end + render(conn, AccountView, "accounts.json", %{users: followers, as: :user}) end end - def following(conn, %{"id" => id}) do + def following(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do with %User{} = user <- Repo.get(User, id), {:ok, followers} <- User.get_friends(user) do + followers = + cond do + for_user && user.id == for_user.id -> followers + user.info.hide_network -> [] + true -> followers + end + render(conn, AccountView, "accounts.json", %{users: followers, as: :user}) end end diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -340,18 +340,32 @@ defmodule Pleroma.Web.TwitterAPI.Controller do end end - def followers(conn, params) do - with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params), + def followers(%{assigns: %{user: for_user}} = conn, params) do + with {:ok, user} <- TwitterAPI.get_user(for_user, params), {:ok, followers} <- User.get_followers(user) do + followers = + cond do + for_user && user.id == for_user.id -> followers + user.info.hide_network -> [] + true -> followers + end + render(conn, UserView, "index.json", %{users: followers, for: conn.assigns[:user]}) else _e -> bad_request_reply(conn, "Can't get followers") end end - def friends(conn, params) do + def friends(%{assigns: %{user: for_user}} = conn, params) do with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params), {:ok, friends} <- User.get_friends(user) do + friends = + cond do + for_user && user.id == for_user.id -> friends + user.info.hide_network -> [] + true -> friends + end + render(conn, UserView, "index.json", %{users: friends, for: conn.assigns[:user]}) else _e -> bad_request_reply(conn, "Can't get friends") @@ -429,7 +443,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do defp build_info_cng(user, params) do info_params = - ["no_rich_text", "locked"] + ["no_rich_text", "locked", "hide_network"] |> Enum.reduce(%{}, fn key, res -> if value = params[key] do Map.put(res, key, value == "true") diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs @@ -150,6 +150,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do assert result["first"]["orderedItems"] == [user.ap_id] end + test "it returns returns empty if the user has 'hide_network' set", %{conn: conn} do + user = insert(:user) + user_two = insert(:user, %{info: %{hide_network: true}}) + User.follow(user, user_two) + + result = + conn + |> get("/users/#{user_two.nickname}/followers") + |> json_response(200) + + assert result["first"]["orderedItems"] == [] + assert result["totalItems"] == 1 + end + test "it works for more than 10 users", %{conn: conn} do user = insert(:user) @@ -191,6 +205,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do assert result["first"]["orderedItems"] == [user_two.ap_id] end + test "it returns returns empty if the user has 'hide_network' set", %{conn: conn} do + user = insert(:user, %{info: %{hide_network: true}}) + user_two = insert(:user) + User.follow(user, user_two) + + result = + conn + |> get("/users/#{user.nickname}/following") + |> json_response(200) + + assert result["first"]["orderedItems"] == [] + assert result["totalItems"] == 1 + end + test "it works for more than 10 users", %{conn: conn} do user = insert(:user) diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -1008,6 +1008,31 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert id == to_string(user.id) end + test "getting followers, hide_network", %{conn: conn} do + user = insert(:user) + other_user = insert(:user, %{info: %{hide_network: true}}) + {:ok, user} = User.follow(user, other_user) + + conn = + conn + |> get("/api/v1/accounts/#{other_user.id}/followers") + + assert [] == json_response(conn, 200) + end + + test "getting followers, hide_network, same user requesting", %{conn: conn} do + user = insert(:user) + other_user = insert(:user, %{info: %{hide_network: true}}) + {:ok, user} = User.follow(user, other_user) + + conn = + conn + |> assign(:user, other_user) + |> get("/api/v1/accounts/#{other_user.id}/followers") + + refute [] == json_response(conn, 200) + end + test "getting following", %{conn: conn} do user = insert(:user) other_user = insert(:user) @@ -1021,6 +1046,31 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert id == to_string(other_user.id) end + test "getting following, hide_network", %{conn: conn} do + user = insert(:user, %{info: %{hide_network: true}}) + other_user = insert(:user) + {:ok, user} = User.follow(user, other_user) + + conn = + conn + |> get("/api/v1/accounts/#{user.id}/following") + + assert [] == json_response(conn, 200) + end + + test "getting following, hide_network, same user requesting", %{conn: conn} do + user = insert(:user, %{info: %{hide_network: true}}) + other_user = insert(:user) + {:ok, user} = User.follow(user, other_user) + + conn = + conn + |> assign(:user, user) + |> get("/api/v1/accounts/#{user.id}/following") + + refute [] == json_response(conn, 200) + end + test "following / unfollowing a user", %{conn: conn} do user = insert(:user) other_user = insert(:user) diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs @@ -861,6 +861,67 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do result = json_response(conn, 200) assert Enum.sort(expected) == Enum.sort(result) end + + test "it returns a given user's followers with user_id", %{conn: conn} do + user = insert(:user) + follower_one = insert(:user) + follower_two = insert(:user) + not_follower = insert(:user) + + {:ok, follower_one} = User.follow(follower_one, user) + {:ok, follower_two} = User.follow(follower_two, user) + + conn = + conn + |> assign(:user, not_follower) + |> get("/api/statuses/followers", %{"user_id" => user.id}) + + assert MapSet.equal?( + MapSet.new(json_response(conn, 200)), + MapSet.new( + UserView.render("index.json", %{ + users: [follower_one, follower_two], + for: not_follower + }) + ) + ) + end + + test "it returns empty for a hidden network", %{conn: conn} do + user = insert(:user, %{info: %{hide_network: true}}) + follower_one = insert(:user) + follower_two = insert(:user) + not_follower = insert(:user) + + {:ok, follower_one} = User.follow(follower_one, user) + {:ok, follower_two} = User.follow(follower_two, user) + + conn = + conn + |> assign(:user, not_follower) + |> get("/api/statuses/followers", %{"user_id" => user.id}) + + assert [] == json_response(conn, 200) + end + + test "it returns the followers for a hidden network if requested by the user themselves", %{ + conn: conn + } do + user = insert(:user, %{info: %{hide_network: true}}) + follower_one = insert(:user) + follower_two = insert(:user) + not_follower = insert(:user) + + {:ok, follower_one} = User.follow(follower_one, user) + {:ok, follower_two} = User.follow(follower_two, user) + + conn = + conn + |> assign(:user, user) + |> get("/api/statuses/followers", %{"user_id" => user.id}) + + refute [] == json_response(conn, 200) + end end describe "GET /api/statuses/friends" do @@ -905,6 +966,42 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do ) end + test "it returns empty for a hidden network", %{conn: conn} do + user = insert(:user, %{info: %{hide_network: true}}) + followed_one = insert(:user) + followed_two = insert(:user) + not_followed = insert(:user) + + {:ok, user} = User.follow(user, followed_one) + {:ok, user} = User.follow(user, followed_two) + + conn = + conn + |> assign(:user, not_followed) + |> get("/api/statuses/friends", %{"user_id" => user.id}) + + assert [] == json_response(conn, 200) + end + + test "it returns friends for a hidden network if the user themselves request it", %{ + conn: conn + } do + user = insert(:user, %{info: %{hide_network: true}}) + followed_one = insert(:user) + followed_two = insert(:user) + not_followed = insert(:user) + + {:ok, user} = User.follow(user, followed_one) + {:ok, user} = User.follow(user, followed_two) + + conn = + conn + |> assign(:user, user) + |> get("/api/statuses/friends", %{"user_id" => user.id}) + + refute [] == json_response(conn, 200) + end + test "it returns a given user's friends with screen_name", %{conn: conn} do user = insert(:user) followed_one = insert(:user) @@ -976,6 +1073,30 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user}) end + test "it sets and un-sets hide_network", %{conn: conn} do + user = insert(:user) + + conn + |> assign(:user, user) + |> post("/api/account/update_profile.json", %{ + "hide_network" => "true" + }) + + user = Repo.get!(User, user.id) + assert user.info.hide_network == true + + conn = + conn + |> assign(:user, user) + |> post("/api/account/update_profile.json", %{ + "hide_network" => "false" + }) + + user = Repo.get!(User, user.id) + assert user.info.hide_network == false + assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user}) + end + test "it locks an account", %{conn: conn} do user = insert(:user)