forked from AkkomaGang/akkoma
Merge branch '483_blocks_import_export' into 'develop'
[#483] Blocked users list import & export Closes #483 See merge request pleroma/pleroma!603
This commit is contained in:
commit
dd8f2196f6
8 changed files with 173 additions and 19 deletions
|
@ -13,6 +13,8 @@ defmodule Pleroma.User do
|
||||||
alias Pleroma.Web.{OStatus, Websub, OAuth}
|
alias Pleroma.Web.{OStatus, Websub, OAuth}
|
||||||
alias Pleroma.Web.ActivityPub.{Utils, ActivityPub}
|
alias Pleroma.Web.ActivityPub.{Utils, ActivityPub}
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
@type t :: %__MODULE__{}
|
@type t :: %__MODULE__{}
|
||||||
|
|
||||||
@email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
|
@email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
|
||||||
|
@ -339,6 +341,24 @@ def following?(%User{} = follower, %User{} = followed) do
|
||||||
Enum.member?(follower.following, followed.follower_address)
|
Enum.member?(follower.following, followed.follower_address)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def follow_import(%User{} = follower, followed_identifiers)
|
||||||
|
when is_list(followed_identifiers) do
|
||||||
|
Enum.map(
|
||||||
|
followed_identifiers,
|
||||||
|
fn followed_identifier ->
|
||||||
|
with %User{} = followed <- get_or_fetch(followed_identifier),
|
||||||
|
{:ok, follower} <- maybe_direct_follow(follower, followed),
|
||||||
|
{:ok, _} <- ActivityPub.follow(follower, followed) do
|
||||||
|
followed
|
||||||
|
else
|
||||||
|
err ->
|
||||||
|
Logger.debug("follow_import failed for #{followed_identifier} with: #{inspect(err)}")
|
||||||
|
err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def locked?(%User{} = user) do
|
def locked?(%User{} = user) do
|
||||||
user.info.locked || false
|
user.info.locked || false
|
||||||
end
|
end
|
||||||
|
@ -375,7 +395,11 @@ def get_cached_by_nickname(nickname) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_by_nickname(nickname) do
|
def get_by_nickname(nickname) do
|
||||||
Repo.get_by(User, nickname: nickname)
|
Repo.get_by(User, nickname: nickname) ||
|
||||||
|
if Regex.match?(~r(@#{Pleroma.Web.Endpoint.host()})i, nickname) do
|
||||||
|
[local_nickname, _] = String.split(nickname, "@")
|
||||||
|
Repo.get_by(User, nickname: local_nickname)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_by_nickname_or_email(nickname_or_email) do
|
def get_by_nickname_or_email(nickname_or_email) do
|
||||||
|
@ -604,6 +628,23 @@ def search(query, resolve \\ false) do
|
||||||
Repo.all(q)
|
Repo.all(q)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def blocks_import(%User{} = blocker, blocked_identifiers) when is_list(blocked_identifiers) do
|
||||||
|
Enum.map(
|
||||||
|
blocked_identifiers,
|
||||||
|
fn blocked_identifier ->
|
||||||
|
with %User{} = blocked <- get_or_fetch(blocked_identifier),
|
||||||
|
{:ok, blocker} <- block(blocker, blocked),
|
||||||
|
{:ok, _} <- ActivityPub.block(blocker, blocked) do
|
||||||
|
blocked
|
||||||
|
else
|
||||||
|
err ->
|
||||||
|
Logger.debug("blocks_import failed for #{blocked_identifier} with: #{inspect(err)}")
|
||||||
|
err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def block(blocker, %User{ap_id: ap_id} = blocked) do
|
def block(blocker, %User{ap_id: ap_id} = blocked) do
|
||||||
# sever any follow relationships to prevent leaks per activitypub (Pleroma issue #213)
|
# sever any follow relationships to prevent leaks per activitypub (Pleroma issue #213)
|
||||||
blocker =
|
blocker =
|
||||||
|
@ -657,6 +698,9 @@ def blocks?(user, %{ap_id: ap_id}) do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def blocked_users(user),
|
||||||
|
do: Repo.all(from(u in User, where: u.ap_id in ^user.info.blocks))
|
||||||
|
|
||||||
def block_domain(user, domain) do
|
def block_domain(user, domain) do
|
||||||
info_cng =
|
info_cng =
|
||||||
user.info
|
user.info
|
||||||
|
|
|
@ -704,11 +704,9 @@ def unblock(%{assigns: %{user: blocker}} = conn, %{"id" => id}) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: Use proper query
|
|
||||||
def blocks(%{assigns: %{user: user}} = conn, _) do
|
def blocks(%{assigns: %{user: user}} = conn, _) do
|
||||||
with blocked_users <- user.info.blocks || [],
|
with blocked_accounts <- User.blocked_users(user) do
|
||||||
accounts <- Enum.map(blocked_users, fn ap_id -> User.get_cached_by_ap_id(ap_id) end) do
|
res = AccountView.render("accounts.json", users: blocked_accounts, for: user, as: :user)
|
||||||
res = AccountView.render("accounts.json", users: accounts, for: user, as: :user)
|
|
||||||
json(conn, res)
|
json(conn, res)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -137,6 +137,7 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
scope "/api/pleroma", Pleroma.Web.TwitterAPI do
|
scope "/api/pleroma", Pleroma.Web.TwitterAPI do
|
||||||
pipe_through(:authenticated_api)
|
pipe_through(:authenticated_api)
|
||||||
|
post("/blocks_import", UtilController, :blocks_import)
|
||||||
post("/follow_import", UtilController, :follow_import)
|
post("/follow_import", UtilController, :follow_import)
|
||||||
post("/change_password", UtilController, :change_password)
|
post("/change_password", UtilController, :change_password)
|
||||||
post("/delete_account", UtilController, :delete_account)
|
post("/delete_account", UtilController, :delete_account)
|
||||||
|
@ -281,6 +282,7 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
get("/statuses/followers", TwitterAPI.Controller, :followers)
|
get("/statuses/followers", TwitterAPI.Controller, :followers)
|
||||||
get("/statuses/friends", TwitterAPI.Controller, :friends)
|
get("/statuses/friends", TwitterAPI.Controller, :friends)
|
||||||
|
get("/statuses/blocks", TwitterAPI.Controller, :blocks)
|
||||||
get("/statuses/show/:id", TwitterAPI.Controller, :fetch_status)
|
get("/statuses/show/:id", TwitterAPI.Controller, :fetch_status)
|
||||||
get("/statusnet/conversation/:id", TwitterAPI.Controller, :fetch_conversation)
|
get("/statusnet/conversation/:id", TwitterAPI.Controller, :fetch_conversation)
|
||||||
|
|
||||||
|
|
|
@ -240,21 +240,22 @@ def follow_import(conn, %{"list" => %Plug.Upload{} = listfile}) do
|
||||||
follow_import(conn, %{"list" => File.read!(listfile.path)})
|
follow_import(conn, %{"list" => File.read!(listfile.path)})
|
||||||
end
|
end
|
||||||
|
|
||||||
def follow_import(%{assigns: %{user: user}} = conn, %{"list" => list}) do
|
def follow_import(%{assigns: %{user: follower}} = conn, %{"list" => list}) do
|
||||||
Task.start(fn ->
|
with followed_identifiers <- String.split(list),
|
||||||
String.split(list)
|
{:ok, _} = Task.start(fn -> User.follow_import(follower, followed_identifiers) end) do
|
||||||
|> Enum.map(fn account ->
|
json(conn, "job started")
|
||||||
with %User{} = follower <- User.get_cached_by_ap_id(user.ap_id),
|
end
|
||||||
%User{} = followed <- User.get_or_fetch(account),
|
end
|
||||||
{:ok, follower} <- User.maybe_direct_follow(follower, followed) do
|
|
||||||
ActivityPub.follow(follower, followed)
|
|
||||||
else
|
|
||||||
err -> Logger.debug("follow_import: following #{account} failed with #{inspect(err)}")
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
json(conn, "job started")
|
def blocks_import(conn, %{"list" => %Plug.Upload{} = listfile}) do
|
||||||
|
blocks_import(conn, %{"list" => File.read!(listfile.path)})
|
||||||
|
end
|
||||||
|
|
||||||
|
def blocks_import(%{assigns: %{user: blocker}} = conn, %{"list" => list}) do
|
||||||
|
with blocked_identifiers <- String.split(list),
|
||||||
|
{:ok, _} = Task.start(fn -> User.blocks_import(blocker, blocked_identifiers) end) do
|
||||||
|
json(conn, "job started")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_password(%{assigns: %{user: user}} = conn, params) do
|
def change_password(%{assigns: %{user: user}} = conn, params) do
|
||||||
|
|
|
@ -507,6 +507,14 @@ def friends(%{assigns: %{user: for_user}} = conn, params) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def blocks(%{assigns: %{user: user}} = conn, _params) do
|
||||||
|
with blocked_users <- User.blocked_users(user) do
|
||||||
|
conn
|
||||||
|
|> put_view(UserView)
|
||||||
|
|> render("index.json", %{users: blocked_users, for: user})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def friend_requests(conn, params) do
|
def friend_requests(conn, params) do
|
||||||
with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params),
|
with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params),
|
||||||
{:ok, friend_requests} <- User.get_follow_requests(user) do
|
{:ok, friend_requests} <- User.get_follow_requests(user) do
|
||||||
|
|
|
@ -278,6 +278,24 @@ test "gets an existing user, case insensitive" do
|
||||||
assert user == fetched_user
|
assert user == fetched_user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "gets an existing user by fully qualified nickname" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
fetched_user =
|
||||||
|
User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
|
||||||
|
|
||||||
|
assert user == fetched_user
|
||||||
|
end
|
||||||
|
|
||||||
|
test "gets an existing user by fully qualified nickname, case insensitive" do
|
||||||
|
user = insert(:user, nickname: "nick")
|
||||||
|
casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
|
||||||
|
|
||||||
|
fetched_user = User.get_or_fetch_by_nickname(casing_altered_fqn)
|
||||||
|
|
||||||
|
assert user == fetched_user
|
||||||
|
end
|
||||||
|
|
||||||
test "fetches an external user via ostatus if no user exists" do
|
test "fetches an external user via ostatus if no user exists" do
|
||||||
fetched_user = User.get_or_fetch_by_nickname("shp@social.heldscal.la")
|
fetched_user = User.get_or_fetch_by_nickname("shp@social.heldscal.la")
|
||||||
assert fetched_user.nickname == "shp@social.heldscal.la"
|
assert fetched_user.nickname == "shp@social.heldscal.la"
|
||||||
|
@ -485,6 +503,21 @@ test "it sets the info->follower_count property" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "follow_import" do
|
||||||
|
test "it imports user followings from list" do
|
||||||
|
[user1, user2, user3] = insert_list(3, :user)
|
||||||
|
|
||||||
|
identifiers = [
|
||||||
|
user2.ap_id,
|
||||||
|
user3.nickname
|
||||||
|
]
|
||||||
|
|
||||||
|
result = User.follow_import(user1, identifiers)
|
||||||
|
assert is_list(result)
|
||||||
|
assert result == [user2, user3]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "blocks" do
|
describe "blocks" do
|
||||||
test "it blocks people" do
|
test "it blocks people" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
@ -584,6 +617,21 @@ test "unblocks domains" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "blocks_import" do
|
||||||
|
test "it imports user blocks from list" do
|
||||||
|
[user1, user2, user3] = insert_list(3, :user)
|
||||||
|
|
||||||
|
identifiers = [
|
||||||
|
user2.ap_id,
|
||||||
|
user3.nickname
|
||||||
|
]
|
||||||
|
|
||||||
|
result = User.blocks_import(user1, identifiers)
|
||||||
|
assert is_list(result)
|
||||||
|
assert result == [user2, user3]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
test "get recipients from activity" do
|
test "get recipients from activity" do
|
||||||
actor = insert(:user)
|
actor = insert(:user)
|
||||||
user = insert(:user, local: true)
|
user = insert(:user, local: true)
|
||||||
|
|
|
@ -1145,6 +1145,24 @@ test "it returns the followers for a hidden network if requested by the user the
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "GET /api/statuses/blocks" do
|
||||||
|
test "it returns the list of users blocked by requester", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, user} = User.block(user, other_user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/statuses/blocks")
|
||||||
|
|
||||||
|
expected = UserView.render("index.json", %{users: [other_user], for: user})
|
||||||
|
result = json_response(conn, 200)
|
||||||
|
assert Enum.sort(expected) == Enum.sort(result)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "GET /api/statuses/friends" do
|
describe "GET /api/statuses/friends" do
|
||||||
test "it returns the logged in user's friends", %{conn: conn} do
|
test "it returns the logged in user's friends", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
35
test/web/twitter_api/util_controller_test.exs
Normal file
35
test/web/twitter_api/util_controller_test.exs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
|
||||||
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
describe "POST /api/pleroma/follow_import" do
|
||||||
|
test "it returns HTTP 200", %{conn: conn} do
|
||||||
|
user1 = insert(:user)
|
||||||
|
user2 = insert(:user)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user1)
|
||||||
|
|> post("/api/pleroma/follow_import", %{"list" => "#{user2.ap_id}"})
|
||||||
|
|> json_response(:ok)
|
||||||
|
|
||||||
|
assert response == "job started"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "POST /api/pleroma/blocks_import" do
|
||||||
|
test "it returns HTTP 200", %{conn: conn} do
|
||||||
|
user1 = insert(:user)
|
||||||
|
user2 = insert(:user)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user1)
|
||||||
|
|> post("/api/pleroma/blocks_import", %{"list" => "#{user2.ap_id}"})
|
||||||
|
|> json_response(:ok)
|
||||||
|
|
||||||
|
assert response == "job started"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue