From 209395c7e60afe7115f22afd6936d9c6bdd7bb72 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 24 Sep 2019 19:50:07 +0700 Subject: [PATCH] Add User.change_info/2 and User.update_info/2 --- lib/mix/tasks/pleroma/user.ex | 25 +-- lib/pleroma/user.ex | 173 +++++------------- lib/pleroma/user/info.ex | 24 +-- .../web/admin_api/admin_api_controller.ex | 59 +++--- lib/pleroma/web/common_api/common_api.ex | 28 +-- .../controllers/mastodon_api_controller.ex | 68 +++---- .../web/twitter_api/twitter_api_controller.ex | 8 +- test/tasks/database_test.exs | 4 +- test/user_test.exs | 18 ++ .../mastodon_api_controller_test.exs | 17 +- test/web/oauth/oauth_controller_test.exs | 9 +- test/web/ostatus/ostatus_controller_test.exs | 20 +- 12 files changed, 146 insertions(+), 307 deletions(-) diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index 84c923901..d93ba8dee 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -4,7 +4,6 @@ defmodule Mix.Tasks.Pleroma.User do use Mix.Task - import Ecto.Changeset import Mix.Pleroma alias Pleroma.User alias Pleroma.UserInviteToken @@ -443,39 +442,21 @@ def run(["sign_out", nickname]) do end defp set_moderator(user, value) do - info_cng = User.Info.admin_api_update(user.info, %{is_moderator: value}) - - user_cng = - Ecto.Changeset.change(user) - |> put_embed(:info, info_cng) - - {:ok, user} = User.update_and_set_cache(user_cng) + {:ok, user} = User.update_info(user, &User.Info.admin_api_update(&1, %{is_moderator: value})) shell_info("Moderator status of #{user.nickname}: #{user.info.is_moderator}") user end defp set_admin(user, value) do - info_cng = User.Info.admin_api_update(user.info, %{is_admin: value}) - - user_cng = - Ecto.Changeset.change(user) - |> put_embed(:info, info_cng) - - {:ok, user} = User.update_and_set_cache(user_cng) + {:ok, user} = User.update_info(user, &User.Info.admin_api_update(&1, %{is_admin: value})) shell_info("Admin status of #{user.nickname}: #{user.info.is_admin}") user end defp set_locked(user, value) do - info_cng = User.Info.user_upgrade(user.info, %{locked: value}) - - user_cng = - Ecto.Changeset.change(user) - |> put_embed(:info, info_cng) - - {:ok, user} = User.update_and_set_cache(user_cng) + {:ok, user} = User.update_info(user, &User.Info.user_upgrade(&1, %{locked: value})) shell_info("Locked status of #{user.nickname}: #{user.info.locked}") user diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 8d126933b..422bc6fa6 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -197,8 +197,6 @@ def remote_user_creation(params) do |> truncate_if_exists(:name, name_limit) |> truncate_if_exists(:bio, bio_limit) - info_cng = User.Info.remote_user_creation(%User.Info{}, params[:info]) - changes = %User{} |> cast(params, [:bio, :name, :ap_id, :nickname, :avatar]) @@ -208,7 +206,7 @@ def remote_user_creation(params) do |> validate_length(:bio, max: bio_limit) |> validate_length(:name, max: name_limit) |> put_change(:local, false) - |> put_embed(:info, info_cng) + |> change_info(&User.Info.remote_user_creation(&1, params[:info])) if changes.valid? do case info_cng.changes[:source_data] do @@ -245,7 +243,6 @@ def upgrade_changeset(struct, params \\ %{}, remote? \\ false) do name_limit = Pleroma.Config.get([:instance, :user_name_length], 100) params = Map.put(params, :last_refreshed_at, NaiveDateTime.utc_now()) - info_cng = User.Info.user_upgrade(struct.info, params[:info], remote?) struct |> cast(params, [ @@ -260,7 +257,7 @@ def upgrade_changeset(struct, params \\ %{}, remote? \\ false) do |> validate_format(:nickname, local_nickname_regex()) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, max: name_limit) - |> put_embed(:info, info_cng) + |> change_info(&User.Info.user_upgrade(&1, params[:info], remote?)) end def password_update_changeset(struct, params) do @@ -785,21 +782,15 @@ def decrease_note_count(%User{} = user) do end def update_note_count(%User{} = user) do - note_count_query = + note_count = from( a in Object, where: fragment("?->>'actor' = ? and ?->>'type' = 'Note'", a.data, ^user.ap_id, a.data), select: count(a.id) ) + |> Repo.one() - note_count = Repo.one(note_count_query) - - info_cng = User.Info.set_note_count(user.info, note_count) - - user - |> change() - |> put_embed(:info, info_cng) - |> update_and_set_cache() + update_info(user, &User.Info.set_note_count(&1, note_count)) end @spec maybe_fetch_follow_information(User.t()) :: User.t() @@ -816,17 +807,7 @@ def maybe_fetch_follow_information(user) do def fetch_follow_information(user) do with {:ok, info} <- ActivityPub.fetch_follow_information_for_user(user) do - info_cng = User.Info.follow_information_update(user.info, info) - - changeset = - user - |> change() - |> put_embed(:info, info_cng) - - update_and_set_cache(changeset) - else - {:error, _} = e -> e - e -> {:error, e} + update_info(user, &User.Info.follow_information_update(&1, info)) end end @@ -900,31 +881,11 @@ def get_recipients_from_activity(%Activity{recipients: to}) do @spec mute(User.t(), User.t(), boolean()) :: {:ok, User.t()} | {:error, String.t()} def mute(muter, %User{ap_id: ap_id}, notifications? \\ true) do - info = muter.info - - info_cng = - User.Info.add_to_mutes(info, ap_id) - |> User.Info.add_to_muted_notifications(info, ap_id, notifications?) - - cng = - change(muter) - |> put_embed(:info, info_cng) - - update_and_set_cache(cng) + update_info(muter, &User.Info.add_to_mutes(&1, ap_id, notifications?)) end def unmute(muter, %{ap_id: ap_id}) do - info = muter.info - - info_cng = - User.Info.remove_from_mutes(info, ap_id) - |> User.Info.remove_from_muted_notifications(info, ap_id) - - cng = - change(muter) - |> put_embed(:info, info_cng) - - update_and_set_cache(cng) + update_info(muter, &User.Info.remove_from_mutes(&1, ap_id)) end def subscribe(subscriber, %{ap_id: ap_id}) do @@ -936,26 +897,14 @@ def subscribe(subscriber, %{ap_id: ap_id}) do if blocked do {:error, "Could not subscribe: #{subscribed.nickname} is blocking you"} else - info_cng = - subscribed.info - |> User.Info.add_to_subscribers(subscriber.ap_id) - - change(subscribed) - |> put_embed(:info, info_cng) - |> update_and_set_cache() + update_info(subscribed, &User.Info.add_to_subscribers(&1, subscriber.ap_id)) end end end def unsubscribe(unsubscriber, %{ap_id: ap_id}) do with %User{} = user <- get_cached_by_ap_id(ap_id) do - info_cng = - user.info - |> User.Info.remove_from_subscribers(unsubscriber.ap_id) - - change(user) - |> put_embed(:info, info_cng) - |> update_and_set_cache() + update_info(user, &User.Info.remove_from_subscribers(&1, unsubscriber.ap_id)) end end @@ -990,15 +939,7 @@ def block(blocker, %User{ap_id: ap_id} = blocked) do {:ok, blocker} = update_follower_count(blocker) - info_cng = - blocker.info - |> User.Info.add_to_block(ap_id) - - cng = - change(blocker) - |> put_embed(:info, info_cng) - - update_and_set_cache(cng) + update_info(blocker, &User.Info.add_to_block(&1, ap_id)) end # helper to handle the block given only an actor's AP id @@ -1007,15 +948,7 @@ def block(blocker, %{ap_id: ap_id}) do end def unblock(blocker, %{ap_id: ap_id}) do - info_cng = - blocker.info - |> User.Info.remove_from_block(ap_id) - - cng = - change(blocker) - |> put_embed(:info, info_cng) - - update_and_set_cache(cng) + update_info(blocker, &User.Info.remove_from_block(&1, ap_id)) end def mutes?(nil, _), do: false @@ -1072,27 +1005,11 @@ def subscribers(user) do end def block_domain(user, domain) do - info_cng = - user.info - |> User.Info.add_to_domain_block(domain) - - cng = - change(user) - |> put_embed(:info, info_cng) - - update_and_set_cache(cng) + update_info(user, &User.Info.add_to_domain_block(&1, domain)) end def unblock_domain(user, domain) do - info_cng = - user.info - |> User.Info.remove_from_domain_block(domain) - - cng = - change(user) - |> put_embed(:info, info_cng) - - update_and_set_cache(cng) + update_info(user, &User.Info.remove_from_domain_block(&1, domain)) end def deactivate_async(user, status \\ true) do @@ -1100,13 +1017,7 @@ def deactivate_async(user, status \\ true) do end def deactivate(%User{} = user, status \\ true) do - info_cng = User.Info.set_activation_status(user.info, status) - - with {:ok, user} <- - user - |> change() - |> put_embed(:info, info_cng) - |> update_and_set_cache() do + with {:ok, user} <- update_info(user, &User.Info.set_activation_status(&1, status)) do Enum.each(get_followers(user), &invalidate_cache/1) Enum.each(get_friends(user), &update_follower_count/1) @@ -1115,11 +1026,7 @@ def deactivate(%User{} = user, status \\ true) do end def update_notification_settings(%User{} = user, settings \\ %{}) do - info_changeset = User.Info.update_notification_settings(user.info, settings) - - change(user) - |> put_embed(:info, info_changeset) - |> update_and_set_cache() + update_info(user, &User.Info.update_notification_settings(&1, settings)) end def delete(%User{} = user) do @@ -1560,11 +1467,7 @@ def list_inactive_users_query(inactivity_threshold \\ 7) do @spec switch_email_notifications(t(), String.t(), boolean()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} def switch_email_notifications(user, type, status) do - info = Pleroma.User.Info.update_email_notifications(user.info, %{type => status}) - - change(user) - |> put_embed(:info, info) - |> update_and_set_cache() + update_info(user, &User.Info.update_email_notifications(&1, %{type => status})) end @doc """ @@ -1586,13 +1489,8 @@ def touch_last_digest_emailed_at(user) do def toggle_confirmation(%User{} = user) do need_confirmation? = !user.info.confirmation_pending - info_changeset = - User.Info.confirmation_changeset(user.info, need_confirmation: need_confirmation?) - user - |> change() - |> put_embed(:info, info_changeset) - |> update_and_set_cache() + |> update_info(&User.Info.confirmation_changeset(&1, need_confirmation: need_confirmation?)) end def get_mascot(%{info: %{mascot: %{} = mascot}}) when not is_nil(mascot) do @@ -1615,16 +1513,11 @@ def get_mascot(%{info: %{mascot: mascot}}) when is_nil(mascot) do } end - def ensure_keys_present(%User{info: info} = user) do - if info.keys do - {:ok, user} - else - {:ok, pem} = Keys.generate_rsa_pem() + def ensure_keys_present(%{info: %{keys: keys}} = user) when not is_nil(keys), do: {:ok, user} - user - |> Ecto.Changeset.change() - |> Ecto.Changeset.put_embed(:info, User.Info.set_keys(info, pem)) - |> update_and_set_cache() + def ensure_keys_present(%User{} = user) do + with {:ok, pem} <- Keys.generate_rsa_pem() do + update_info(user, &User.Info.set_keys(&1, pem)) end end @@ -1670,4 +1563,26 @@ def change_email(user, email) do |> validate_format(:email, @email_regex) |> update_and_set_cache() end + + @doc """ + Changes `user.info` and returns the user changeset. + + `fun` is called with the `user.info`. + """ + def change_info(user, fun) do + changeset = change(user) + info = get_field(changeset, :info) || %User.Info{} + put_embed(changeset, :info, fun.(info)) + end + + @doc """ + Updates `user.info` and sets cache. + + `fun` is called with the `user.info`. + """ + def update_info(user, fun) do + user + |> change_info(fun) + |> update_and_set_cache() + end end diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex index 99745f496..92e3944f7 100644 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@ -187,16 +187,11 @@ def set_subscribers(info, subscribers) do |> validate_required([:subscribers]) end - @spec add_to_mutes(Info.t(), String.t()) :: Changeset.t() - def add_to_mutes(info, muted) do - set_mutes(info, Enum.uniq([muted | info.mutes])) - end - - @spec add_to_muted_notifications(Changeset.t(), Info.t(), String.t(), boolean()) :: - Changeset.t() - def add_to_muted_notifications(changeset, info, muted, notifications?) do - set_notification_mutes( - changeset, + @spec add_to_mutes(Info.t(), String.t(), boolean()) :: Changeset.t() + def add_to_mutes(info, muted, notifications?) do + info + |> set_mutes(Enum.uniq([muted | info.mutes])) + |> set_notification_mutes( Enum.uniq([muted | info.muted_notifications]), notifications? ) @@ -204,12 +199,9 @@ def add_to_muted_notifications(changeset, info, muted, notifications?) do @spec remove_from_mutes(Info.t(), String.t()) :: Changeset.t() def remove_from_mutes(info, muted) do - set_mutes(info, List.delete(info.mutes, muted)) - end - - @spec remove_from_muted_notifications(Changeset.t(), Info.t(), String.t()) :: Changeset.t() - def remove_from_muted_notifications(changeset, info, muted) do - set_notification_mutes(changeset, List.delete(info.muted_notifications, muted), true) + info + |> set_mutes(List.delete(info.mutes, muted)) + |> set_notification_mutes(List.delete(info.muted_notifications, muted), true) end def add_to_block(info, blocked) do diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 0d1db8fa0..6e703d169 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -254,18 +254,12 @@ def right_add(%{assigns: %{user: admin}} = conn, %{ "nickname" => nickname }) when permission_group in ["moderator", "admin"] do - user = User.get_cached_by_nickname(nickname) + info = Map.put(%{}, "is_" <> permission_group, true) - info = - %{} - |> Map.put("is_" <> permission_group, true) - - info_cng = User.Info.admin_api_update(user.info, info) - - cng = - user - |> Ecto.Changeset.change() - |> Ecto.Changeset.put_embed(:info, info_cng) + {:ok, user} = + nickname + |> User.get_cached_by_nickname() + |> User.update_info(&User.Info.admin_api_update(&1, info)) ModerationLog.insert_log(%{ action: "grant", @@ -274,8 +268,6 @@ def right_add(%{assigns: %{user: admin}} = conn, %{ permission: permission_group }) - {:ok, _user} = User.update_and_set_cache(cng) - json(conn, info) end @@ -293,40 +285,33 @@ def right_get(conn, %{"nickname" => nickname}) do }) end + def right_delete(%{assigns: %{user: %{nickname: nickname}}} = conn, %{"nickname" => nickname}) do + render_error(conn, :forbidden, "You can't revoke your own admin status.") + end + def right_delete( - %{assigns: %{user: %User{:nickname => admin_nickname} = admin}} = conn, + %{assigns: %{user: admin}} = conn, %{ "permission_group" => permission_group, "nickname" => nickname } ) when permission_group in ["moderator", "admin"] do - if admin_nickname == nickname do - render_error(conn, :forbidden, "You can't revoke your own admin status.") - else - user = User.get_cached_by_nickname(nickname) + info = Map.put(%{}, "is_" <> permission_group, false) - info = - %{} - |> Map.put("is_" <> permission_group, false) + {:ok, user} = + nickname + |> User.get_cached_by_nickname() + |> User.update_info(&User.Info.admin_api_update(&1, info)) - info_cng = User.Info.admin_api_update(user.info, info) + ModerationLog.insert_log(%{ + action: "revoke", + actor: admin, + subject: user, + permission: permission_group + }) - cng = - Ecto.Changeset.change(user) - |> Ecto.Changeset.put_embed(:info, info_cng) - - {:ok, _user} = User.update_and_set_cache(cng) - - ModerationLog.insert_log(%{ - action: "revoke", - actor: admin, - subject: user, - permission: permission_group - }) - - json(conn, info) - end + json(conn, info) end def right_delete(conn, _) do diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 5faddc9f4..2f12ad43a 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -302,12 +302,11 @@ def post(user, %{"status" => status} = data) do # Updates the emojis for a user based on their profile def update(user) do + emoji = emoji_from_profile(user) + source_data = user.info |> Map.get(:source_data, {}) |> Map.put("tag", emoji) + user = - with emoji <- emoji_from_profile(user), - source_data <- (user.info.source_data || %{}) |> Map.put("tag", emoji), - info_cng <- User.Info.set_source_data(user.info, source_data), - change <- Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_cng), - {:ok, user} <- User.update_and_set_cache(change) do + with {:ok, user} <- User.update_info(user, &User.Info.set_source_data(&1, source_data)) do user else _e -> @@ -336,10 +335,7 @@ def pin(id_or_ap_id, %{ap_id: user_ap_id} = user) do } } = activity <- get_by_id_or_ap_id(id_or_ap_id), true <- Visibility.is_public?(activity), - %{valid?: true} = info_changeset <- User.Info.add_pinnned_activity(user.info, activity), - changeset <- - Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset), - {:ok, _user} <- User.update_and_set_cache(changeset) do + {:ok, _user} <- User.update_info(user, &User.Info.add_pinnned_activity(&1, activity)) do {:ok, activity} else %{errors: [pinned_activities: {err, _}]} -> @@ -352,11 +348,7 @@ def pin(id_or_ap_id, %{ap_id: user_ap_id} = user) do def unpin(id_or_ap_id, user) do with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), - %{valid?: true} = info_changeset <- - User.Info.remove_pinnned_activity(user.info, activity), - changeset <- - Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset), - {:ok, _user} <- User.update_and_set_cache(changeset) do + {:ok, _user} <- User.update_info(user, &User.Info.remove_pinnned_activity(&1, activity)) do {:ok, activity} else %{errors: [pinned_activities: {err, _}]} -> @@ -462,9 +454,7 @@ def hide_reblogs(user, muted) do ap_id = muted.ap_id if ap_id not in user.info.muted_reblogs do - info_changeset = User.Info.add_reblog_mute(user.info, ap_id) - changeset = Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset) - User.update_and_set_cache(changeset) + User.update_info(user, &User.Info.add_reblog_mute(&1, ap_id)) end end @@ -472,9 +462,7 @@ def show_reblogs(user, muted) do ap_id = muted.ap_id if ap_id in user.info.muted_reblogs do - info_changeset = User.Info.remove_reblog_mute(user.info, ap_id) - changeset = Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset) - User.update_and_set_cache(changeset) + User.update_info(user, &User.Info.remove_reblog_mute(&1, ap_id)) end end end diff --git a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex index 270c74089..8a5287079 100644 --- a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex @@ -188,14 +188,13 @@ def update_credentials(%{assigns: %{user: user}} = conn, params) do end) |> Map.put(:emoji, user_info_emojis) - info_cng = User.Info.profile_update(user.info, info_params) + changeset = + user + |> User.update_changeset(user_params) + |> User.change_info(&User.Info.profile_update(&1, info_params)) - with changeset <- User.update_changeset(user, user_params), - changeset <- Changeset.put_embed(changeset, :info, info_cng), - {:ok, user} <- User.update_and_set_cache(changeset) do - if original_user != user do - CommonAPI.update(user) - end + with {:ok, user} <- User.update_and_set_cache(changeset) do + if original_user != user, do: CommonAPI.update(user) json( conn, @@ -225,12 +224,10 @@ def update_avatar(%{assigns: %{user: user}} = conn, params) do end def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do - with new_info <- %{"banner" => %{}}, - info_cng <- User.Info.profile_update(user.info, new_info), - changeset <- Changeset.change(user) |> Changeset.put_embed(:info, info_cng), - {:ok, user} <- User.update_and_set_cache(changeset) do - CommonAPI.update(user) + new_info = %{"banner" => %{}} + with {:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do + CommonAPI.update(user) json(conn, %{url: nil}) end end @@ -238,9 +235,7 @@ def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do def update_banner(%{assigns: %{user: user}} = conn, params) do with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner), new_info <- %{"banner" => object.data}, - info_cng <- User.Info.profile_update(user.info, new_info), - changeset <- Changeset.change(user) |> Changeset.put_embed(:info, info_cng), - {:ok, user} <- User.update_and_set_cache(changeset) do + {:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do CommonAPI.update(user) %{"url" => [%{"href" => href} | _]} = object.data @@ -249,10 +244,9 @@ def update_banner(%{assigns: %{user: user}} = conn, params) do end def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do - with new_info <- %{"background" => %{}}, - info_cng <- User.Info.profile_update(user.info, new_info), - changeset <- Changeset.change(user) |> Changeset.put_embed(:info, info_cng), - {:ok, _user} <- User.update_and_set_cache(changeset) do + new_info = %{"background" => %{}} + + with {:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do json(conn, %{url: nil}) end end @@ -260,9 +254,7 @@ def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do def update_background(%{assigns: %{user: user}} = conn, params) do with {:ok, object} <- ActivityPub.upload(params, type: :background), new_info <- %{"background" => object.data}, - info_cng <- User.Info.profile_update(user.info, new_info), - changeset <- Changeset.change(user) |> Changeset.put_embed(:info, info_cng), - {:ok, _user} <- User.update_and_set_cache(changeset) do + {:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do %{"url" => [%{"href" => href} | _]} = object.data json(conn, %{url: href}) @@ -816,26 +808,16 @@ def upload(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do def set_mascot(%{assigns: %{user: user}} = conn, %{"file" => file}) do with {:ok, object} <- ActivityPub.upload(file, actor: User.ap_id(user)), %{} = attachment_data <- Map.put(object.data, "id", object.id), - %{type: type} = rendered <- + # Reject if not an image + %{type: "image"} = rendered <- StatusView.render("attachment.json", %{attachment: attachment_data}) do - # Reject if not an image - if type == "image" do - # Sure! - # Save to the user's info - info_changeset = User.Info.mascot_update(user.info, rendered) + # Sure! + # Save to the user's info + {:ok, _user} = User.update_info(user, &User.Info.mascot_update(&1, rendered)) - user_changeset = - user - |> Changeset.change() - |> Changeset.put_embed(:info, info_changeset) - - {:ok, _user} = User.update_and_set_cache(user_changeset) - - conn - |> json(rendered) - else - render_error(conn, :unsupported_media_type, "mascots can only be images") - end + json(conn, rendered) + else + %{type: _} -> render_error(conn, :unsupported_media_type, "mascots can only be images") end end @@ -1366,11 +1348,7 @@ def index(%{assigns: %{user: user}} = conn, _params) do end def put_settings(%{assigns: %{user: user}} = conn, %{"data" => settings} = _params) do - info_cng = User.Info.mastodon_settings_update(user.info, settings) - - with changeset <- Changeset.change(user), - changeset <- Changeset.put_embed(changeset, :info, info_cng), - {:ok, _user} <- User.update_and_set_cache(changeset) do + with {:ok, _user} <- User.update_info(user, &User.Info.mastodon_settings_update(&1, settings)) do json(conn, %{}) else e -> diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 42234ae09..27f3664e0 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -5,7 +5,6 @@ defmodule Pleroma.Web.TwitterAPI.Controller do use Pleroma.Web, :controller - alias Ecto.Changeset alias Pleroma.Notification alias Pleroma.User alias Pleroma.Web.OAuth.Token @@ -16,15 +15,14 @@ defmodule Pleroma.Web.TwitterAPI.Controller do action_fallback(:errors) def confirm_email(conn, %{"user_id" => uid, "token" => token}) do - with %User{} = user <- User.get_cached_by_id(uid), true <- user.local, true <- user.info.confirmation_pending, true <- user.info.confirmation_token == token, - info_change <- User.Info.confirmation_changeset(user.info, need_confirmation: false), - changeset <- Changeset.change(user) |> Changeset.put_embed(:info, info_change), - {:ok, _} <- User.update_and_set_cache(changeset) do conn |> redirect(to: "/") + with %User{info: info} = user <- User.get_cached_by_id(uid), + {:ok, _} <- + User.update_info(user, &User.Info.confirmation_changeset(&1, need_confirmation: false)) do end end diff --git a/test/tasks/database_test.exs b/test/tasks/database_test.exs index a9925c361..b63dcac00 100644 --- a/test/tasks/database_test.exs +++ b/test/tasks/database_test.exs @@ -77,12 +77,10 @@ test "following and followers count are updated" do assert length(following) == 2 assert info.follower_count == 0 - info_cng = Ecto.Changeset.change(info, %{follower_count: 3}) - {:ok, user} = user |> Ecto.Changeset.change(%{following: following ++ following}) - |> Ecto.Changeset.put_embed(:info, info_cng) + |> User.change_info(&Ecto.Changeset.change(&1, %{follower_count: 3})) |> Repo.update() assert length(user.following) == 4 diff --git a/test/user_test.exs b/test/user_test.exs index 21ea1d28e..126bd69e8 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -1707,4 +1707,22 @@ test "sets password_reset_pending to true", %{user: user} do assert password_reset_pending end end + + test "change_info/2" do + user = insert(:user) + assert user.info.hide_follows == false + + changeset = User.change_info(user, &User.Info.profile_update(&1, %{hide_follows: true})) + assert changeset.changes.info.changes.hide_follows == true + end + + test "update_info/2" do + user = insert(:user) + assert user.info.hide_follows == false + + assert {:ok, _} = User.update_info(user, &User.Info.profile_update(&1, %{hide_follows: true})) + + assert %{info: %{hide_follows: true}} = Repo.get(User, user.id) + assert {:ok, %{info: %{hide_follows: true}}} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}") + end end diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index 73a3bf135..e32468f85 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -2613,14 +2613,11 @@ test "get instance stats", %{conn: conn} do {:ok, _} = CommonAPI.post(user, %{"status" => "cofe"}) # Stats should count users with missing or nil `info.deactivated` value - user = User.get_cached_by_id(user.id) - info_change = Changeset.change(user.info, %{deactivated: nil}) {:ok, _user} = - user - |> Changeset.change() - |> Changeset.put_embed(:info, info_change) - |> User.update_and_set_cache() + user.id + |> User.get_cached_by_id() + |> User.update_info(&Changeset.change(&1, %{deactivated: nil})) Pleroma.Stats.force_update() @@ -3953,13 +3950,9 @@ test "it returns 400 when user is not local", %{conn: conn, user: user} do describe "POST /api/v1/pleroma/accounts/confirmation_resend" do setup do - user = insert(:user) - info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true) - {:ok, user} = - user - |> Changeset.change() - |> Changeset.put_embed(:info, info_change) + insert(:user) + |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true)) |> Repo.update() assert user.info.confirmation_pending diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs index 8b88fd784..0cf755806 100644 --- a/test/web/oauth/oauth_controller_test.exs +++ b/test/web/oauth/oauth_controller_test.exs @@ -7,6 +7,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do import Pleroma.Factory alias Pleroma.Repo + alias Pleroma.User alias Pleroma.Web.OAuth.Authorization alias Pleroma.Web.OAuth.OAuthController alias Pleroma.Web.OAuth.Token @@ -775,15 +776,11 @@ test "rejects token exchange with invalid client credentials" do test "rejects token exchange for valid credentials belonging to unconfirmed user and confirmation is required" do Pleroma.Config.put([:instance, :account_activation_required], true) - password = "testpassword" - user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password)) - info_change = Pleroma.User.Info.confirmation_changeset(user.info, need_confirmation: true) {:ok, user} = - user - |> Ecto.Changeset.change() - |> Ecto.Changeset.put_embed(:info, info_change) + insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password)) + |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true)) |> Repo.update() refute Pleroma.User.auth_active?(user) diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs index ec96f0012..2b40fb47e 100644 --- a/test/web/ostatus/ostatus_controller_test.exs +++ b/test/web/ostatus/ostatus_controller_test.exs @@ -50,20 +50,16 @@ test "decodes a salmon with a changed magic key", %{conn: conn} do assert response(conn, 200) end) =~ "[error]" - # Set a wrong magic-key for a user so it has to refetch - salmon_user = User.get_cached_by_ap_id("http://gs.example.org:4040/index.php/user/1") - # Wrong key - info_cng = - User.Info.remote_user_creation(salmon_user.info, %{ - magic_key: - "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB" - }) + info = %{ + magic_key: + "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB" + } - salmon_user - |> Ecto.Changeset.change() - |> Ecto.Changeset.put_embed(:info, info_cng) - |> User.update_and_set_cache() + # Set a wrong magic-key for a user so it has to refetch + "http://gs.example.org:4040/index.php/user/1" + |> User.get_cached_by_ap_id() + |> User.update_info(&User.Info.remote_user_creation(&1, info)) assert capture_log(fn -> conn =