Merge branch 'feature/845-improve-status-deletion' into 'develop'

Improve status deletion

Closes #845

See merge request pleroma/pleroma!1104
This commit is contained in:
lambda 2019-05-06 16:45:22 +00:00
commit 4dabf64af4
9 changed files with 40 additions and 21 deletions

View file

@ -66,6 +66,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Deactivated users being able to request an access token - Deactivated users being able to request an access token
- Limit on request body in rich media/relme parsers being ignored resulting in a possible memory leak - Limit on request body in rich media/relme parsers being ignored resulting in a possible memory leak
- proper Twitter Card generation instead of a dummy - proper Twitter Card generation instead of a dummy
- Deletions failing for users with a large number of posts
- NodeInfo: Include admins in `staffAccounts` - NodeInfo: Include admins in `staffAccounts`
- ActivityPub: Crashing when requesting empty local user's outbox - ActivityPub: Crashing when requesting empty local user's outbox
- Federation: Handling of objects without `summary` property - Federation: Handling of objects without `summary` property

View file

@ -232,7 +232,8 @@
welcome_message: nil, welcome_message: nil,
max_report_comment_size: 1000, max_report_comment_size: 1000,
safe_dm_mentions: false, safe_dm_mentions: false,
healthcheck: false healthcheck: false,
repo_batch_size: 500
config :pleroma, :markup, config :pleroma, :markup,
# XXX - unfortunately, inline images must be enabled by default right now, because # XXX - unfortunately, inline images must be enabled by default right now, because
@ -416,7 +417,8 @@
web_push: 50, web_push: 50,
mailer: 10, mailer: 10,
transmogrifier: 20, transmogrifier: 20,
scheduled_activities: 10 scheduled_activities: 10,
background: 5
config :pleroma, :fetch_initial_posts, config :pleroma, :fetch_initial_posts,
enabled: false, enabled: false,

View file

