Add User.change_info/2 and User.update_info/2

This commit is contained in:
Egor Kislitsyn 2019-09-24 19:50:07 +07:00
parent 79b25be4e1
commit 209395c7e6
12 changed files with 146 additions and 307 deletions

View file

@ -4,7 +4,6 @@
defmodule Mix.Tasks.Pleroma.User do defmodule Mix.Tasks.Pleroma.User do
use Mix.Task use Mix.Task
import Ecto.Changeset
import Mix.Pleroma import Mix.Pleroma
alias Pleroma.User alias Pleroma.User
alias Pleroma.UserInviteToken alias Pleroma.UserInviteToken
@ -443,39 +442,21 @@ defmodule Mix.Tasks.Pleroma.User do
end end
defp set_moderator(user, value) do defp set_moderator(user, value) do
info_cng = User.Info.admin_api_update(user.info, %{is_moderator: value}) {:ok, user} = User.update_info(user, &User.Info.admin_api_update(&1, %{is_moderator: value}))
user_cng =
Ecto.Changeset.change(user)
|> put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(user_cng)
shell_info("Moderator status of #{user.nickname}: #{user.info.is_moderator}") shell_info("Moderator status of #{user.nickname}: #{user.info.is_moderator}")
user user
end end
defp set_admin(user, value) do defp set_admin(user, value) do
info_cng = User.Info.admin_api_update(user.info, %{is_admin: value}) {:ok, user} = User.update_info(user, &User.Info.admin_api_update(&1, %{is_admin: value}))
user_cng =
Ecto.Changeset.change(user)
|> put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(user_cng)
shell_info("Admin status of #{user.nickname}: #{user.info.is_admin}") shell_info("Admin status of #{user.nickname}: #{user.info.is_admin}")
user user
end end
defp set_locked(user, value) do defp set_locked(user, value) do
info_cng = User.Info.user_upgrade(user.info, %{locked: value}) {:ok, user} = User.update_info(user, &User.Info.user_upgrade(&1, %{locked: value}))
user_cng =
Ecto.Changeset.change(user)
|> put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(user_cng)
shell_info("Locked status of #{user.nickname}: #{user.info.locked}") shell_info("Locked status of #{user.nickname}: #{user.info.locked}")
user user

View file

