diff --git a/lib/pleroma/instances/instance.ex b/lib/pleroma/instances/instance.ex index 4d0e8034d..2f338b3e2 100644 --- a/lib/pleroma/instances/instance.ex +++ b/lib/pleroma/instances/instance.ex @@ -8,6 +8,8 @@ defmodule Pleroma.Instances.Instance do alias Pleroma.Instances alias Pleroma.Instances.Instance alias Pleroma.Repo + alias Pleroma.User + alias Pleroma.Workers.BackgroundWorker use Ecto.Schema @@ -195,4 +197,24 @@ defp scrape_favicon(%URI{} = instance_uri) do nil end end + + @doc """ + Deletes all users from an instance in a background task, thus also deleting + all of those users' activities and notifications. + """ + def delete_users_and_activities(host) when is_binary(host) do + BackgroundWorker.enqueue("delete_instance", %{"host" => host}) + end + + def perform(:delete_instance, host) when is_binary(host) do + User.Query.build(%{nickname: "@#{host}"}) + |> Repo.chunk_stream(100, :batches) + |> Stream.each(fn users -> + users + |> Enum.each(fn user -> + User.perform(:delete, user) + end) + end) + |> Stream.run() + end end diff --git a/lib/pleroma/workers/background_worker.ex b/lib/pleroma/workers/background_worker.ex index 1e28384cb..4db077232 100644 --- a/lib/pleroma/workers/background_worker.ex +++ b/lib/pleroma/workers/background_worker.ex @@ -3,6 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Workers.BackgroundWorker do + alias Pleroma.Instances.Instance alias Pleroma.User use Pleroma.Workers.WorkerHelper, queue: "background" @@ -38,4 +39,8 @@ def perform(%Job{ Pleroma.FollowingRelationship.move_following(origin, target) end + + def perform(%Job{args: %{"op" => "delete_instance", "host" => host}}) do + Instance.perform(:delete_instance, host) + end end diff --git a/test/pleroma/instances/instance_test.exs b/test/pleroma/instances/instance_test.exs index bacc0b19b..e49922724 100644 --- a/test/pleroma/instances/instance_test.exs +++ b/test/pleroma/instances/instance_test.exs @@ -6,6 +6,8 @@ defmodule Pleroma.Instances.InstanceTest do alias Pleroma.Instances alias Pleroma.Instances.Instance alias Pleroma.Repo + alias Pleroma.Tests.ObanHelpers + alias Pleroma.Web.CommonAPI use Pleroma.DataCase @@ -158,4 +160,33 @@ test "Doesn't scrapes unreachable instances" do "Instance.scrape_favicon(\"#{url}\") ignored unreachable host" end end + + test "delete_users_and_activities/1 deletes remote instance users and activities" do + [mario, luigi, _peach, wario] = + users = [ + insert(:user, nickname: "mario@mushroom.kingdom", name: "Mario"), + insert(:user, nickname: "luigi@mushroom.kingdom", name: "Luigi"), + insert(:user, nickname: "peach@mushroom.kingdom", name: "Peach"), + insert(:user, nickname: "wario@greedville.biz", name: "Wario") + ] + + {:ok, post1} = CommonAPI.post(mario, %{status: "letsa go!"}) + {:ok, post2} = CommonAPI.post(luigi, %{status: "itsa me... luigi"}) + {:ok, post3} = CommonAPI.post(wario, %{status: "WHA-HA-HA!"}) + + {:ok, job} = Instance.delete_users_and_activities("mushroom.kingdom") + :ok = ObanHelpers.perform(job) + + [mario, luigi, peach, wario] = Repo.reload(users) + + refute mario.is_active + refute luigi.is_active + refute peach.is_active + refute peach.name == "Peach" + + assert wario.is_active + assert wario.name == "Wario" + + assert [nil, nil, %{}] = Repo.reload([post1, post2, post3]) + end end