- `settings_store`: A generic map of settings for frontends. Opaque to the backend. Only returned in `verify_credentials` and `update_credentials`
- `chat_token`: The token needed for Pleroma chat. Only returned in `verify_credentials`
- `deactivated`: boolean, true when the user is deactivated
+- `allow_following_move`: boolean, true when the user allows automatically follow moved following accounts
- `unread_conversation_count`: The count of unread conversations. Only returned to the account owner.
### Source
- `default_scope` - the scope returned under `privacy` key in Source subentity
- `pleroma_settings_store` - Opaque user settings to be saved on the backend.
- `skip_thread_containment` - if true, skip filtering out broken threads
+- `allow_following_move` - if true, allows automatically follow moved following accounts
- `pleroma_background_image` - sets the background image of the user.
### Pleroma Settings Store
end
def move_following(origin, target) do
- following_relationships =
- __MODULE__
- |> where(following_id: ^origin.id)
- |> preload([:follower])
- |> limit(50)
- |> Repo.all()
-
- case following_relationships do
- [] ->
- :ok
-
- following_relationships ->
- Enum.each(following_relationships, fn following_relationship ->
- Repo.transaction(fn ->
- Repo.delete(following_relationship)
- User.follow(following_relationship.follower, target)
- end)
- end)
-
- move_following(origin, target)
+ __MODULE__
+ |> join(:inner, [r], f in assoc(r, :follower))
+ |> where(following_id: ^origin.id)
+ |> where([r, f], f.allow_following_move == true)
+ |> limit(50)
+ |> preload([:follower])
+ |> Repo.all()
+ |> Enum.map(fn following_relationship ->
+ Repo.delete(following_relationship)
+ Pleroma.Web.CommonAPI.follow(following_relationship.follower, target)
+ end)
+ |> case do
+ [] -> :ok
+ _ -> move_following(origin, target)
end
end
end
field(:raw_fields, {:array, :map}, default: [])
field(:discoverable, :boolean, default: false)
field(:invisible, :boolean, default: false)
+ field(:allow_following_move, :boolean, default: true)
field(:skip_thread_containment, :boolean, default: false)
field(:also_known_as, {:array, :string}, default: [])
:hide_followers_count,
:hide_follows_count,
:hide_favorites,
+ :allow_following_move,
:background,
:show_role,
:skip_thread_containment,
:hide_follows,
:fields,
:hide_followers,
+ :allow_following_move,
:discoverable,
:hide_followers_count,
:hide_follows_count,
:hide_favorites,
:show_role,
:skip_thread_containment,
+ :allow_following_move,
:discoverable
]
|> Enum.reduce(%{}, fn key, acc ->
|> maybe_put_chat_token(user, opts[:for], opts)
|> maybe_put_activation_status(user, opts[:for])
|> maybe_put_follow_requests_count(user, opts[:for])
+ |> maybe_put_allow_following_move(user, opts[:for])
|> maybe_put_unread_conversation_count(user, opts[:for])
end
defp maybe_put_notification_settings(data, _, _), do: data
+ defp maybe_put_allow_following_move(data, %User{id: user_id} = user, %User{id: user_id}) do
+ Kernel.put_in(data, [:pleroma, :allow_following_move], user.allow_following_move)
+ end
+
+ defp maybe_put_allow_following_move(data, _, _), do: data
+
defp maybe_put_activation_status(data, user, %User{is_admin: true}) do
Kernel.put_in(data, [:pleroma, :deactivated], user.deactivated)
end
+++ /dev/null
-defmodule Pleroma.Repo.Migrations.AddAlsoKnownAsToUsers do
- use Ecto.Migration
-
- def change do
- alter table(:users) do
- add(:also_known_as, {:array, :string}, default: [])
- end
- end
-end
--- /dev/null
+defmodule Pleroma.Repo.Migrations.AddMoveSupportToUsers do
+ use Ecto.Migration
+
+ def change do
+ alter table(:users) do
+ add(:also_known_as, {:array, :string}, default: [], null: false)
+ add(:allow_following_move, :boolean, default: true, null: false)
+ end
+ end
+end
%{ap_id: old_ap_id} = old_user = insert(:user)
%{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
follower = insert(:user)
+ follower_move_opted_out = insert(:user, allow_following_move: false)
User.follow(follower, old_user)
+ User.follow(follower_move_opted_out, old_user)
assert User.following?(follower, old_user)
+ assert User.following?(follower_move_opted_out, old_user)
assert {:ok, activity} = ActivityPub.move(old_user, new_user)
refute User.following?(follower, old_user)
assert User.following?(follower, new_user)
+
+ assert User.following?(follower_move_opted_out, old_user)
+ refute User.following?(follower_move_opted_out, new_user)
end
test "old user must be in the new user's `also_known_as` list" do
assert user["locked"] == true
end
+ test "updates the user's allow_following_move", %{conn: conn} do
+ user = insert(:user)
+
+ assert user.allow_following_move == true
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/accounts/update_credentials", %{allow_following_move: "false"})
+
+ assert refresh_record(user).allow_following_move == false
+ assert user = json_response(conn, 200)
+ assert user["pleroma"]["allow_following_move"] == false
+ end
+
test "updates the user's default scope", %{conn: conn} do
user = insert(:user)
privacy = user.default_scope
assert %{
- pleroma: %{notification_settings: ^notification_settings},
+ pleroma: %{notification_settings: ^notification_settings, allow_following_move: true},
source: %{privacy: ^privacy}
} = AccountView.render("show.json", %{user: user, for: user})
end