@ -197,8 +197,6 @@ defmodule Pleroma.User do
|> truncate_if_exists(:name, name_limit) |> truncate_if_exists(:name, name_limit)
|> truncate_if_exists(:bio, bio_limit) |> truncate_if_exists(:bio, bio_limit)
info_cng = User.Info.remote_user_creation(%User.Info{}, params[:info])
changes = changes =
%User{} %User{}
|> cast(params, [:bio, :name, :ap_id, :nickname, :avatar]) |> cast(params, [:bio, :name, :ap_id, :nickname, :avatar])
@ -208,7 +206,7 @@ defmodule Pleroma.User do
|> validate_length(:bio, max: bio_limit) |> validate_length(:bio, max: bio_limit)
|> validate_length(:name, max: name_limit) |> validate_length(:name, max: name_limit)
|> put_change(:local, false) |> put_change(:local, false)
|> put_embed(:info, info_cng) |> change_info(&User.Info.remote_user_creation(&1, params[:info]))
if changes.valid? do if changes.valid? do
case info_cng.changes[:source_data] do case info_cng.changes[:source_data] do
@ -245,7 +243,6 @@ defmodule Pleroma.User do
name_limit = Pleroma.Config.get([:instance, :user_name_length], 100) name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
params = Map.put(params, :last_refreshed_at, NaiveDateTime.utc_now()) params = Map.put(params, :last_refreshed_at, NaiveDateTime.utc_now())
info_cng = User.Info.user_upgrade(struct.info, params[:info], remote?)
struct struct
|> cast(params, [ |> cast(params, [
@ -260,7 +257,7 @@ defmodule Pleroma.User do
|> validate_format(:nickname, local_nickname_regex()) |> validate_format(:nickname, local_nickname_regex())
|> validate_length(:bio, max: bio_limit) |> validate_length(:bio, max: bio_limit)
|> validate_length(:name, max: name_limit) |> validate_length(:name, max: name_limit)
|> put_embed(:info, info_cng) |> change_info(&User.Info.user_upgrade(&1, params[:info], remote?))
end end
def password_update_changeset(struct, params) do def password_update_changeset(struct, params) do
@ -785,21 +782,15 @@ defmodule Pleroma.User do
end end
def update_note_count(%User{} = user) do def update_note_count(%User{} = user) do
note_count_query = note_count =
from( from(
a in Object, a in Object,
where: fragment("?->>'actor' = ? and ?->>'type' = 'Note'", a.data, ^user.ap_id, a.data), where: fragment("?->>'actor' = ? and ?->>'type' = 'Note'", a.data, ^user.ap_id, a.data),
select: count(a.id) select: count(a.id)
) )
|> Repo.one()
note_count = Repo.one(note_count_query) update_info(user, &User.Info.set_note_count(&1, note_count))
info_cng = User.Info.set_note_count(user.info, note_count)
user
|> change()
|> put_embed(:info, info_cng)
|> update_and_set_cache()
end end
@spec maybe_fetch_follow_information(User.t()) :: User.t() @spec maybe_fetch_follow_information(User.t()) :: User.t()
@ -816,17 +807,7 @@ defmodule Pleroma.User do
def fetch_follow_information(user) do def fetch_follow_information(user) do
with {:ok, info} <- ActivityPub.fetch_follow_information_for_user(user) do with {:ok, info} <- ActivityPub.fetch_follow_information_for_user(user) do
info_cng = User.Info.follow_information_update(user.info, info) update_info(user, &User.Info.follow_information_update(&1, info))
changeset =
user
|> change()
|> put_embed(:info, info_cng)
update_and_set_cache(changeset)
else
{:error, _} = e -> e
e -> {:error, e}
end end
end end
@ -900,31 +881,11 @@ defmodule Pleroma.User do
@spec mute(User.t(), User.t(), boolean()) :: {:ok, User.t()} | {:error, String.t()} @spec mute(User.t(), User.t(), boolean()) :: {:ok, User.t()} | {:error, String.t()}
def mute(muter, %User{ap_id: ap_id}, notifications? \\ true) do def mute(muter, %User{ap_id: ap_id}, notifications? \\ true) do
info = muter.info update_info(muter, &User.Info.add_to_mutes(&1, ap_id, notifications?))
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)
end end
def unmute(muter, %{ap_id: ap_id}) do def unmute(muter, %{ap_id: ap_id}) do
info = muter.info update_info(muter, &User.Info.remove_from_mutes(&1, ap_id))
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)
end end
def subscribe(subscriber, %{ap_id: ap_id}) do def subscribe(subscriber, %{ap_id: ap_id}) do
@ -936,26 +897,14 @@ defmodule Pleroma.User do
if blocked do if blocked do
{:error, "Could not subscribe: #{subscribed.nickname} is blocking you"} {:error, "Could not subscribe: #{subscribed.nickname} is blocking you"}
else else
info_cng = update_info(subscribed, &User.Info.add_to_subscribers(&1, subscriber.ap_id))
subscribed.info
|> User.Info.add_to_subscribers(subscriber.ap_id)
change(subscribed)
|> put_embed(:info, info_cng)
|> update_and_set_cache()
end end
end end
end end
def unsubscribe(unsubscriber, %{ap_id: ap_id}) do def unsubscribe(unsubscriber, %{ap_id: ap_id}) do
with %User{} = user <- get_cached_by_ap_id(ap_id) do with %User{} = user <- get_cached_by_ap_id(ap_id) do
info_cng = update_info(user, &User.Info.remove_from_subscribers(&1, unsubscriber.ap_id))
user.info
|> User.Info.remove_from_subscribers(unsubscriber.ap_id)
change(user)
|> put_embed(:info, info_cng)
|> update_and_set_cache()
end end
end end
@ -990,15 +939,7 @@ defmodule Pleroma.User do
{:ok, blocker} = update_follower_count(blocker) {:ok, blocker} = update_follower_count(blocker)
info_cng = update_info(blocker, &User.Info.add_to_block(&1, ap_id))
blocker.info
|> User.Info.add_to_block(ap_id)
cng =
change(blocker)
|> put_embed(:info, info_cng)
update_and_set_cache(cng)
end end
# helper to handle the block given only an actor's AP id # helper to handle the block given only an actor's AP id
@ -1007,15 +948,7 @@ defmodule Pleroma.User do
end end
def unblock(blocker, %{ap_id: ap_id}) do def unblock(blocker, %{ap_id: ap_id}) do
info_cng = update_info(blocker, &User.Info.remove_from_block(&1, ap_id))
blocker.info
|> User.Info.remove_from_block(ap_id)
cng =
change(blocker)
|> put_embed(:info, info_cng)
update_and_set_cache(cng)
end end
def mutes?(nil, _), do: false def mutes?(nil, _), do: false
@ -1072,27 +1005,11 @@ defmodule Pleroma.User do
end end
def block_domain(user, domain) do def block_domain(user, domain) do
info_cng = update_info(user, &User.Info.add_to_domain_block(&1, domain))
user.info
|> User.Info.add_to_domain_block(domain)
cng =
change(user)
|> put_embed(:info, info_cng)
update_and_set_cache(cng)
end end
def unblock_domain(user, domain) do def unblock_domain(user, domain) do
info_cng = update_info(user, &User.Info.remove_from_domain_block(&1, domain))
user.info
|> User.Info.remove_from_domain_block(domain)
cng =
change(user)
|> put_embed(:info, info_cng)
update_and_set_cache(cng)
end end
def deactivate_async(user, status \\ true) do def deactivate_async(user, status \\ true) do
@ -1100,13 +1017,7 @@ defmodule Pleroma.User do
end end
def deactivate(%User{} = user, status \\ true) do def deactivate(%User{} = user, status \\ true) do
info_cng = User.Info.set_activation_status(user.info, status) with {:ok, user} <- update_info(user, &User.Info.set_activation_status(&1, status)) do
with {:ok, user} <-
user
|> change()
|> put_embed(:info, info_cng)
|> update_and_set_cache() do
Enum.each(get_followers(user), &invalidate_cache/1) Enum.each(get_followers(user), &invalidate_cache/1)
Enum.each(get_friends(user), &update_follower_count/1) Enum.each(get_friends(user), &update_follower_count/1)
@ -1115,11 +1026,7 @@ defmodule Pleroma.User do
end end
def update_notification_settings(%User{} = user, settings \\ %{}) do def update_notification_settings(%User{} = user, settings \\ %{}) do
info_changeset = User.Info.update_notification_settings(user.info, settings) update_info(user, &User.Info.update_notification_settings(&1, settings))
change(user)
|> put_embed(:info, info_changeset)
|> update_and_set_cache()
end end
def delete(%User{} = user) do def delete(%User{} = user) do
@ -1560,11 +1467,7 @@ defmodule Pleroma.User do
@spec switch_email_notifications(t(), String.t(), boolean()) :: @spec switch_email_notifications(t(), String.t(), boolean()) ::
{:ok, t()} | {:error, Ecto.Changeset.t()} {:ok, t()} | {:error, Ecto.Changeset.t()}
def switch_email_notifications(user, type, status) do def switch_email_notifications(user, type, status) do
info = Pleroma.User.Info.update_email_notifications(user.info, %{type => status}) update_info(user, &User.Info.update_email_notifications(&1, %{type => status}))
change(user)
|> put_embed(:info, info)
|> update_and_set_cache()
end end
@doc """ @doc """
@ -1586,13 +1489,8 @@ defmodule Pleroma.User do
def toggle_confirmation(%User{} = user) do def toggle_confirmation(%User{} = user) do
need_confirmation? = !user.info.confirmation_pending need_confirmation? = !user.info.confirmation_pending
info_changeset =
User.Info.confirmation_changeset(user.info, need_confirmation: need_confirmation?)
user user
|> change() |> update_info(&User.Info.confirmation_changeset(&1, need_confirmation: need_confirmation?))
|> put_embed(:info, info_changeset)
|> update_and_set_cache()
end end
def get_mascot(%{info: %{mascot: %{} = mascot}}) when not is_nil(mascot) do def get_mascot(%{info: %{mascot: %{} = mascot}}) when not is_nil(mascot) do
@ -1615,16 +1513,11 @@ defmodule Pleroma.User do
} }
end end
def ensure_keys_present(%User{info: info} = user) do def ensure_keys_present(%{info: %{keys: keys}} = user) when not is_nil(keys), do: {:ok, user}
if info.keys do
{:ok, user}
else
{:ok, pem} = Keys.generate_rsa_pem()
user def ensure_keys_present(%User{} = user) do
|> Ecto.Changeset.change() with {:ok, pem} <- Keys.generate_rsa_pem() do
|> Ecto.Changeset.put_embed(:info, User.Info.set_keys(info, pem)) update_info(user, &User.Info.set_keys(&1, pem))
|> update_and_set_cache()
end end
end end
@ -1670,4 +1563,26 @@ defmodule Pleroma.User do
|> validate_format(:email, @email_regex) |> validate_format(:email, @email_regex)
|> update_and_set_cache() |> update_and_set_cache()
end 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 end

