diff --git a/lib/mobilizon/actors/actors.ex b/lib/mobilizon/actors/actors.ex index 4ae932e27..82e8dbf24 100644 --- a/lib/mobilizon/actors/actors.ex +++ b/lib/mobilizon/actors/actors.ex @@ -333,28 +333,33 @@ defmodule Mobilizon.Actors do |> Multi.run(:remove_avatar, fn _, _ -> remove_avatar(actor) end) multi = - if type == :Group do - multi - |> Multi.run(:delete_remote_members, fn _, _ -> - delete_group_elements(actor, :remote_members) - end) - |> Multi.run(:delete_group_organized_events, fn _, _ -> - delete_group_elements(actor, :events) - end) - |> Multi.run(:delete_group_posts, fn _, _ -> - delete_group_elements(actor, :posts) - end) - |> Multi.run(:delete_group_resources, fn _, _ -> - delete_group_elements(actor, :resources) - end) - |> Multi.run(:delete_group_todo_lists, fn _, _ -> - delete_group_elements(actor, :todo_lists) - end) - |> Multi.run(:delete_group_discussions, fn _, _ -> - delete_group_elements(actor, :discussions) - end) - else - multi + case type do + :Group -> + multi + |> Multi.run(:delete_remote_members, fn _, _ -> + delete_group_elements(actor, :remote_members) + end) + |> Multi.run(:delete_group_organized_events, fn _, _ -> + delete_group_elements(actor, :events) + end) + |> Multi.run(:delete_group_posts, fn _, _ -> + delete_group_elements(actor, :posts) + end) + |> Multi.run(:delete_group_resources, fn _, _ -> + delete_group_elements(actor, :resources) + end) + |> Multi.run(:delete_group_todo_lists, fn _, _ -> + delete_group_elements(actor, :todo_lists) + end) + |> Multi.run(:delete_group_discussions, fn _, _ -> + delete_group_elements(actor, :discussions) + end) + + :Person -> + # When deleting a profile, reset default_actor_id + Multi.run(multi, :reset_default_actor_id, fn _, _ -> + reset_default_actor_id(actor) + end) end multi = @@ -1825,6 +1830,24 @@ defmodule Mobilizon.Actors do end end + @spec reset_default_actor_id(Actor.t()) :: {:ok, User.t()} | {:error, :user_not_found} + defp reset_default_actor_id(%Actor{type: :Person, user: %User{id: user_id} = user, id: actor_id}) do + Logger.debug("reset_default_actor_id") + + new_actor_id = + user + |> Users.get_actors_for_user() + |> Enum.map(& &1.id) + |> Enum.find(&(&1 !== actor_id)) + + {:ok, Users.update_user_default_actor(user_id, new_actor_id)} + rescue + _e in Ecto.NoResultsError -> + {:error, :user_not_found} + end + + defp reset_default_actor_id(%Actor{type: :Person, user: nil}), do: {:ok, nil} + defp accumulate_paginated_elements( %Actor{} = actor, method, diff --git a/priv/repo/migrations/20210422140923_cleanup_addresses.exs b/priv/repo/migrations/20210422140923_cleanup_addresses.exs index 695122595..5a6a82693 100644 --- a/priv/repo/migrations/20210422140923_cleanup_addresses.exs +++ b/priv/repo/migrations/20210422140923_cleanup_addresses.exs @@ -5,8 +5,6 @@ defmodule Mobilizon.Storage.Repo.Migrations.CleanupAddresses do # Make sure we don't have any duplicate addresses rows = fetch_bad_rows() Enum.each(rows, &process_row/1) - - flush() end def down do diff --git a/priv/repo/migrations/20210427091034_repair_users_default_actors.exs b/priv/repo/migrations/20210427091034_repair_users_default_actors.exs new file mode 100644 index 000000000..be4126e23 --- /dev/null +++ b/priv/repo/migrations/20210427091034_repair_users_default_actors.exs @@ -0,0 +1,47 @@ +defmodule Mobilizon.Storage.Repo.Migrations.RepairUsersDefaultActors do + use Ecto.Migration + + def up do + rows = fetch_bad_rows() + Enum.each(rows, &process_row/1) + end + + def down do + # Nothing to do + end + + defp fetch_bad_rows() do + %Postgrex.Result{rows: rows} = + Ecto.Adapters.SQL.query!( + Mobilizon.Storage.Repo, + "SELECT u.id FROM users u JOIN actors a ON u.default_actor_id = a.id WHERE a.user_id IS NULL" + ) + + rows + end + + defp process_row([user_id]) do + user_id + |> find_first_actor_id() + |> repair_user_default_actor(user_id) + end + + defp find_first_actor_id(user_id) do + %Postgrex.Result{rows: [[id]]} = + Ecto.Adapters.SQL.query!( + Mobilizon.Storage.Repo, + "SELECT id FROM actors WHERE user_id = $1 AND type = 'Person' AND NOT suspended ORDER BY id LIMIT 1", + [user_id] + ) + + id + end + + defp repair_user_default_actor(actor_id, user_id) do + Ecto.Adapters.SQL.query!( + Mobilizon.Storage.Repo, + "UPDATE users SET default_actor_id = $1 WHERE id = $2", + [actor_id, user_id] + ) + end +end