@ -104,6 +104,7 @@ config :pleroma, Pleroma.Emails.Mailer,
* `max_report_comment_size`: The maximum size of the report comment (Default: `1000`) * `max_report_comment_size`: The maximum size of the report comment (Default: `1000`)
* `safe_dm_mentions`: If set to true, only mentions at the beginning of a post will be used to address people in direct messages. This is to prevent accidental mentioning of people when talking about them (e.g. "@friend hey i really don't like @enemy"). (Default: `false`) * `safe_dm_mentions`: If set to true, only mentions at the beginning of a post will be used to address people in direct messages. This is to prevent accidental mentioning of people when talking about them (e.g. "@friend hey i really don't like @enemy"). (Default: `false`)
* `healthcheck`: if set to true, system data will be shown on ``/api/pleroma/healthcheck``. * `healthcheck`: if set to true, system data will be shown on ``/api/pleroma/healthcheck``.
* `repo_batch_size`: Repo batch size. The number of loaded rows from the database to the memory for processing chunks. E.g. deleting user statuses.
## :logger ## :logger
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog, and `Quack.Logger` to log to Slack * `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog, and `Quack.Logger` to log to Slack

View file

@ -163,7 +163,7 @@ def run(["rm", nickname]) do
Common.start_pleroma() Common.start_pleroma()
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
User.delete(user) User.perform(:delete, user)
Mix.shell().info("User #{nickname} deleted.") Mix.shell().info("User #{nickname} deleted.")
else else
_ -> _ ->
@ -380,7 +380,7 @@ def run(["delete_activities", nickname]) do
Common.start_pleroma() Common.start_pleroma()
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
User.delete_user_activities(user) {:ok, _} = User.delete_user_activities(user)
Mix.shell().info("User #{nickname} statuses deleted.") Mix.shell().info("User #{nickname} statuses deleted.")
else else
_ -> _ ->

View file

@ -14,6 +14,8 @@ defmodule Pleroma.Activity do
import Ecto.Query import Ecto.Query
@type t :: %__MODULE__{} @type t :: %__MODULE__{}
@type actor :: String.t()
@primary_key {:id, Pleroma.FlakeId, autogenerate: true} @primary_key {:id, Pleroma.FlakeId, autogenerate: true}
# https://github.com/tootsuite/mastodon/blob/master/app/models/notification.rb#L19 # https://github.com/tootsuite/mastodon/blob/master/app/models/notification.rb#L19
@ -260,4 +262,9 @@ def all_by_actor_and_id(actor, status_ids) do
|> where([s], s.actor == ^actor) |> where([s], s.actor == ^actor)
|> Repo.all() |> Repo.all()
end end
@spec query_by_actor(actor()) :: Ecto.Query.t()
def query_by_actor(actor) do
from(a in Activity, where: a.actor == ^actor)
end
end end

View file

@ -1164,7 +1164,12 @@ def update_notification_settings(%User{} = user, settings \\ %{}) do
|> update_and_set_cache() |> update_and_set_cache()
end end
def delete(%User{} = user) do @spec delete(User.t()) :: :ok
def delete(%User{} = user),
do: PleromaJobQueue.enqueue(:background, __MODULE__, [:delete, user])
@spec perform(atom(), User.t()) :: {:ok, User.t()}
def perform(:delete, %User{} = user) do
{:ok, user} = User.deactivate(user) {:ok, user} = User.deactivate(user)
# Remove all relationships # Remove all relationships
@ -1180,22 +1185,23 @@ def delete(%User{} = user) do
end end
def delete_user_activities(%User{ap_id: ap_id} = user) do def delete_user_activities(%User{ap_id: ap_id} = user) do
Activity stream =
|> where(actor: ^ap_id) ap_id
|> Activity.query_by_actor()
|> Activity.with_preloaded_object() |> Activity.with_preloaded_object()
|> Repo.all() |> Repo.stream()
|> Enum.each(fn
%{data: %{"type" => "Create"}} = activity ->
activity |> Object.normalize() |> ActivityPub.delete()
# TODO: Do something with likes, follows, repeats. Repo.transaction(fn -> Enum.each(stream, &delete_activity(&1)) end, timeout: :infinity)
_ ->
"Doing nothing"
end)
{:ok, user} {:ok, user}
end end
defp delete_activity(%{data: %{"type" => "Create"}} = activity) do
Object.normalize(activity) |> ActivityPub.delete()
end
defp delete_activity(_activity), do: "Doing nothing"
def html_filter_policy(%User{info: %{no_rich_text: true}}) do def html_filter_policy(%User{info: %{no_rich_text: true}}) do
Pleroma.HTML.Scrubber.TwitterText Pleroma.HTML.Scrubber.TwitterText
end end

View file

@ -24,7 +24,7 @@ defmodule Pleroma.UserInviteToken do
timestamps() timestamps()
end end
@spec create_invite(map()) :: UserInviteToken.t() @spec create_invite(map()) :: {:ok, UserInviteToken.t()}
def create_invite(params \\ %{}) do def create_invite(params \\ %{}) do
%UserInviteToken{} %UserInviteToken{}
|> cast(params, [:max_use, :expires_at]) |> cast(params, [:max_use, :expires_at])

View file

@ -352,7 +352,7 @@ def change_password(%{assigns: %{user: user}} = conn, params) do
def delete_account(%{assigns: %{user: user}} = conn, params) do def delete_account(%{assigns: %{user: user}} = conn, params) do
case CommonAPI.Utils.confirm_current_password(user, params["password"]) do case CommonAPI.Utils.confirm_current_password(user, params["password"]) do
{:ok, user} -> {:ok, user} ->
Task.start(fn -> User.delete(user) end) User.delete(user)
json(conn, %{status: "success"}) json(conn, %{status: "success"})
{:error, msg} -> {:error, msg} ->

View file

@ -829,10 +829,12 @@ test ".delete_user_activities deletes all create activities" do
user = insert(:user) user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"}) {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
{:ok, _} = User.delete_user_activities(user)
Ecto.Adapters.SQL.Sandbox.unboxed_run(Repo, fn ->
{:ok, _} = User.delete_user_activities(user)
# TODO: Remove favorites, repeats, delete activities. # TODO: Remove favorites, repeats, delete activities.
refute Activity.get_by_id(activity.id) refute Activity.get_by_id(activity.id)
end)
end end
test ".delete deactivates a user, all follow relationships and all create activities" do test ".delete deactivates a user, all follow relationships and all create activities" do