View file

@ -187,16 +187,11 @@ defmodule Pleroma.User.Info do
|> validate_required([:subscribers]) |> validate_required([:subscribers])
end end
@spec add_to_mutes(Info.t(), String.t()) :: Changeset.t() @spec add_to_mutes(Info.t(), String.t(), boolean()) :: Changeset.t()
def add_to_mutes(info, muted) do def add_to_mutes(info, muted, notifications?) do
set_mutes(info, Enum.uniq([muted | info.mutes])) info
end |> set_mutes(Enum.uniq([muted | info.mutes]))
|> set_notification_mutes(
@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,
Enum.uniq([muted | info.muted_notifications]), Enum.uniq([muted | info.muted_notifications]),
notifications? notifications?
) )
@ -204,12 +199,9 @@ defmodule Pleroma.User.Info do
@spec remove_from_mutes(Info.t(), String.t()) :: Changeset.t() @spec remove_from_mutes(Info.t(), String.t()) :: Changeset.t()
def remove_from_mutes(info, muted) do def remove_from_mutes(info, muted) do
set_mutes(info, List.delete(info.mutes, muted)) info
end |> set_mutes(List.delete(info.mutes, muted))
|> set_notification_mutes(List.delete(info.muted_notifications, muted), true)
@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)
end end
def add_to_block(info, blocked) do def add_to_block(info, blocked) do

