forked from AkkomaGang/akkoma
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:
commit
4dabf64af4
9 changed files with 40 additions and 21 deletions
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
_ ->
|
_ ->
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.with_preloaded_object()
|
|> Activity.query_by_actor()
|
||||||
|> Repo.all()
|
|> Activity.with_preloaded_object()
|
||||||
|> Enum.each(fn
|
|> Repo.stream()
|
||||||
%{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
|
||||||
|
|
|
@ -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])
|
||||||
|
|
|
@ -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} ->
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
||||||
# TODO: Remove favorites, repeats, delete activities.
|
Ecto.Adapters.SQL.Sandbox.unboxed_run(Repo, fn ->
|
||||||
refute Activity.get_by_id(activity.id)
|
{:ok, _} = User.delete_user_activities(user)
|
||||||
|
# TODO: Remove favorites, repeats, delete activities.
|
||||||
|
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
|
||||||
|
|
Loading…
Reference in a new issue