View file

@ -254,18 +254,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
"nickname" => nickname "nickname" => nickname
}) })
when permission_group in ["moderator", "admin"] do when permission_group in ["moderator", "admin"] do
user = User.get_cached_by_nickname(nickname) info = Map.put(%{}, "is_" <> permission_group, true)
info = {:ok, user} =
%{} nickname
|> Map.put("is_" <> permission_group, true) |> 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)
cng =
user
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_embed(:info, info_cng)
ModerationLog.insert_log(%{ ModerationLog.insert_log(%{
action: "grant", action: "grant",
@ -274,8 +268,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
permission: permission_group permission: permission_group
}) })
{:ok, _user} = User.update_and_set_cache(cng)
json(conn, info) json(conn, info)
end end
@ -293,40 +285,33 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
}) })
end 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( def right_delete(
%{assigns: %{user: %User{:nickname => admin_nickname} = admin}} = conn, %{assigns: %{user: admin}} = conn,
%{ %{
"permission_group" => permission_group, "permission_group" => permission_group,
"nickname" => nickname "nickname" => nickname
} }
) )
when permission_group in ["moderator", "admin"] do when permission_group in ["moderator", "admin"] do
if admin_nickname == nickname do info = Map.put(%{}, "is_" <> permission_group, false)
render_error(conn, :forbidden, "You can't revoke your own admin status.")
else
user = User.get_cached_by_nickname(nickname)
info = {:ok, user} =
%{} nickname
|> Map.put("is_" <> permission_group, false) |> 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 = json(conn, info)
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
end end
def right_delete(conn, _) do def right_delete(conn, _) do

View file

@ -302,12 +302,11 @@ defmodule Pleroma.Web.CommonAPI do
# Updates the emojis for a user based on their profile # Updates the emojis for a user based on their profile
def update(user) do def update(user) do
emoji = emoji_from_profile(user)
source_data = user.info |> Map.get(:source_data, {}) |> Map.put("tag", emoji)
user = user =
with emoji <- emoji_from_profile(user), with {:ok, user} <- User.update_info(user, &User.Info.set_source_data(&1, source_data)) do
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
user user
else else
_e -> _e ->
@ -336,10 +335,7 @@ defmodule Pleroma.Web.CommonAPI do
} }
} = activity <- get_by_id_or_ap_id(id_or_ap_id), } = activity <- get_by_id_or_ap_id(id_or_ap_id),
true <- Visibility.is_public?(activity), true <- Visibility.is_public?(activity),
%{valid?: true} = info_changeset <- User.Info.add_pinnned_activity(user.info, activity), {:ok, _user} <- User.update_info(user, &User.Info.add_pinnned_activity(&1, activity)) do
changeset <-
Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset),
{:ok, _user} <- User.update_and_set_cache(changeset) do
{:ok, activity} {:ok, activity}
else else
%{errors: [pinned_activities: {err, _}]} -> %{errors: [pinned_activities: {err, _}]} ->
@ -352,11 +348,7 @@ defmodule Pleroma.Web.CommonAPI do
def unpin(id_or_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), with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
%{valid?: true} = info_changeset <- {:ok, _user} <- User.update_info(user, &User.Info.remove_pinnned_activity(&1, activity)) do
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, activity} {:ok, activity}
else else
%{errors: [pinned_activities: {err, _}]} -> %{errors: [pinned_activities: {err, _}]} ->
@ -462,9 +454,7 @@ defmodule Pleroma.Web.CommonAPI do
ap_id = muted.ap_id ap_id = muted.ap_id
if ap_id not in user.info.muted_reblogs do if ap_id not in user.info.muted_reblogs do
info_changeset = User.Info.add_reblog_mute(user.info, ap_id) User.update_info(user, &User.Info.add_reblog_mute(&1, ap_id))
changeset = Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset)
User.update_and_set_cache(changeset)
end end
end end
@ -472,9 +462,7 @@ defmodule Pleroma.Web.CommonAPI do
ap_id = muted.ap_id ap_id = muted.ap_id
if ap_id in user.info.muted_reblogs do if ap_id in user.info.muted_reblogs do
info_changeset = User.Info.remove_reblog_mute(user.info, ap_id) User.update_info(user, &User.Info.remove_reblog_mute(&1, ap_id))
changeset = Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset)
User.update_and_set_cache(changeset)
end end
end end
end end

View file

@ -188,14 +188,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end) end)
|> Map.put(:emoji, user_info_emojis) |> 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), with {:ok, user} <- User.update_and_set_cache(changeset) do
changeset <- Changeset.put_embed(changeset, :info, info_cng), if original_user != user, do: CommonAPI.update(user)
{:ok, user} <- User.update_and_set_cache(changeset) do
if original_user != user do
CommonAPI.update(user)
end
json( json(
conn, conn,
@ -225,12 +224,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end end
def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do
with new_info <- %{"banner" => %{}}, 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)
with {:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
CommonAPI.update(user)
json(conn, %{url: nil}) json(conn, %{url: nil})
end end
end end
@ -238,9 +235,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
def update_banner(%{assigns: %{user: user}} = conn, params) do def update_banner(%{assigns: %{user: user}} = conn, params) do
with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner), with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner),
new_info <- %{"banner" => object.data}, new_info <- %{"banner" => object.data},
info_cng <- User.Info.profile_update(user.info, new_info), {:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
changeset <- Changeset.change(user) |> Changeset.put_embed(:info, info_cng),
{:ok, user} <- User.update_and_set_cache(changeset) do
CommonAPI.update(user) CommonAPI.update(user)
%{"url" => [%{"href" => href} | _]} = object.data %{"url" => [%{"href" => href} | _]} = object.data
@ -249,10 +244,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end end
def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
with new_info <- %{"background" => %{}}, new_info = %{"background" => %{}}
info_cng <- User.Info.profile_update(user.info, new_info),
changeset <- Changeset.change(user) |> Changeset.put_embed(:info, info_cng), with {:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
{:ok, _user} <- User.update_and_set_cache(changeset) do
json(conn, %{url: nil}) json(conn, %{url: nil})
end end
end end
@ -260,9 +254,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
def update_background(%{assigns: %{user: user}} = conn, params) do def update_background(%{assigns: %{user: user}} = conn, params) do
with {:ok, object} <- ActivityPub.upload(params, type: :background), with {:ok, object} <- ActivityPub.upload(params, type: :background),
new_info <- %{"background" => object.data}, new_info <- %{"background" => object.data},
info_cng <- User.Info.profile_update(user.info, new_info), {:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
changeset <- Changeset.change(user) |> Changeset.put_embed(:info, info_cng),
{:ok, _user} <- User.update_and_set_cache(changeset) do
%{"url" => [%{"href" => href} | _]} = object.data %{"url" => [%{"href" => href} | _]} = object.data
json(conn, %{url: href}) json(conn, %{url: href})
@ -816,26 +808,16 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
def set_mascot(%{assigns: %{user: user}} = conn, %{"file" => file}) do def set_mascot(%{assigns: %{user: user}} = conn, %{"file" => file}) do
with {:ok, object} <- ActivityPub.upload(file, actor: User.ap_id(user)), with {:ok, object} <- ActivityPub.upload(file, actor: User.ap_id(user)),
%{} = attachment_data <- Map.put(object.data, "id", object.id), %{} = 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 StatusView.render("attachment.json", %{attachment: attachment_data}) do
# Reject if not an image # Sure!
if type == "image" do # Save to the user's info
# Sure! {:ok, _user} = User.update_info(user, &User.Info.mascot_update(&1, rendered))
# Save to the user's info
info_changeset = User.Info.mascot_update(user.info, rendered)
user_changeset = json(conn, rendered)
user else
|> Changeset.change() %{type: _} -> render_error(conn, :unsupported_media_type, "mascots can only be images")
|> 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
end end
end end
@ -1366,11 +1348,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end end
def put_settings(%{assigns: %{user: user}} = conn, %{"data" => settings} = _params) do def put_settings(%{assigns: %{user: user}} = conn, %{"data" => settings} = _params) do
info_cng = User.Info.mastodon_settings_update(user.info, settings) with {:ok, _user} <- User.update_info(user, &User.Info.mastodon_settings_update(&1, settings)) do
with changeset <- Changeset.change(user),
changeset <- Changeset.put_embed(changeset, :info, info_cng),
{:ok, _user} <- User.update_and_set_cache(changeset) do
json(conn, %{}) json(conn, %{})
else else
e -> e ->

View file

@ -5,7 +5,6 @@
defmodule Pleroma.Web.TwitterAPI.Controller do defmodule Pleroma.Web.TwitterAPI.Controller do
use Pleroma.Web, :controller use Pleroma.Web, :controller
alias Ecto.Changeset
alias Pleroma.Notification alias Pleroma.Notification
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.OAuth.Token alias Pleroma.Web.OAuth.Token
@ -16,15 +15,14 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
action_fallback(:errors) action_fallback(:errors)
def confirm_email(conn, %{"user_id" => uid, "token" => token}) do def confirm_email(conn, %{"user_id" => uid, "token" => token}) do
with %User{} = user <- User.get_cached_by_id(uid),
true <- user.local, true <- user.local,
true <- user.info.confirmation_pending, true <- user.info.confirmation_pending,
true <- user.info.confirmation_token == token, 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 conn
|> redirect(to: "/") |> 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
end end

View file

@ -77,12 +77,10 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
assert length(following) == 2 assert length(following) == 2
assert info.follower_count == 0 assert info.follower_count == 0
info_cng = Ecto.Changeset.change(info, %{follower_count: 3})
{:ok, user} = {:ok, user} =
user user
|> Ecto.Changeset.change(%{following: following ++ following}) |> 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() |> Repo.update()
assert length(user.following) == 4 assert length(user.following) == 4

View file

@ -1707,4 +1707,22 @@ defmodule Pleroma.UserTest do
assert password_reset_pending assert password_reset_pending
end end
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 end

View file

@ -2613,14 +2613,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
{:ok, _} = CommonAPI.post(user, %{"status" => "cofe"}) {:ok, _} = CommonAPI.post(user, %{"status" => "cofe"})
# Stats should count users with missing or nil `info.deactivated` value # 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} = {:ok, _user} =
user user.id
|> Changeset.change() |> User.get_cached_by_id()
|> Changeset.put_embed(:info, info_change) |> User.update_info(&Changeset.change(&1, %{deactivated: nil}))
|> User.update_and_set_cache()
Pleroma.Stats.force_update() Pleroma.Stats.force_update()
@ -3953,13 +3950,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
describe "POST /api/v1/pleroma/accounts/confirmation_resend" do describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
setup do setup do
user = insert(:user)
info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
{:ok, user} = {:ok, user} =
user insert(:user)
|> Changeset.change() |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true))
|> Changeset.put_embed(:info, info_change)
|> Repo.update() |> Repo.update()
assert user.info.confirmation_pending assert user.info.confirmation_pending

View file

@ -7,6 +7,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.OAuth.Authorization alias Pleroma.Web.OAuth.Authorization
alias Pleroma.Web.OAuth.OAuthController alias Pleroma.Web.OAuth.OAuthController
alias Pleroma.Web.OAuth.Token alias Pleroma.Web.OAuth.Token
@ -775,15 +776,11 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
test "rejects token exchange for valid credentials belonging to unconfirmed user and confirmation is required" 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) Pleroma.Config.put([:instance, :account_activation_required], true)
password = "testpassword" 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} = {:ok, user} =
user insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
|> Ecto.Changeset.change() |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true))
|> Ecto.Changeset.put_embed(:info, info_change)
|> Repo.update() |> Repo.update()
refute Pleroma.User.auth_active?(user) refute Pleroma.User.auth_active?(user)

View file

@ -50,20 +50,16 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
assert response(conn, 200) assert response(conn, 200)
end) =~ "[error]" 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 # Wrong key
info_cng = info = %{
User.Info.remote_user_creation(salmon_user.info, %{ magic_key:
magic_key: "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB"
"RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB" }
})
salmon_user # Set a wrong magic-key for a user so it has to refetch
|> Ecto.Changeset.change() "http://gs.example.org:4040/index.php/user/1"
|> Ecto.Changeset.put_embed(:info, info_cng) |> User.get_cached_by_ap_id()
|> User.update_and_set_cache() |> User.update_info(&User.Info.remote_user_creation(&1, info))
assert capture_log(fn -> assert capture_log(fn ->
conn = conn =