[#1304] Moved all non-mutes / non-blocks fields from User.Info to User. WIP.

This commit is contained in:
Ivan Tashkinov 2019-10-16 21:59:21 +03:00
parent e3b4a3e96b
commit 10ff01acd9
88 changed files with 1069 additions and 1170 deletions

View file

@ -29,6 +29,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- MRF (Simple Policy): Also use `:accept`/`:reject` on the actors rather than only their activities - MRF (Simple Policy): Also use `:accept`/`:reject` on the actors rather than only their activities
- OStatus: Extract RSS functionality - OStatus: Extract RSS functionality
- Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`) - Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
- Deprecated `User.Info` embedded schema (fields moved to `User`)
### Fixed ### Fixed
- Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`) - Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`)

View file

@ -109,10 +109,10 @@ def run(["toggle_activated", nickname]) do
start_pleroma() start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do with %User{} = user <- User.get_cached_by_nickname(nickname) do
{:ok, user} = User.deactivate(user, !user.info.deactivated) {:ok, user} = User.deactivate(user, !user.deactivated)
shell_info( shell_info(
"Activation status of #{nickname}: #{if(user.info.deactivated, do: "de", else: "")}activated" "Activation status of #{nickname}: #{if(user.deactivated, do: "de", else: "")}activated"
) )
else else
_ -> _ ->
@ -340,7 +340,7 @@ def run(["toggle_confirmed", nickname]) do
with %User{} = user <- User.get_cached_by_nickname(nickname) do with %User{} = user <- User.get_cached_by_nickname(nickname) do
{:ok, user} = User.toggle_confirmation(user) {:ok, user} = User.toggle_confirmation(user)
message = if user.info.confirmation_pending, do: "needs", else: "doesn't need" message = if user.confirmation_pending, do: "needs", else: "doesn't need"
shell_info("#{nickname} #{message} confirmation.") shell_info("#{nickname} #{message} confirmation.")
else else
@ -364,23 +364,23 @@ def run(["sign_out", nickname]) do
end end
defp set_moderator(user, value) do defp set_moderator(user, value) do
{:ok, user} = User.update_info(user, &User.Info.admin_api_update(&1, %{is_moderator: value})) {:ok, user} = User.update_and_set_cache(user, %{is_moderator: value})
shell_info("Moderator status of #{user.nickname}: #{user.info.is_moderator}") shell_info("Moderator status of #{user.nickname}: #{user.is_moderator}")
user user
end end
defp set_admin(user, value) do defp set_admin(user, value) do
{:ok, user} = User.update_info(user, &User.Info.admin_api_update(&1, %{is_admin: value})) {:ok, user} = User.update_and_set_cache(user, %{is_admin: value})
shell_info("Admin status of #{user.nickname}: #{user.info.is_admin}") shell_info("Admin status of #{user.nickname}: #{user.is_admin}")
user user
end end
defp set_locked(user, value) do defp set_locked(user, value) do
{:ok, user} = User.update_info(user, &User.Info.user_upgrade(&1, %{locked: value})) {:ok, user} = User.update_and_set_cache(user, %{locked: value})
shell_info("Locked status of #{user.nickname}: #{user.info.locked}") shell_info("Locked status of #{user.nickname}: #{user.locked}")
user user
end end
end end

View file

@ -17,7 +17,7 @@ def perform do
now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
from(u in inactive_users_query, from(u in inactive_users_query,
where: fragment(~s(? #> '{"email_notifications","digest"}' @> 'true'), u.info), where: fragment(~s(? ->'digest' @> 'true'), u.email_notifications),
where: u.last_digest_emailed_at < datetime_add(^now, ^negative_interval, "day"), where: u.last_digest_emailed_at < datetime_add(^now, ^negative_interval, "day"),
select: u select: u
) )

View file

@ -72,7 +72,7 @@ def account_confirmation_email(user) do
Endpoint, Endpoint,
:confirm_email, :confirm_email,
user.id, user.id,
to_string(user.info.confirmation_token) to_string(user.confirmation_token)
) )
html_body = """ html_body = """

View file

@ -127,7 +127,7 @@ def truncate(text, max_length \\ 200, omission \\ "...") do
end end
end end
defp get_ap_id(%User{info: %{source_data: %{"url" => url}}}) when is_binary(url), do: url defp get_ap_id(%User{source_data: %{"url" => url}}) when is_binary(url), do: url
defp get_ap_id(%User{ap_id: ap_id}), do: ap_id defp get_ap_id(%User{ap_id: ap_id}), do: ap_id
defp get_nickname_text(nickname, %{mentions_format: :full}), do: User.full_nickname(nickname) defp get_nickname_text(nickname, %{mentions_format: :full}), do: User.full_nickname(nickname)

View file

@ -40,7 +40,7 @@ def for_user_query(user, opts \\ []) do
|> where( |> where(
[n, a], [n, a],
fragment( fragment(
"? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')", "? not in (SELECT ap_id FROM users WHERE deactivated = 'true')",
a.actor a.actor
) )
) )
@ -259,7 +259,7 @@ def skip?(:self, activity, user) do
def skip?( def skip?(
:followers, :followers,
activity, activity,
%{info: %{notification_settings: %{"followers" => false}}} = user %{notification_settings: %{"followers" => false}} = user
) do ) do
actor = activity.data["actor"] actor = activity.data["actor"]
follower = User.get_cached_by_ap_id(actor) follower = User.get_cached_by_ap_id(actor)
@ -269,14 +269,14 @@ def skip?(
def skip?( def skip?(
:non_followers, :non_followers,
activity, activity,
%{info: %{notification_settings: %{"non_followers" => false}}} = user %{notification_settings: %{"non_followers" => false}} = user
) do ) do
actor = activity.data["actor"] actor = activity.data["actor"]
follower = User.get_cached_by_ap_id(actor) follower = User.get_cached_by_ap_id(actor)
!User.following?(follower, user) !User.following?(follower, user)
end end
def skip?(:follows, activity, %{info: %{notification_settings: %{"follows" => false}}} = user) do def skip?(:follows, activity, %{notification_settings: %{"follows" => false}} = user) do
actor = activity.data["actor"] actor = activity.data["actor"]
followed = User.get_cached_by_ap_id(actor) followed = User.get_cached_by_ap_id(actor)
User.following?(user, followed) User.following?(user, followed)
@ -285,7 +285,7 @@ def skip?(:follows, activity, %{info: %{notification_settings: %{"follows" => fa
def skip?( def skip?(
:non_follows, :non_follows,
activity, activity,
%{info: %{notification_settings: %{"non_follows" => false}}} = user %{notification_settings: %{"non_follows" => false}} = user
) do ) do
actor = activity.data["actor"] actor = activity.data["actor"]
followed = User.get_cached_by_ap_id(actor) followed = User.get_cached_by_ap_id(actor)

View file

@ -19,7 +19,7 @@ def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
def call(%{params: %{"admin_token" => admin_token}} = conn, _) do def call(%{params: %{"admin_token" => admin_token}} = conn, _) do
if secret_token() && admin_token == secret_token() do if secret_token() && admin_token == secret_token() do
conn conn
|> assign(:user, %User{info: %{is_admin: true}}) |> assign(:user, %User{is_admin: true})
else else
conn conn
end end

View file

@ -71,7 +71,7 @@ defp fetch_user_and_token(token) do
) )
# credo:disable-for-next-line Credo.Check.Readability.MaxLineLength # credo:disable-for-next-line Credo.Check.Readability.MaxLineLength
with %Token{user: %{info: %{deactivated: false} = _} = user} = token_record <- Repo.one(query) do with %Token{user: %{deactivated: false} = user} = token_record <- Repo.one(query) do
{:ok, user, token_record} {:ok, user, token_record}
end end
end end

View file

@ -10,7 +10,7 @@ def init(options) do
options options
end end
def call(%{assigns: %{user: %User{info: %{deactivated: true}}}} = conn, _) do def call(%{assigns: %{user: %User{deactivated: true}}} = conn, _) do
conn conn
|> assign(:user, nil) |> assign(:user, nil)
end end

View file

@ -11,7 +11,7 @@ def init(options) do
options options
end end
def call(%{assigns: %{user: %User{info: %{is_admin: true}}}} = conn, _) do def call(%{assigns: %{user: %User{is_admin: true}}} = conn, _) do
conn conn
end end

View file

@ -68,12 +68,7 @@ defp get_stat_data do
domain_count = Enum.count(peers) domain_count = Enum.count(peers)
status_query = status_count = Repo.aggregate(User.Query.build(%{local: true}), :sum, :note_count)
from(u in User.Query.build(%{local: true}),
select: fragment("sum((?->>'note_count')::int)", u.info)
)
status_count = Repo.one(status_query)
user_count = Repo.aggregate(User.Query.build(%{local: true, active: true}), :count, :id) user_count = Repo.aggregate(User.Query.build(%{local: true, active: true}), :count, :id)

View file

@ -63,6 +63,62 @@ defmodule Pleroma.User do
field(:tags, {:array, :string}, default: []) field(:tags, {:array, :string}, default: [])
field(:last_refreshed_at, :naive_datetime_usec) field(:last_refreshed_at, :naive_datetime_usec)
field(:last_digest_emailed_at, :naive_datetime) field(:last_digest_emailed_at, :naive_datetime)
field(:banner, :map, default: %{})
field(:background, :map, default: %{})
field(:source_data, :map, default: %{})
field(:note_count, :integer, default: 0)
field(:follower_count, :integer, default: 0)
# Should be filled in only for remote users
field(:following_count, :integer, default: nil)
field(:locked, :boolean, default: false)
field(:confirmation_pending, :boolean, default: false)
field(:password_reset_pending, :boolean, default: false)
field(:confirmation_token, :string, default: nil)
field(:default_scope, :string, default: "public")
field(:blocks, {:array, :string}, default: [])
field(:domain_blocks, {:array, :string}, default: [])
field(:mutes, {:array, :string}, default: [])
field(:muted_reblogs, {:array, :string}, default: [])
field(:muted_notifications, {:array, :string}, default: [])
field(:subscribers, {:array, :string}, default: [])
field(:deactivated, :boolean, default: false)
field(:no_rich_text, :boolean, default: false)
field(:ap_enabled, :boolean, default: false)
field(:is_moderator, :boolean, default: false)
field(:is_admin, :boolean, default: false)
field(:show_role, :boolean, default: true)
field(:settings, :map, default: nil)
field(:magic_key, :string, default: nil)
field(:uri, :string, default: nil)
field(:topic, :string, default: nil)
field(:hub, :string, default: nil)
field(:salmon, :string, default: nil)
field(:hide_followers_count, :boolean, default: false)
field(:hide_follows_count, :boolean, default: false)
field(:hide_followers, :boolean, default: false)
field(:hide_follows, :boolean, default: false)
field(:hide_favorites, :boolean, default: true)
field(:unread_conversation_count, :integer, default: 0)
field(:pinned_activities, {:array, :string}, default: [])
field(:email_notifications, :map, default: %{"digest" => false})
field(:mascot, :map, default: nil)
field(:emoji, {:array, :map}, default: [])
field(:pleroma_settings_store, :map, default: %{})
field(:fields, {:array, :map}, default: nil)
field(:raw_fields, {:array, :map}, default: [])
field(:discoverable, :boolean, default: false)
field(:skip_thread_containment, :boolean, default: false)
field(:notification_settings, :map,
default: %{
"followers" => true,
"follows" => true,
"non_follows" => true,
"non_followers" => true
}
)
has_many(:notifications, Notification) has_many(:notifications, Notification)
has_many(:registrations, Registration) has_many(:registrations, Registration)
has_many(:deliveries, Delivery) has_many(:deliveries, Delivery)
@ -71,7 +127,7 @@ defmodule Pleroma.User do
timestamps() timestamps()
end end
def auth_active?(%User{info: %User.Info{confirmation_pending: true}}), def auth_active?(%User{confirmation_pending: true}),
do: !Pleroma.Config.get([:instance, :account_activation_required]) do: !Pleroma.Config.get([:instance, :account_activation_required])
def auth_active?(%User{}), do: true def auth_active?(%User{}), do: true
@ -86,8 +142,8 @@ def visible_for?(%User{} = user, for_user) do
def visible_for?(_, _), do: false def visible_for?(_, _), do: false
def superuser?(%User{local: true, info: %User.Info{is_admin: true}}), do: true def superuser?(%User{local: true, is_admin: true}), do: true
def superuser?(%User{local: true, info: %User.Info{is_moderator: true}}), do: true def superuser?(%User{local: true, is_moderator: true}), do: true
def superuser?(_), do: false def superuser?(_), do: false
def avatar_url(user, options \\ []) do def avatar_url(user, options \\ []) do
@ -98,13 +154,13 @@ def avatar_url(user, options \\ []) do
end end
def banner_url(user, options \\ []) do def banner_url(user, options \\ []) do
case user.info.banner do case user.banner do
%{"url" => [%{"href" => href} | _]} -> href %{"url" => [%{"href" => href} | _]} -> href
_ -> !options[:no_default] && "#{Web.base_url()}/images/banner.png" _ -> !options[:no_default] && "#{Web.base_url()}/images/banner.png"
end end
end end
def profile_url(%User{info: %{source_data: %{"url" => url}}}), do: url def profile_url(%User{source_data: %{"url" => url}}), do: url
def profile_url(%User{ap_id: ap_id}), do: ap_id def profile_url(%User{ap_id: ap_id}), do: ap_id
def profile_url(_), do: nil def profile_url(_), do: nil
@ -119,15 +175,15 @@ def ap_following(%User{} = user), do: "#{ap_id(user)}/following"
def user_info(%User{} = user, args \\ %{}) do def user_info(%User{} = user, args \\ %{}) do
following_count = following_count =
Map.get(args, :following_count, user.info.following_count || following_count(user)) Map.get(args, :following_count, user.following_count || following_count(user))
follower_count = Map.get(args, :follower_count, user.info.follower_count) follower_count = Map.get(args, :follower_count, user.follower_count)
%{ %{
note_count: user.info.note_count, note_count: user.note_count,
locked: user.info.locked, locked: user.locked,
confirmation_pending: user.info.confirmation_pending, confirmation_pending: user.confirmation_pending,
default_scope: user.info.default_scope default_scope: user.default_scope
} }
|> Map.put(:following_count, following_count) |> Map.put(:following_count, following_count)
|> Map.put(:follower_count, follower_count) |> Map.put(:follower_count, follower_count)
@ -157,9 +213,7 @@ def set_info_cache(user, args) do
@spec restrict_deactivated(Ecto.Query.t()) :: Ecto.Query.t() @spec restrict_deactivated(Ecto.Query.t()) :: Ecto.Query.t()
def restrict_deactivated(query) do def restrict_deactivated(query) do
from(u in query, from(u in query, where: u.deactivated != ^true)
where: not fragment("? \\? 'deactivated' AND ?->'deactivated' @> 'true'", u.info, u.info)
)
end end
def following_count(%User{following: []}), do: 0 def following_count(%User{following: []}), do: 0
@ -170,6 +224,64 @@ def following_count(%User{} = user) do
|> Repo.aggregate(:count, :id) |> Repo.aggregate(:count, :id)
end end
@info_fields [
:banner,
:background,
:source_data,
:note_count,
:follower_count,
:following_count,
:locked,
:confirmation_pending,
:password_reset_pending,
:confirmation_token,
:default_scope,
:blocks,
:domain_blocks,
:mutes,
:muted_reblogs,
:muted_notifications,
:subscribers,
:deactivated,
:no_rich_text,
:ap_enabled,
:is_moderator,
:is_admin,
:show_role,
:settings,
:magic_key,
:uri,
:topic,
:hub,
:salmon,
:hide_followers_count,
:hide_follows_count,
:hide_followers,
:hide_follows,
:hide_favorites,
:unread_conversation_count,
:pinned_activities,
:email_notifications,
:mascot,
:emoji,
:pleroma_settings_store,
:fields,
:raw_fields,
:discoverable,
:skip_thread_containment,
:notification_settings
]
def info_fields, do: @info_fields
defp truncate_fields_param(params) do
if Map.has_key?(params, :fields) do
Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1))
else
params
end
end
defp truncate_if_exists(params, key, max_length) do defp truncate_if_exists(params, key, max_length) do
if Map.has_key?(params, key) and is_binary(params[key]) do if Map.has_key?(params, key) and is_binary(params[key]) do
{value, _chopped} = String.split_at(params[key], max_length) {value, _chopped} = String.split_at(params[key], max_length)
@ -188,18 +300,20 @@ def remote_user_creation(params) do
|> Map.put(:info, params[:info] || %{}) |> Map.put(:info, params[:info] || %{})
|> truncate_if_exists(:name, name_limit) |> truncate_if_exists(:name, name_limit)
|> truncate_if_exists(:bio, bio_limit) |> truncate_if_exists(:bio, bio_limit)
|> truncate_fields_param()
changeset = changeset =
%User{local: false} %User{local: false}
|> cast(params, [:bio, :name, :ap_id, :nickname, :avatar]) |> cast(params, [:bio, :name, :ap_id, :nickname, :avatar] ++ @info_fields)
|> validate_required([:name, :ap_id]) |> validate_required([:name, :ap_id])
|> unique_constraint(:nickname) |> unique_constraint(:nickname)
|> validate_format(:nickname, @email_regex) |> validate_format(:nickname, @email_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)
|> change_info(&User.Info.remote_user_creation(&1, params[:info])) |> validate_fields(true)
|> change_info(& &1)
case params[:info][:source_data] do case params[:source_data] do
%{"followers" => followers, "following" => following} -> %{"followers" => followers, "following" => following} ->
changeset changeset
|> put_change(:follower_address, followers) |> put_change(:follower_address, followers)
@ -216,11 +330,12 @@ def update_changeset(struct, params \\ %{}) do
name_limit = Pleroma.Config.get([:instance, :user_name_length], 100) name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
struct struct
|> cast(params, [:bio, :name, :avatar, :following]) |> cast(params, [:bio, :name, :avatar, :following] ++ @info_fields)
|> unique_constraint(:nickname) |> unique_constraint(:nickname)
|> 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, min: 1, max: name_limit) |> validate_length(:name, min: 1, max: name_limit)
|> validate_fields(false)
end end
def upgrade_changeset(struct, params \\ %{}, remote? \\ false) do def upgrade_changeset(struct, params \\ %{}, remote? \\ false) do
@ -229,20 +344,26 @@ def upgrade_changeset(struct, params \\ %{}, remote? \\ false) do
params = Map.put(params, :last_refreshed_at, NaiveDateTime.utc_now()) params = Map.put(params, :last_refreshed_at, NaiveDateTime.utc_now())
params = if remote?, do: truncate_fields_param(params), else: params
struct struct
|> cast(params, [ |> cast(
params,
[
:bio, :bio,
:name, :name,
:follower_address, :follower_address,
:following_address, :following_address,
:avatar, :avatar,
:last_refreshed_at :last_refreshed_at
]) ] ++ @info_fields
)
|> unique_constraint(:nickname) |> unique_constraint(:nickname)
|> 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)
|> change_info(&User.Info.user_upgrade(&1, params[:info], remote?)) |> validate_fields(remote?)
|> change_info(& &1)
end end
def password_update_changeset(struct, params) do def password_update_changeset(struct, params) do
@ -250,8 +371,8 @@ def password_update_changeset(struct, params) do
|> cast(params, [:password, :password_confirmation]) |> cast(params, [:password, :password_confirmation])
|> validate_required([:password, :password_confirmation]) |> validate_required([:password, :password_confirmation])
|> validate_confirmation(:password) |> validate_confirmation(:password)
|> put_password_hash |> put_password_hash()
|> put_embed(:info, User.Info.set_password_reset_pending(struct.info, false)) |> put_change(:password_reset_pending, false)
end end
@spec reset_password(User.t(), map) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} @spec reset_password(User.t(), map) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
@ -268,19 +389,19 @@ def reset_password(%User{id: user_id} = user, data) do
end end
end end
def update_password_reset_pending(user, value) do
user
|> change()
|> put_change(:password_reset_pending, value)
|> update_and_set_cache()
end
def force_password_reset_async(user) do def force_password_reset_async(user) do
BackgroundWorker.enqueue("force_password_reset", %{"user_id" => user.id}) BackgroundWorker.enqueue("force_password_reset", %{"user_id" => user.id})
end end
@spec force_password_reset(User.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} @spec force_password_reset(User.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
def force_password_reset(user) do def force_password_reset(user), do: update_password_reset_pending(user, true)
info_cng = User.Info.set_password_reset_pending(user.info, true)
user
|> change()
|> put_embed(:info, info_cng)
|> update_and_set_cache()
end
def register_changeset(struct, params \\ %{}, opts \\ []) do def register_changeset(struct, params \\ %{}, opts \\ []) do
bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000) bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
@ -294,6 +415,7 @@ def register_changeset(struct, params \\ %{}, opts \\ []) do
end end
struct struct
|> confirmation_changeset(need_confirmation: need_confirmation?)
|> cast(params, [:bio, :email, :name, :nickname, :password, :password_confirmation]) |> cast(params, [:bio, :email, :name, :nickname, :password, :password_confirmation])
|> validate_required([:name, :nickname, :password, :password_confirmation]) |> validate_required([:name, :nickname, :password, :password_confirmation])
|> validate_confirmation(:password) |> validate_confirmation(:password)
@ -304,7 +426,7 @@ def register_changeset(struct, params \\ %{}, opts \\ []) do
|> validate_format(:email, @email_regex) |> validate_format(:email, @email_regex)
|> validate_length(:bio, max: bio_limit) |> validate_length(:bio, max: bio_limit)
|> validate_length(:name, min: 1, max: name_limit) |> validate_length(:name, min: 1, max: name_limit)
|> change_info(&User.Info.confirmation_changeset(&1, need_confirmation: need_confirmation?)) |> change_info(& &1)
|> maybe_validate_required_email(opts[:external]) |> maybe_validate_required_email(opts[:external])
|> put_password_hash |> put_password_hash
|> put_ap_id() |> put_ap_id()
@ -355,7 +477,7 @@ def post_register_action(%User{} = user) do
end end
def try_send_confirmation_email(%User{} = user) do def try_send_confirmation_email(%User{} = user) do
if user.info.confirmation_pending && if user.confirmation_pending &&
Pleroma.Config.get([:instance, :account_activation_required]) do Pleroma.Config.get([:instance, :account_activation_required]) do
user user
|> Pleroma.Emails.UserEmail.account_confirmation_email() |> Pleroma.Emails.UserEmail.account_confirmation_email()
@ -378,7 +500,7 @@ def needs_update?(%User{local: false} = user) do
def needs_update?(_), do: true def needs_update?(_), do: true
@spec maybe_direct_follow(User.t(), User.t()) :: {:ok, User.t()} | {:error, String.t()} @spec maybe_direct_follow(User.t(), User.t()) :: {:ok, User.t()} | {:error, String.t()}
def maybe_direct_follow(%User{} = follower, %User{local: true, info: %{locked: true}}) do def maybe_direct_follow(%User{} = follower, %User{local: true, locked: true}) do
{:ok, follower} {:ok, follower}
end end
@ -425,13 +547,13 @@ def follow_all(follower, followeds) do
set_cache(follower) set_cache(follower)
end end
def follow(%User{} = follower, %User{info: info} = followed) do def follow(%User{} = follower, %User{} = followed) do
deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked]) deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked])
ap_followers = followed.follower_address ap_followers = followed.follower_address
cond do cond do
info.deactivated -> followed.deactivated ->
{:error, "Could not follow user: You are deactivated."} {:error, "Could not follow user: #{followed.nickname} is deactivated."}
deny_follow_blocked and blocks?(followed, follower) -> deny_follow_blocked and blocks?(followed, follower) ->
{:error, "Could not follow user: #{followed.nickname} blocked you."} {:error, "Could not follow user: #{followed.nickname} blocked you."}
@ -489,7 +611,7 @@ def following?(%User{} = follower, %User{} = followed) do
end end
def locked?(%User{} = user) do def locked?(%User{} = user) do
user.info.locked || false user.locked || false
end end
def get_by_id(id) do def get_by_id(id) do
@ -532,6 +654,12 @@ def set_cache(%User{} = user) do
{:ok, user} {:ok, user}
end end
def update_and_set_cache(struct, params) do
struct
|> update_changeset(params)
|> update_and_set_cache()
end
def update_and_set_cache(changeset) do def update_and_set_cache(changeset) do
with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do
set_cache(user) set_cache(user)
@ -721,16 +849,7 @@ def get_follow_requests(%User{} = user) do
def increase_note_count(%User{} = user) do def increase_note_count(%User{} = user) do
User User
|> where(id: ^user.id) |> where(id: ^user.id)
|> update([u], |> update([u], inc: [note_count: 1])
set: [
info:
fragment(
"jsonb_set(?, '{note_count}', ((?->>'note_count')::int + 1)::varchar::jsonb, true)",
u.info,
u.info
)
]
)
|> select([u], u) |> select([u], u)
|> Repo.update_all([]) |> Repo.update_all([])
|> case do |> case do
@ -744,12 +863,7 @@ def decrease_note_count(%User{} = user) do
|> where(id: ^user.id) |> where(id: ^user.id)
|> update([u], |> update([u],
set: [ set: [
info: note_count: fragment("greatest(0, note_count - 1)")
fragment(
"jsonb_set(?, '{note_count}', (greatest(0, (?->>'note_count')::int - 1))::varchar::jsonb, true)",
u.info,
u.info
)
] ]
) )
|> select([u], u) |> select([u], u)
@ -760,8 +874,9 @@ def decrease_note_count(%User{} = user) do
end end
end end
def update_note_count(%User{} = user) do def update_note_count(%User{} = user, note_count \\ nil) do
note_count = note_count =
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),
@ -769,20 +884,7 @@ def update_note_count(%User{} = user) do
) )
|> Repo.one() |> Repo.one()
update_info(user, &User.Info.set_note_count(&1, note_count)) update_and_set_cache(user, %{note_count: note_count})
end
def update_mascot(user, url) do
info_changeset =
User.Info.mascot_update(
user.info,
url
)
user
|> change()
|> put_embed(:info, info_changeset)
|> update_and_set_cache()
end end
@spec maybe_fetch_follow_information(User.t()) :: User.t() @spec maybe_fetch_follow_information(User.t()) :: User.t()
@ -799,10 +901,24 @@ def maybe_fetch_follow_information(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
update_info(user, &User.Info.follow_information_update(&1, info)) user
|> follow_information_changeset(info)
|> update_and_set_cache()
end end
end end
defp follow_information_changeset(user, params) do
user
|> cast(params, [
:hide_followers,
:hide_follows,
:follower_count,
:following_count,
:hide_followers_count,
:hide_follows_count
])
end
def update_follower_count(%User{} = user) do def update_follower_count(%User{} = user) do
if user.local or !Pleroma.Config.get([:instance, :external_user_synchronization]) do if user.local or !Pleroma.Config.get([:instance, :external_user_synchronization]) do
follower_count_query = follower_count_query =
@ -813,14 +929,7 @@ def update_follower_count(%User{} = user) do
|> where(id: ^user.id) |> where(id: ^user.id)
|> join(:inner, [u], s in subquery(follower_count_query)) |> join(:inner, [u], s in subquery(follower_count_query))
|> update([u, s], |> update([u, s],
set: [ set: [follower_count: s.count]
info:
fragment(
"jsonb_set(?, '{follower_count}', ?::varchar::jsonb, true)",
u.info,
s.count
)
]
) )
|> select([u], u) |> select([u], u)
|> Repo.update_all([]) |> Repo.update_all([])
@ -850,14 +959,7 @@ def set_unread_conversation_count(%User{local: true} = user) do
User User
|> join(:inner, [u], p in subquery(unread_query)) |> join(:inner, [u], p in subquery(unread_query))
|> update([u, p], |> update([u, p],
set: [ set: [unread_conversation_count: p.count]
info:
fragment(
"jsonb_set(?, '{unread_conversation_count}', ?::varchar::jsonb, true)",
u.info,
p.count
)
]
) )
|> where([u], u.id == ^user.id) |> where([u], u.id == ^user.id)
|> select([u], u) |> select([u], u)
@ -878,14 +980,7 @@ def increment_unread_conversation_count(conversation, %User{local: true} = user)
User User
|> join(:inner, [u], p in subquery(unread_query)) |> join(:inner, [u], p in subquery(unread_query))
|> update([u, p], |> update([u, p],
set: [ inc: [unread_conversation_count: 1]
info:
fragment(
"jsonb_set(?, '{unread_conversation_count}', (coalesce((?->>'unread_conversation_count')::int, 0) + 1)::varchar::jsonb, true)",
u.info,
u.info
)
]
) )
|> where([u], u.id == ^user.id) |> where([u], u.id == ^user.id)
|> where([u, p], p.count == 0) |> where([u, p], p.count == 0)
@ -942,14 +1037,14 @@ def subscribe(subscriber, %{ap_id: ap_id}) do
if blocks?(subscribed, subscriber) and deny_follow_blocked do if blocks?(subscribed, subscriber) and deny_follow_blocked do
{:error, "Could not subscribe: #{subscribed.nickname} is blocking you"} {:error, "Could not subscribe: #{subscribed.nickname} is blocking you"}
else else
update_info(subscribed, &User.Info.add_to_subscribers(&1, subscriber.ap_id)) User.add_to_subscribers(subscribed, subscriber.ap_id)
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
update_info(user, &User.Info.remove_from_subscribers(&1, unsubscriber.ap_id)) User.remove_from_subscribers(user, unsubscriber.ap_id)
end end
end end
@ -1025,7 +1120,7 @@ def blocks_domain?(_, _), do: false
def subscribed_to?(user, %{ap_id: ap_id}) do def subscribed_to?(user, %{ap_id: ap_id}) do
with %User{} = target <- get_cached_by_ap_id(ap_id) do with %User{} = target <- get_cached_by_ap_id(ap_id) do
Enum.member?(target.info.subscribers, user.ap_id) Enum.member?(target.subscribers, user.ap_id)
end end
end end
@ -1043,7 +1138,7 @@ def blocked_users(user) do
@spec subscribers(User.t()) :: [User.t()] @spec subscribers(User.t()) :: [User.t()]
def subscribers(user) do def subscribers(user) do
User.Query.build(%{ap_id: user.info.subscribers, deactivated: false}) User.Query.build(%{ap_id: user.subscribers, deactivated: false})
|> Repo.all() |> Repo.all()
end end
@ -1060,7 +1155,7 @@ def deactivate_async(user, status \\ true) do
end end
def deactivate(%User{} = user, status \\ true) do def deactivate(%User{} = user, status \\ true) do
with {:ok, user} <- update_info(user, &User.Info.set_activation_status(&1, status)) do with {:ok, user} <- set_activation_status(user, status) 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)
@ -1068,8 +1163,23 @@ def deactivate(%User{} = user, status \\ true) do
end end
end end
def update_notification_settings(%User{} = user, settings \\ %{}) do def update_notification_settings(%User{} = user, settings) do
update_info(user, &User.Info.update_notification_settings(&1, settings)) settings =
settings
|> Enum.map(fn {k, v} -> {k, v in [true, "true", "True", "1"]} end)
|> Map.new()
notification_settings =
user.notification_settings
|> Map.merge(settings)
|> Map.take(["followers", "follows", "non_follows", "non_followers"])
params = %{notification_settings: notification_settings}
user
|> cast(params, [:notification_settings])
|> validate_required([:notification_settings])
|> update_and_set_cache()
end end
def delete(%User{} = user) do def delete(%User{} = user) do
@ -1107,7 +1217,7 @@ def perform(:fetch_initial_posts, %User{} = user) do
pages = Pleroma.Config.get!([:fetch_initial_posts, :pages]) pages = Pleroma.Config.get!([:fetch_initial_posts, :pages])
# Insert all the posts in reverse order, so they're in the right order on the timeline # Insert all the posts in reverse order, so they're in the right order on the timeline
user.info.source_data["outbox"] user.source_data["outbox"]
|> Utils.fetch_ordered_collection(pages) |> Utils.fetch_ordered_collection(pages)
|> Enum.reverse() |> Enum.reverse()
|> Enum.each(&Pleroma.Web.Federator.incoming_ap_doc/1) |> Enum.each(&Pleroma.Web.Federator.incoming_ap_doc/1)
@ -1228,7 +1338,7 @@ defp delete_activity(%{data: %{"type" => "Announce"}} = activity) do
defp delete_activity(_activity), do: "Doing nothing" defp delete_activity(_activity), do: "Doing nothing"
def html_filter_policy(%User{info: %{no_rich_text: true}}) do def html_filter_policy(%User{no_rich_text: true}) do
Pleroma.HTML.Scrubber.TwitterText Pleroma.HTML.Scrubber.TwitterText
end end
@ -1288,9 +1398,7 @@ def get_or_create_service_actor_by_ap_id(uri, nickname \\ nil) do
end end
# AP style # AP style
def public_key_from_info(%{ def public_key(%{source_data: %{"publicKey" => %{"publicKeyPem" => public_key_pem}}}) do
source_data: %{"publicKey" => %{"publicKeyPem" => public_key_pem}}
}) do
key = key =
public_key_pem public_key_pem
|> :public_key.pem_decode() |> :public_key.pem_decode()
@ -1301,15 +1409,15 @@ def public_key_from_info(%{
end end
# OStatus Magic Key # OStatus Magic Key
def public_key_from_info(%{magic_key: magic_key}) when not is_nil(magic_key) do def public_key(%{magic_key: magic_key}) when not is_nil(magic_key) do
{:ok, Pleroma.Web.Salmon.decode_key(magic_key)} {:ok, Pleroma.Web.Salmon.decode_key(magic_key)}
end end
def public_key_from_info(_), do: {:error, "not found key"} def public_key(_), do: {:error, "not found key"}
def get_public_key_for_ap_id(ap_id) do def get_public_key_for_ap_id(ap_id) do
with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id), with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id),
{:ok, public_key} <- public_key_from_info(user.info) do {:ok, public_key} <- public_key(user) do
{:ok, public_key} {:ok, public_key}
else else
_ -> :error _ -> :error
@ -1328,7 +1436,7 @@ def insert_or_update_user(data) do
end end
def ap_enabled?(%User{local: true}), do: true def ap_enabled?(%User{local: true}), do: true
def ap_enabled?(%User{info: info}), do: info.ap_enabled def ap_enabled?(%User{ap_enabled: ap_enabled}), do: ap_enabled
def ap_enabled?(_), do: false def ap_enabled?(_), do: false
@doc "Gets or fetch a user by uri or nickname." @doc "Gets or fetch a user by uri or nickname."
@ -1486,7 +1594,7 @@ def list_inactive_users_query(inactivity_threshold \\ 7) do
left_join: a in Pleroma.Activity, left_join: a in Pleroma.Activity,
on: u.ap_id == a.actor, on: u.ap_id == a.actor,
where: not is_nil(u.nickname), where: not is_nil(u.nickname),
where: fragment("not (?->'deactivated' @> 'true')", u.info), where: u.deactivated != ^true,
where: u.id not in ^has_read_notifications, where: u.id not in ^has_read_notifications,
group_by: u.id, group_by: u.id,
having: having:
@ -1500,16 +1608,16 @@ def list_inactive_users_query(inactivity_threshold \\ 7) do
## Examples ## Examples
iex> Pleroma.User.switch_email_notifications(Pleroma.User{info: %{email_notifications: %{"digest" => false}}}, "digest", true) iex> Pleroma.User.switch_email_notifications(Pleroma.User{email_notifications: %{"digest" => false}}, "digest", true)
Pleroma.User{info: %{email_notifications: %{"digest" => true}}} Pleroma.User{email_notifications: %{"digest" => true}}
iex> Pleroma.User.switch_email_notifications(Pleroma.User{info: %{email_notifications: %{"digest" => true}}}, "digest", false) iex> Pleroma.User.switch_email_notifications(Pleroma.User{email_notifications: %{"digest" => true}}, "digest", false)
Pleroma.User{info: %{email_notifications: %{"digest" => false}}} Pleroma.User{email_notifications: %{"digest" => false}}
""" """
@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
update_info(user, &User.Info.update_email_notifications(&1, %{type => status})) User.update_email_notifications(user, %{type => status})
end end
@doc """ @doc """
@ -1529,17 +1637,16 @@ def touch_last_digest_emailed_at(user) do
@spec toggle_confirmation(User.t()) :: {:ok, User.t()} | {:error, Changeset.t()} @spec toggle_confirmation(User.t()) :: {:ok, User.t()} | {:error, Changeset.t()}
def toggle_confirmation(%User{} = user) do def toggle_confirmation(%User{} = user) do
need_confirmation? = !user.info.confirmation_pending
user user
|> update_info(&User.Info.confirmation_changeset(&1, need_confirmation: need_confirmation?)) |> confirmation_changeset(need_confirmation: !user.confirmation_pending)
|> update_and_set_cache()
end end
def get_mascot(%{info: %{mascot: %{} = mascot}}) when not is_nil(mascot) do def get_mascot(%{mascot: %{} = mascot}) when not is_nil(mascot) do
mascot mascot
end end
def get_mascot(%{info: %{mascot: mascot}}) when is_nil(mascot) do def get_mascot(%{mascot: mascot}) when is_nil(mascot) do
# use instance-default # use instance-default
config = Pleroma.Config.get([:assets, :mascots]) config = Pleroma.Config.get([:assets, :mascots])
default_mascot = Pleroma.Config.get([:assets, :default_mascot]) default_mascot = Pleroma.Config.get([:assets, :default_mascot])
@ -1609,6 +1716,31 @@ def change_email(user, email) do
|> update_and_set_cache() |> update_and_set_cache()
end end
# Internal function; public one is `deactivate/2`
defp set_activation_status(user, deactivated) do
user
|> cast(%{deactivated: deactivated}, [:deactivated])
|> update_and_set_cache()
end
def update_banner(user, banner) do
user
|> cast(%{banner: banner}, [:banner])
|> update_and_set_cache()
end
def update_background(user, background) do
user
|> cast(%{background: background}, [:background])
|> update_and_set_cache()
end
def update_source_data(user, source_data) do
user
|> cast(%{source_data: source_data}, [:source_data])
|> update_and_set_cache()
end
@doc """ @doc """
Changes `user.info` and returns the user changeset. Changes `user.info` and returns the user changeset.
@ -1630,4 +1762,160 @@ def update_info(user, fun) do
|> change_info(fun) |> change_info(fun)
|> update_and_set_cache() |> update_and_set_cache()
end end
def roles(%{is_moderator: is_moderator, is_admin: is_admin}) do
%{
admin: is_admin,
moderator: is_moderator
}
end
# ``fields`` is an array of mastodon profile field, containing ``{"name": "…", "value": "…"}``.
# For example: [{"name": "Pronoun", "value": "she/her"}, …]
def fields(%{fields: nil, source_data: %{"attachment" => attachment}}) do
limit = Pleroma.Config.get([:instance, :max_remote_account_fields], 0)
attachment
|> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
|> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
|> Enum.take(limit)
end
def fields(%{fields: nil}), do: []
def fields(%{fields: fields}), do: fields
def validate_fields(changeset, remote? \\ false) do
limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields
limit = Pleroma.Config.get([:instance, limit_name], 0)
changeset
|> validate_length(:fields, max: limit)
|> validate_change(:fields, fn :fields, fields ->
if Enum.all?(fields, &valid_field?/1) do
[]
else
[fields: "invalid"]
end
end)
end
defp valid_field?(%{"name" => name, "value" => value}) do
name_limit = Pleroma.Config.get([:instance, :account_field_name_length], 255)
value_limit = Pleroma.Config.get([:instance, :account_field_value_length], 255)
is_binary(name) && is_binary(value) && String.length(name) <= name_limit &&
String.length(value) <= value_limit
end
defp valid_field?(_), do: false
defp truncate_field(%{"name" => name, "value" => value}) do
{name, _chopped} =
String.split_at(name, Pleroma.Config.get([:instance, :account_field_name_length], 255))
{value, _chopped} =
String.split_at(value, Pleroma.Config.get([:instance, :account_field_value_length], 255))
%{"name" => name, "value" => value}
end
def admin_api_update(user, params) do
user
|> cast(params, [
:is_moderator,
:is_admin,
:show_role
])
|> update_and_set_cache()
end
def mascot_update(user, url) do
user
|> cast(%{mascot: url}, [:mascot])
|> validate_required([:mascot])
|> update_and_set_cache()
end
def mastodon_settings_update(user, settings) do
user
|> cast(%{settings: settings}, [:settings])
|> validate_required([:settings])
|> update_and_set_cache()
end
@spec confirmation_changeset(User.t(), keyword()) :: Changeset.t()
def confirmation_changeset(user, need_confirmation: need_confirmation?) do
params =
if need_confirmation? do
%{
confirmation_pending: true,
confirmation_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64()
}
else
%{
confirmation_pending: false,
confirmation_token: nil
}
end
cast(user, params, [:confirmation_pending, :confirmation_token])
end
def add_pinnned_activity(user, %Pleroma.Activity{id: id}) do
if id not in user.pinned_activities do
max_pinned_statuses = Pleroma.Config.get([:instance, :max_pinned_statuses], 0)
params = %{pinned_activities: user.pinned_activities ++ [id]}
user
|> cast(params, [:pinned_activities])
|> validate_length(:pinned_activities,
max: max_pinned_statuses,
message: "You have already pinned the maximum number of statuses"
)
else
change(user)
end
|> update_and_set_cache()
end
def remove_pinnned_activity(user, %Pleroma.Activity{id: id}) do
params = %{pinned_activities: List.delete(user.pinned_activities, id)}
user
|> cast(params, [:pinned_activities])
|> update_and_set_cache()
end
def update_email_notifications(user, settings) do
email_notifications =
user.email_notifications
|> Map.merge(settings)
|> Map.take(["digest"])
params = %{email_notifications: email_notifications}
fields = [:email_notifications]
user
|> cast(params, fields)
|> validate_required(fields)
|> update_and_set_cache()
end
defp set_subscribers(user, subscribers) do
params = %{subscribers: subscribers}
user
|> cast(params, [:subscribers])
|> validate_required([:subscribers])
|> update_and_set_cache()
end
def add_to_subscribers(user, subscribed) do
set_subscribers(user, Enum.uniq([subscribed | user.subscribers]))
end
def remove_from_subscribers(user, subscribed) do
set_subscribers(user, List.delete(user.subscribers, subscribed))
end
end end

View file

@ -11,62 +11,11 @@ defmodule Pleroma.User.Info do
@type t :: %__MODULE__{} @type t :: %__MODULE__{}
embedded_schema do embedded_schema do
field(:banner, :map, default: %{})
field(:background, :map, default: %{})
field(:source_data, :map, default: %{})
field(:note_count, :integer, default: 0)
field(:follower_count, :integer, default: 0)
# Should be filled in only for remote users
field(:following_count, :integer, default: nil)
field(:locked, :boolean, default: false)
field(:confirmation_pending, :boolean, default: false)
field(:password_reset_pending, :boolean, default: false)
field(:confirmation_token, :string, default: nil)
field(:default_scope, :string, default: "public")
field(:blocks, {:array, :string}, default: []) field(:blocks, {:array, :string}, default: [])
field(:domain_blocks, {:array, :string}, default: []) field(:domain_blocks, {:array, :string}, default: [])
field(:mutes, {:array, :string}, default: []) field(:mutes, {:array, :string}, default: [])
field(:muted_reblogs, {:array, :string}, default: []) field(:muted_reblogs, {:array, :string}, default: [])
field(:muted_notifications, {:array, :string}, default: []) field(:muted_notifications, {:array, :string}, default: [])
field(:subscribers, {:array, :string}, default: [])
field(:deactivated, :boolean, default: false)
field(:no_rich_text, :boolean, default: false)
field(:ap_enabled, :boolean, default: false)
field(:is_moderator, :boolean, default: false)
field(:is_admin, :boolean, default: false)
field(:show_role, :boolean, default: true)
field(:keys, :string, default: nil)
field(:settings, :map, default: nil)
field(:magic_key, :string, default: nil)
field(:uri, :string, default: nil)
field(:topic, :string, default: nil)
field(:hub, :string, default: nil)
field(:salmon, :string, default: nil)
field(:hide_followers_count, :boolean, default: false)
field(:hide_follows_count, :boolean, default: false)
field(:hide_followers, :boolean, default: false)
field(:hide_follows, :boolean, default: false)
field(:hide_favorites, :boolean, default: true)
field(:unread_conversation_count, :integer, default: 0)
field(:pinned_activities, {:array, :string}, default: [])
field(:email_notifications, :map, default: %{"digest" => false})
field(:mascot, :map, default: nil)
field(:emoji, {:array, :map}, default: [])
field(:pleroma_settings_store, :map, default: %{})
field(:fields, {:array, :map}, default: nil)
field(:raw_fields, {:array, :map}, default: [])
field(:discoverable, :boolean, default: false)
field(:notification_settings, :map,
default: %{
"followers" => true,
"follows" => true,
"non_follows" => true,
"non_followers" => true
}
)
field(:skip_thread_containment, :boolean, default: false)
# Found in the wild # Found in the wild
# ap_id -> Where is this used? # ap_id -> Where is this used?
@ -77,84 +26,6 @@ defmodule Pleroma.User.Info do
# subject _> Where is this used? # subject _> Where is this used?
end end
def set_activation_status(info, deactivated) do
params = %{deactivated: deactivated}
info
|> cast(params, [:deactivated])
|> validate_required([:deactivated])
end
def set_password_reset_pending(info, pending) do
params = %{password_reset_pending: pending}
info
|> cast(params, [:password_reset_pending])
|> validate_required([:password_reset_pending])
end
def update_notification_settings(info, settings) do
settings =
settings
|> Enum.map(fn {k, v} -> {k, v in [true, "true", "True", "1"]} end)
|> Map.new()
notification_settings =
info.notification_settings
|> Map.merge(settings)
|> Map.take(["followers", "follows", "non_follows", "non_followers"])
params = %{notification_settings: notification_settings}
info
|> cast(params, [:notification_settings])
|> validate_required([:notification_settings])
end
@doc """
Update email notifications in the given User.Info struct.
Examples:
iex> update_email_notifications(%Pleroma.User.Info{email_notifications: %{"digest" => false}}, %{"digest" => true})
%Pleroma.User.Info{email_notifications: %{"digest" => true}}
"""
@spec update_email_notifications(t(), map()) :: Ecto.Changeset.t()
def update_email_notifications(info, settings) do
email_notifications =
info.email_notifications
|> Map.merge(settings)
|> Map.take(["digest"])
params = %{email_notifications: email_notifications}
fields = [:email_notifications]
info
|> cast(params, fields)
|> validate_required(fields)
end
def add_to_note_count(info, number) do
set_note_count(info, info.note_count + number)
end
def set_note_count(info, number) do
params = %{note_count: Enum.max([0, number])}
info
|> cast(params, [:note_count])
|> validate_required([:note_count])
end
def set_follower_count(info, number) do
params = %{follower_count: Enum.max([0, number])}
info
|> cast(params, [:follower_count])
|> validate_required([:follower_count])
end
def set_mutes(info, mutes) do def set_mutes(info, mutes) do
params = %{mutes: mutes} params = %{mutes: mutes}
@ -181,14 +52,6 @@ def set_blocks(info, blocks) do
|> validate_required([:blocks]) |> validate_required([:blocks])
end end
def set_subscribers(info, subscribers) do
params = %{subscribers: subscribers}
info
|> cast(params, [:subscribers])
|> validate_required([:subscribers])
end
@spec add_to_mutes(Info.t(), String.t(), boolean()) :: Changeset.t() @spec add_to_mutes(Info.t(), String.t(), boolean()) :: Changeset.t()
def add_to_mutes(info, muted, notifications?) do def add_to_mutes(info, muted, notifications?) do
info info
@ -214,14 +77,6 @@ def remove_from_block(info, blocked) do
set_blocks(info, List.delete(info.blocks, blocked)) set_blocks(info, List.delete(info.blocks, blocked))
end end
def add_to_subscribers(info, subscribed) do
set_subscribers(info, Enum.uniq([subscribed | info.subscribers]))
end
def remove_from_subscribers(info, subscribed) do
set_subscribers(info, List.delete(info.subscribers, subscribed))
end
def set_domain_blocks(info, domain_blocks) do def set_domain_blocks(info, domain_blocks) do
params = %{domain_blocks: domain_blocks} params = %{domain_blocks: domain_blocks}
@ -238,205 +93,6 @@ def remove_from_domain_block(info, domain_blocked) do
set_domain_blocks(info, List.delete(info.domain_blocks, domain_blocked)) set_domain_blocks(info, List.delete(info.domain_blocks, domain_blocked))
end end
def set_keys(info, keys) do
params = %{keys: keys}
info
|> cast(params, [:keys])
|> validate_required([:keys])
end
def remote_user_creation(info, params) do
params =
if Map.has_key?(params, :fields) do
Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1))
else
params
end
info
|> cast(params, [
:ap_enabled,
:source_data,
:banner,
:locked,
:magic_key,
:uri,
:hub,
:topic,
:salmon,
:hide_followers,
:hide_follows,
:hide_followers_count,
:hide_follows_count,
:follower_count,
:fields,
:following_count,
:discoverable
])
|> validate_fields(true)
end
def user_upgrade(info, params, remote? \\ false) do
info
|> cast(params, [
:ap_enabled,
:source_data,
:banner,
:locked,
:magic_key,
:follower_count,
:following_count,
:hide_follows,
:fields,
:hide_followers,
:discoverable,
:hide_followers_count,
:hide_follows_count
])
|> validate_fields(remote?)
end
def profile_update(info, params) do
info
|> cast(params, [
:locked,
:no_rich_text,
:default_scope,
:banner,
:hide_follows,
:hide_followers,
:hide_followers_count,
:hide_follows_count,
:hide_favorites,
:background,
:show_role,
:skip_thread_containment,
:fields,
:raw_fields,
:pleroma_settings_store,
:discoverable
])
|> validate_fields()
end
def validate_fields(changeset, remote? \\ false) do
limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields
limit = Pleroma.Config.get([:instance, limit_name], 0)
changeset
|> validate_length(:fields, max: limit)
|> validate_change(:fields, fn :fields, fields ->
if Enum.all?(fields, &valid_field?/1) do
[]
else
[fields: "invalid"]
end
end)
end
defp valid_field?(%{"name" => name, "value" => value}) do
name_limit = Pleroma.Config.get([:instance, :account_field_name_length], 255)
value_limit = Pleroma.Config.get([:instance, :account_field_value_length], 255)
is_binary(name) && is_binary(value) && String.length(name) <= name_limit &&
String.length(value) <= value_limit
end
defp valid_field?(_), do: false
defp truncate_field(%{"name" => name, "value" => value}) do
{name, _chopped} =
String.split_at(name, Pleroma.Config.get([:instance, :account_field_name_length], 255))
{value, _chopped} =
String.split_at(value, Pleroma.Config.get([:instance, :account_field_value_length], 255))
%{"name" => name, "value" => value}
end
@spec confirmation_changeset(Info.t(), keyword()) :: Changeset.t()
def confirmation_changeset(info, opts) do
need_confirmation? = Keyword.get(opts, :need_confirmation)
params =
if need_confirmation? do
%{
confirmation_pending: true,
confirmation_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64()
}
else
%{
confirmation_pending: false,
confirmation_token: nil
}
end
cast(info, params, [:confirmation_pending, :confirmation_token])
end
def mastodon_settings_update(info, settings) do
params = %{settings: settings}
info
|> cast(params, [:settings])
|> validate_required([:settings])
end
def mascot_update(info, url) do
params = %{mascot: url}
info
|> cast(params, [:mascot])
|> validate_required([:mascot])
end
def set_source_data(info, source_data) do
params = %{source_data: source_data}
info
|> cast(params, [:source_data])
|> validate_required([:source_data])
end
def admin_api_update(info, params) do
info
|> cast(params, [
:is_moderator,
:is_admin,
:show_role
])
end
def add_pinnned_activity(info, %Pleroma.Activity{id: id}) do
if id not in info.pinned_activities do
max_pinned_statuses = Pleroma.Config.get([:instance, :max_pinned_statuses], 0)
params = %{pinned_activities: info.pinned_activities ++ [id]}
info
|> cast(params, [:pinned_activities])
|> validate_length(:pinned_activities,
max: max_pinned_statuses,
message: "You have already pinned the maximum number of statuses"
)
else
change(info)
end
end
def remove_pinnned_activity(info, %Pleroma.Activity{id: id}) do
params = %{pinned_activities: List.delete(info.pinned_activities, id)}
cast(info, params, [:pinned_activities])
end
def roles(%Info{is_moderator: is_moderator, is_admin: is_admin}) do
%{
admin: is_admin,
moderator: is_moderator
}
end
def add_reblog_mute(info, ap_id) do def add_reblog_mute(info, ap_id) do
params = %{muted_reblogs: info.muted_reblogs ++ [ap_id]} params = %{muted_reblogs: info.muted_reblogs ++ [ap_id]}
@ -448,31 +104,4 @@ def remove_reblog_mute(info, ap_id) do
cast(info, params, [:muted_reblogs]) cast(info, params, [:muted_reblogs])
end end
# ``fields`` is an array of mastodon profile field, containing ``{"name": "…", "value": "…"}``.
# For example: [{"name": "Pronoun", "value": "she/her"}, …]
def fields(%{fields: nil, source_data: %{"attachment" => attachment}}) do
limit = Pleroma.Config.get([:instance, :max_remote_account_fields], 0)
attachment
|> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
|> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
|> Enum.take(limit)
end
def fields(%{fields: nil}), do: []
def fields(%{fields: fields}), do: fields
def follow_information_update(info, params) do
info
|> cast(params, [
:hide_followers,
:hide_follows,
:follower_count,
:following_count,
:hide_followers_count,
:hide_follows_count
])
end
end end

View file

@ -56,7 +56,6 @@ defmodule Pleroma.User.Query do
@ilike_criteria [:nickname, :name, :query] @ilike_criteria [:nickname, :name, :query]
@equal_criteria [:email] @equal_criteria [:email]
@role_criteria [:is_admin, :is_moderator]
@contains_criteria [:ap_id, :nickname] @contains_criteria [:ap_id, :nickname]
@spec build(criteria()) :: Query.t() @spec build(criteria()) :: Query.t()
@ -100,15 +99,19 @@ defp compose_query({:tags, tags}, query) when is_list(tags) and length(tags) > 0
Enum.reduce(tags, query, &prepare_tag_criteria/2) Enum.reduce(tags, query, &prepare_tag_criteria/2)
end end
defp compose_query({key, _}, query) when key in @role_criteria do defp compose_query({:is_admin, _}, query) do
where(query, [u], fragment("(?->? @> 'true')", u.info, ^to_string(key))) where(query, [u], u.is_admin)
end
defp compose_query({:is_moderator, _}, query) do
where(query, [u], u.is_moderator)
end end
defp compose_query({:super_users, _}, query) do defp compose_query({:super_users, _}, query) do
where( where(
query, query,
[u], [u],
fragment("?->'is_admin' @> 'true' OR ?->'is_moderator' @> 'true'", u.info, u.info) u.is_admin or u.is_moderator
) )
end end
@ -117,7 +120,13 @@ defp compose_query({:local, _}, query), do: location_query(query, true)
defp compose_query({:external, _}, query), do: location_query(query, false) defp compose_query({:external, _}, query), do: location_query(query, false)
defp compose_query({:active, _}, query) do defp compose_query({:active, _}, query) do
where(query, [u], fragment("not (?->'deactivated' @> 'true')", u.info)) User.restrict_deactivated(query)
|> where([u], not is_nil(u.nickname))
end
defp compose_query({:legacy_active, _}, query) do
query
|> where([u], fragment("not (?->'deactivated' @> 'true')", u.info))
|> where([u], not is_nil(u.nickname)) |> where([u], not is_nil(u.nickname))
end end
@ -126,7 +135,7 @@ defp compose_query({:deactivated, false}, query) do
end end
defp compose_query({:deactivated, true}, query) do defp compose_query({:deactivated, true}, query) do
where(query, [u], fragment("?->'deactivated' @> 'true'", u.info)) where(query, [u], u.deactivated == ^true)
|> where([u], not is_nil(u.nickname)) |> where([u], not is_nil(u.nickname))
end end

View file

@ -68,7 +68,7 @@ defp get_recipients(data) do
defp check_actor_is_active(actor) do defp check_actor_is_active(actor) do
if not is_nil(actor) do if not is_nil(actor) do
with user <- User.get_cached_by_ap_id(actor), with user <- User.get_cached_by_ap_id(actor),
false <- user.info.deactivated do false <- user.deactivated do
true true
else else
_e -> false _e -> false
@ -601,7 +601,7 @@ defp restrict_thread_visibility(query, _, %{skip_thread_containment: true} = _),
defp restrict_thread_visibility( defp restrict_thread_visibility(
query, query,
%{"user" => %User{info: %{skip_thread_containment: true}}}, %{"user" => %User{skip_thread_containment: true}},
_ _
), ),
do: query do: query
@ -639,7 +639,7 @@ def fetch_user_activities(user, reading_user, params \\ %{}) do
|> Map.put("user", reading_user) |> Map.put("user", reading_user)
|> Map.put("actor_id", user.ap_id) |> Map.put("actor_id", user.ap_id)
|> Map.put("whole_db", true) |> Map.put("whole_db", true)
|> Map.put("pinned_activity_ids", user.info.pinned_activities) |> Map.put("pinned_activity_ids", user.pinned_activities)
recipients = recipients =
user_activities_recipients(%{ user_activities_recipients(%{
@ -1049,14 +1049,12 @@ defp object_to_user_data(data) do
user_data = %{ user_data = %{
ap_id: data["id"], ap_id: data["id"],
info: %{
ap_enabled: true,
source_data: data,
banner: banner, banner: banner,
discoverable: discoverable,
source_data: data,
fields: fields, fields: fields,
locked: locked, locked: locked,
discoverable: discoverable ap_enabled: true,
},
avatar: avatar, avatar: avatar,
name: data["name"], name: data["name"],
follower_address: data["followers"], follower_address: data["followers"],

View file

@ -137,7 +137,7 @@ def following(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "p
with %User{} = user <- User.get_cached_by_nickname(nickname), with %User{} = user <- User.get_cached_by_nickname(nickname),
{user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user), {user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user),
{:show_follows, true} <- {:show_follows, true} <-
{:show_follows, (for_user && for_user == user) || !user.info.hide_follows} do {:show_follows, (for_user && for_user == user) || !user.hide_follows} do
{page, _} = Integer.parse(page) {page, _} = Integer.parse(page)
conn conn
@ -174,7 +174,7 @@ def followers(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "p
with %User{} = user <- User.get_cached_by_nickname(nickname), with %User{} = user <- User.get_cached_by_nickname(nickname),
{user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user), {user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user),
{:show_followers, true} <- {:show_followers, true} <-
{:show_followers, (for_user && for_user == user) || !user.info.hide_followers} do {:show_followers, (for_user && for_user == user) || !user.hide_followers} do
{page, _} = Integer.parse(page) {page, _} = Integer.parse(page)
conn conn
@ -387,7 +387,7 @@ def handle_user_activity(user, %{"type" => "Create"} = params) do
def handle_user_activity(user, %{"type" => "Delete"} = params) do def handle_user_activity(user, %{"type" => "Delete"} = params) do
with %Object{} = object <- Object.normalize(params["object"]), with %Object{} = object <- Object.normalize(params["object"]),
true <- user.info.is_moderator || user.ap_id == object.data["actor"], true <- user.is_moderator || user.ap_id == object.data["actor"],
{:ok, delete} <- ActivityPub.delete(object) do {:ok, delete} <- ActivityPub.delete(object) do
{:ok, delete} {:ok, delete}
else else

View file

@ -11,7 +11,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
# has the user successfully posted before? # has the user successfully posted before?
defp old_user?(%User{} = u) do defp old_user?(%User{} = u) do
u.info.note_count > 0 || u.info.follower_count > 0 u.note_count > 0 || u.follower_count > 0
end end
# does the post contain links? # does the post contain links?

View file

@ -140,7 +140,7 @@ defp get_cc_ap_ids(ap_id, recipients) do
|> Enum.map(& &1.ap_id) |> Enum.map(& &1.ap_id)
end end
defp maybe_use_sharedinbox(%User{info: %{source_data: data}}), defp maybe_use_sharedinbox(%User{source_data: data}),
do: (is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"] do: (is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"]
@doc """ @doc """
@ -156,7 +156,7 @@ defp maybe_use_sharedinbox(%User{info: %{source_data: data}}),
""" """
def determine_inbox( def determine_inbox(
%Activity{data: activity_data}, %Activity{data: activity_data},
%User{info: %{source_data: data}} = user %User{source_data: data} = user
) do ) do
to = activity_data["to"] || [] to = activity_data["to"] || []
cc = activity_data["cc"] || [] cc = activity_data["cc"] || []
@ -190,12 +190,12 @@ def publish(%User{} = actor, %{data: %{"bcc" => bcc}} = activity)
recipients recipients
|> Enum.filter(&User.ap_enabled?/1) |> Enum.filter(&User.ap_enabled?/1)
|> Enum.map(fn %{info: %{source_data: data}} -> data["inbox"] end) |> Enum.map(fn %{source_data: data} -> data["inbox"] end)
|> Enum.filter(fn inbox -> should_federate?(inbox, public) end) |> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
|> Instances.filter_reachable() |> Instances.filter_reachable()
|> Enum.each(fn {inbox, unreachable_since} -> |> Enum.each(fn {inbox, unreachable_since} ->
%User{ap_id: ap_id} = %User{ap_id: ap_id} =
Enum.find(recipients, fn %{info: %{source_data: data}} -> data["inbox"] == inbox end) Enum.find(recipients, fn %{source_data: data} -> data["inbox"] == inbox end)
# Get all the recipients on the same host and add them to cc. Otherwise, a remote # Get all the recipients on the same host and add them to cc. Otherwise, a remote
# instance would only accept a first message for the first recipient and ignore the rest. # instance would only accept a first message for the first recipient and ignore the rest.

View file

@ -600,9 +600,8 @@ def handle_incoming(
with %User{ap_id: ^actor_id} = actor <- User.get_cached_by_ap_id(object["id"]) do with %User{ap_id: ^actor_id} = actor <- User.get_cached_by_ap_id(object["id"]) do
{:ok, new_user_data} = ActivityPub.user_data_from_user_object(object) {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object)
banner = new_user_data[:info][:banner] locked = new_user_data[:locked] || false
locked = new_user_data[:info][:locked] || false attachment = get_in(new_user_data, [:source_data, "attachment"]) || []
attachment = get_in(new_user_data, [:info, :source_data, "attachment"]) || []
fields = fields =
attachment attachment
@ -611,8 +610,9 @@ def handle_incoming(
update_data = update_data =
new_user_data new_user_data
|> Map.take([:name, :bio, :avatar]) |> Map.take([:avatar, :banner, :bio, :name])
|> Map.put(:info, %{banner: banner, locked: locked, fields: fields}) |> Map.put(:fields, fields)
|> Map.put(:locked, locked)
actor actor
|> User.upgrade_changeset(update_data, true) |> User.upgrade_changeset(update_data, true)
@ -979,7 +979,7 @@ defp build_mention_tag(%{ap_id: ap_id, nickname: nickname} = _) do
%{"type" => "Mention", "href" => ap_id, "name" => "@#{nickname}"} %{"type" => "Mention", "href" => ap_id, "name" => "@#{nickname}"}
end end
def take_emoji_tags(%User{info: %{emoji: emoji} = _user_info} = _user) do def take_emoji_tags(%User{emoji: emoji}) do
emoji emoji
|> Enum.flat_map(&Map.to_list/1) |> Enum.flat_map(&Map.to_list/1)
|> Enum.map(&build_emoji_tag/1) |> Enum.map(&build_emoji_tag/1)

View file

@ -78,8 +78,8 @@ def render("user.json", %{user: user}) do
emoji_tags = Transmogrifier.take_emoji_tags(user) emoji_tags = Transmogrifier.take_emoji_tags(user)
fields = fields =
user.info user
|> User.Info.fields() |> User.fields()
|> Enum.map(fn %{"name" => name, "value" => value} -> |> Enum.map(fn %{"name" => name, "value" => value} ->
%{ %{
"name" => Pleroma.HTML.strip_tags(name), "name" => Pleroma.HTML.strip_tags(name),
@ -99,7 +99,7 @@ def render("user.json", %{user: user}) do
"name" => user.name, "name" => user.name,
"summary" => user.bio, "summary" => user.bio,
"url" => user.ap_id, "url" => user.ap_id,
"manuallyApprovesFollowers" => user.info.locked, "manuallyApprovesFollowers" => user.locked,
"publicKey" => %{ "publicKey" => %{
"id" => "#{user.ap_id}#main-key", "id" => "#{user.ap_id}#main-key",
"owner" => user.ap_id, "owner" => user.ap_id,
@ -107,8 +107,8 @@ def render("user.json", %{user: user}) do
}, },
"endpoints" => endpoints, "endpoints" => endpoints,
"attachment" => fields, "attachment" => fields,
"tag" => (user.info.source_data["tag"] || []) ++ emoji_tags, "tag" => (user.source_data["tag"] || []) ++ emoji_tags,
"discoverable" => user.info.discoverable "discoverable" => user.discoverable
} }
|> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user)) |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))
|> Map.merge(maybe_make_image(&User.banner_url/2, "image", user)) |> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))
@ -116,8 +116,8 @@ def render("user.json", %{user: user}) do
end end
def render("following.json", %{user: user, page: page} = opts) do def render("following.json", %{user: user, page: page} = opts) do
showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_follows showing_items = (opts[:for] && opts[:for] == user) || !user.hide_follows
showing_count = showing_items || !user.info.hide_follows_count showing_count = showing_items || !user.hide_follows_count
query = User.get_friends_query(user) query = User.get_friends_query(user)
query = from(user in query, select: [:ap_id]) query = from(user in query, select: [:ap_id])
@ -135,8 +135,8 @@ def render("following.json", %{user: user, page: page} = opts) do
end end
def render("following.json", %{user: user} = opts) do def render("following.json", %{user: user} = opts) do
showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_follows showing_items = (opts[:for] && opts[:for] == user) || !user.hide_follows
showing_count = showing_items || !user.info.hide_follows_count showing_count = showing_items || !user.hide_follows_count
query = User.get_friends_query(user) query = User.get_friends_query(user)
query = from(user in query, select: [:ap_id]) query = from(user in query, select: [:ap_id])
@ -155,7 +155,7 @@ def render("following.json", %{user: user} = opts) do
"totalItems" => total, "totalItems" => total,
"first" => "first" =>
if showing_items do if showing_items do
collection(following, "#{user.ap_id}/following", 1, !user.info.hide_follows) collection(following, "#{user.ap_id}/following", 1, !user.hide_follows)
else else
"#{user.ap_id}/following?page=1" "#{user.ap_id}/following?page=1"
end end
@ -164,8 +164,8 @@ def render("following.json", %{user: user} = opts) do
end end
def render("followers.json", %{user: user, page: page} = opts) do def render("followers.json", %{user: user, page: page} = opts) do
showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_followers showing_items = (opts[:for] && opts[:for] == user) || !user.hide_followers
showing_count = showing_items || !user.info.hide_followers_count showing_count = showing_items || !user.hide_followers_count
query = User.get_followers_query(user) query = User.get_followers_query(user)
query = from(user in query, select: [:ap_id]) query = from(user in query, select: [:ap_id])
@ -183,8 +183,8 @@ def render("followers.json", %{user: user, page: page} = opts) do
end end
def render("followers.json", %{user: user} = opts) do def render("followers.json", %{user: user} = opts) do
showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_followers showing_items = (opts[:for] && opts[:for] == user) || !user.hide_followers
showing_count = showing_items || !user.info.hide_followers_count showing_count = showing_items || !user.hide_followers_count
query = User.get_followers_query(user) query = User.get_followers_query(user)
query = from(user in query, select: [:ap_id]) query = from(user in query, select: [:ap_id])

View file

@ -234,9 +234,9 @@ def list_user_statuses(conn, %{"nickname" => nickname} = params) do
def user_toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do def user_toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
user = User.get_cached_by_nickname(nickname) user = User.get_cached_by_nickname(nickname)
{:ok, updated_user} = User.deactivate(user, !user.info.deactivated) {:ok, updated_user} = User.deactivate(user, !user.deactivated)
action = if user.info.deactivated, do: "activate", else: "deactivate" action = if user.deactivated, do: "activate", else: "deactivate"
ModerationLog.insert_log(%{ ModerationLog.insert_log(%{
actor: admin, actor: admin,
@ -318,12 +318,12 @@ def right_add(%{assigns: %{user: admin}} = conn, %{
"nickname" => nickname "nickname" => nickname
}) })
when permission_group in ["moderator", "admin"] do when permission_group in ["moderator", "admin"] do
info = Map.put(%{}, "is_" <> permission_group, true) fields = %{:"is_#{permission_group}" => true}
{:ok, user} = {:ok, user} =
nickname nickname
|> User.get_cached_by_nickname() |> User.get_cached_by_nickname()
|> User.update_info(&User.Info.admin_api_update(&1, info)) |> User.admin_api_update(fields)
ModerationLog.insert_log(%{ ModerationLog.insert_log(%{
action: "grant", action: "grant",
@ -332,7 +332,7 @@ def right_add(%{assigns: %{user: admin}} = conn, %{
permission: permission_group permission: permission_group
}) })
json(conn, info) json(conn, fields)
end end
def right_add(conn, _) do def right_add(conn, _) do
@ -344,8 +344,8 @@ def right_get(conn, %{"nickname" => nickname}) do
conn conn
|> json(%{ |> json(%{
is_moderator: user.info.is_moderator, is_moderator: user.is_moderator,
is_admin: user.info.is_admin is_admin: user.is_admin
}) })
end end
@ -361,12 +361,12 @@ def right_delete(
} }
) )
when permission_group in ["moderator", "admin"] do when permission_group in ["moderator", "admin"] do
info = Map.put(%{}, "is_" <> permission_group, false) fields = %{:"is_#{permission_group}" => false}
{:ok, user} = {:ok, user} =
nickname nickname
|> User.get_cached_by_nickname() |> User.get_cached_by_nickname()
|> User.update_info(&User.Info.admin_api_update(&1, info)) |> User.admin_api_update(fields)
ModerationLog.insert_log(%{ ModerationLog.insert_log(%{
action: "revoke", action: "revoke",
@ -375,7 +375,7 @@ def right_delete(
permission: permission_group permission: permission_group
}) })
json(conn, info) json(conn, fields)
end end
def right_delete(conn, _) do def right_delete(conn, _) do
@ -389,7 +389,7 @@ def set_activation_status(%{assigns: %{user: admin}} = conn, %{
with {:ok, status} <- Ecto.Type.cast(:boolean, status), with {:ok, status} <- Ecto.Type.cast(:boolean, status),
%User{} = user <- User.get_cached_by_nickname(nickname), %User{} = user <- User.get_cached_by_nickname(nickname),
{:ok, _} <- User.deactivate(user, !status) do {:ok, _} <- User.deactivate(user, !status) do
action = if(user.info.deactivated, do: "activate", else: "deactivate") action = if(user.deactivated, do: "activate", else: "deactivate")
ModerationLog.insert_log(%{ ModerationLog.insert_log(%{
actor: admin, actor: admin,

View file

@ -7,7 +7,6 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
alias Pleroma.HTML alias Pleroma.HTML
alias Pleroma.User alias Pleroma.User
alias Pleroma.User.Info
alias Pleroma.Web.AdminAPI.AccountView alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.MediaProxy alias Pleroma.Web.MediaProxy
@ -28,9 +27,9 @@ def render("show.json", %{user: user}) do
"avatar" => avatar, "avatar" => avatar,
"nickname" => user.nickname, "nickname" => user.nickname,
"display_name" => display_name, "display_name" => display_name,
"deactivated" => user.info.deactivated, "deactivated" => user.deactivated,
"local" => user.local, "local" => user.local,
"roles" => Info.roles(user.info), "roles" => User.roles(user),
"tags" => user.tags || [] "tags" => user.tags || []
} }
end end

View file

@ -263,10 +263,10 @@ defp maybe_create_activity_expiration(result, _), do: result
# 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) emoji = emoji_from_profile(user)
source_data = user.info |> Map.get(:source_data, %{}) |> Map.put("tag", emoji) source_data = Map.put(user.source_data, "tag", emoji)
user = user =
case User.update_info(user, &User.Info.set_source_data(&1, source_data)) do case User.update_source_data(user, source_data) do
{:ok, user} -> user {:ok, user} -> user
_ -> user _ -> user
end end
@ -287,20 +287,20 @@ def pin(id_or_ap_id, %{ap_id: user_ap_id} = user) do
object: %Object{data: %{"type" => "Note"}} object: %Object{data: %{"type" => "Note"}}
} = 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),
{:ok, _user} <- User.update_info(user, &User.Info.add_pinnned_activity(&1, activity)) do {:ok, _user} <- User.add_pinnned_activity(user, activity) do
{:ok, activity} {:ok, activity}
else else
{:error, %{changes: %{info: %{errors: [pinned_activities: {err, _}]}}}} -> {:error, err} {:error, %{errors: [pinned_activities: {err, _}]}} -> {:error, err}
_ -> {:error, dgettext("errors", "Could not pin")} _ -> {:error, dgettext("errors", "Could not pin")}
end end
end end
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),
{:ok, _user} <- User.update_info(user, &User.Info.remove_pinnned_activity(&1, activity)) do {:ok, _user} <- User.remove_pinnned_activity(user, activity) do
{:ok, activity} {:ok, activity}
else else
%{errors: [pinned_activities: {err, _}]} -> {:error, err} {:error, %{errors: [pinned_activities: {err, _}]}} -> {:error, err}
_ -> {:error, dgettext("errors", "Could not unpin")} _ -> {:error, dgettext("errors", "Could not unpin")}
end end
end end

View file

@ -36,7 +36,7 @@ def index(%{assigns: %{user: user}} = conn, _params) do
@doc "PUT /api/web/settings" @doc "PUT /api/web/settings"
def put_settings(%{assigns: %{user: user}} = conn, %{"data" => settings} = _params) do def put_settings(%{assigns: %{user: user}} = conn, %{"data" => settings} = _params) do
with {:ok, _} <- User.update_info(user, &User.Info.mastodon_settings_update(&1, settings)) do with {:ok, _} <- User.mastodon_settings_update(user, settings) do
json(conn, %{}) json(conn, %{})
else else
e -> e ->

View file

@ -130,25 +130,6 @@ def verify_credentials(%{assigns: %{user: user}} = conn, _) do
def update_credentials(%{assigns: %{user: original_user}} = conn, params) do def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
user = original_user user = original_user
user_params =
%{}
|> add_if_present(params, "display_name", :name)
|> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value, user)} end)
|> add_if_present(params, "avatar", :avatar, fn value ->
with %Plug.Upload{} <- value,
{:ok, object} <- ActivityPub.upload(value, type: :avatar) do
{:ok, object.data}
end
end)
emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "")
user_info_emojis =
user.info
|> Map.get(:emoji, [])
|> Enum.concat(Emoji.Formatter.get_emoji_map(emojis_text))
|> Enum.dedup()
params = params =
if Map.has_key?(params, "fields_attributes") do if Map.has_key?(params, "fields_attributes") do
Map.update!(params, "fields_attributes", fn fields -> Map.update!(params, "fields_attributes", fn fields ->
@ -160,7 +141,7 @@ def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
params params
end end
info_params = user_params =
[ [
:no_rich_text, :no_rich_text,
:locked, :locked,
@ -176,15 +157,13 @@ def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
|> Enum.reduce(%{}, fn key, acc -> |> Enum.reduce(%{}, fn key, acc ->
add_if_present(acc, params, to_string(key), key, &{:ok, truthy_param?(&1)}) add_if_present(acc, params, to_string(key), key, &{:ok, truthy_param?(&1)})
end) end)
|> add_if_present(params, "default_scope", :default_scope) |> add_if_present(params, "display_name", :name)
|> add_if_present(params, "fields_attributes", :fields, fn fields -> |> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value, user)} end)
fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end) |> add_if_present(params, "avatar", :avatar, fn value ->
with %Plug.Upload{} <- value,
{:ok, fields} {:ok, object} <- ActivityPub.upload(value, type: :avatar) do
end) {:ok, object.data}
|> add_if_present(params, "fields_attributes", :raw_fields) end
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
{:ok, Map.merge(user.info.pleroma_settings_store, value)}
end) end)
|> add_if_present(params, "header", :banner, fn value -> |> add_if_present(params, "header", :banner, fn value ->
with %Plug.Upload{} <- value, with %Plug.Upload{} <- value,
@ -198,12 +177,31 @@ def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
{:ok, object.data} {:ok, object.data}
end end
end) end)
|> Map.put(:emoji, user_info_emojis) |> add_if_present(params, "fields_attributes", :fields, fn fields ->
fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
{:ok, fields}
end)
|> add_if_present(params, "fields_attributes", :raw_fields)
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
{:ok, Map.merge(user.pleroma_settings_store, value)}
end)
|> add_if_present(params, "default_scope", :default_scope)
emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "")
user_emojis =
user
|> Map.get(:emoji, [])
|> Enum.concat(Emoji.Formatter.get_emoji_map(emojis_text))
|> Enum.dedup()
user_params = Map.put(user_params, :emoji, user_emojis)
changeset = changeset =
user user
|> User.update_changeset(user_params) |> User.update_changeset(user_params)
|> User.change_info(&User.Info.profile_update(&1, info_params)) |> User.change_info(& &1)
with {:ok, user} <- User.update_and_set_cache(changeset) do with {:ok, user} <- User.update_and_set_cache(changeset) do
if original_user != user, do: CommonAPI.update(user) if original_user != user, do: CommonAPI.update(user)
@ -269,7 +267,7 @@ def followers(%{assigns: %{user: for_user, account: user}} = conn, params) do
followers = followers =
cond do cond do
for_user && user.id == for_user.id -> MastodonAPI.get_followers(user, params) for_user && user.id == for_user.id -> MastodonAPI.get_followers(user, params)
user.info.hide_followers -> [] user.hide_followers -> []
true -> MastodonAPI.get_followers(user, params) true -> MastodonAPI.get_followers(user, params)
end end
@ -283,7 +281,7 @@ def following(%{assigns: %{user: for_user, account: user}} = conn, params) do
followers = followers =
cond do cond do
for_user && user.id == for_user.id -> MastodonAPI.get_friends(user, params) for_user && user.id == for_user.id -> MastodonAPI.get_friends(user, params)
user.info.hide_follows -> [] user.hide_follows -> []
true -> MastodonAPI.get_friends(user, params) true -> MastodonAPI.get_friends(user, params)
end end

View file

@ -74,23 +74,23 @@ defp do_render("show.json", %{user: user} = opts) do
user_info = User.get_cached_user_info(user) user_info = User.get_cached_user_info(user)
following_count = following_count =
if !user.info.hide_follows_count or !user.info.hide_follows or opts[:for] == user do if !user.hide_follows_count or !user.hide_follows or opts[:for] == user do
user_info.following_count user_info.following_count
else else
0 0
end end
followers_count = followers_count =
if !user.info.hide_followers_count or !user.info.hide_followers or opts[:for] == user do if !user.hide_followers_count or !user.hide_followers or opts[:for] == user do
user_info.follower_count user_info.follower_count
else else
0 0
end end
bot = (user.info.source_data["type"] || "Person") in ["Application", "Service"] bot = (user.source_data["type"] || "Person") in ["Application", "Service"]
emojis = emojis =
(user.info.source_data["tag"] || []) (user.source_data["tag"] || [])
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end) |> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} -> |> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
%{ %{
@ -102,8 +102,8 @@ defp do_render("show.json", %{user: user} = opts) do
end) end)
fields = fields =
user.info user
|> User.Info.fields() |> User.fields()
|> Enum.map(fn %{"name" => name, "value" => value} -> |> Enum.map(fn %{"name" => name, "value" => value} ->
%{ %{
"name" => Pleroma.HTML.strip_tags(name), "name" => Pleroma.HTML.strip_tags(name),
@ -111,23 +111,19 @@ defp do_render("show.json", %{user: user} = opts) do
} }
end) end)
raw_fields = Map.get(user.info, :raw_fields, [])
bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for])) bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for]))
relationship = render("relationship.json", %{user: opts[:for], target: user}) relationship = render("relationship.json", %{user: opts[:for], target: user})
discoverable = user.info.discoverable
%{ %{
id: to_string(user.id), id: to_string(user.id),
username: username_from_nickname(user.nickname), username: username_from_nickname(user.nickname),
acct: user.nickname, acct: user.nickname,
display_name: display_name, display_name: display_name,
locked: user_info.locked, locked: user.locked,
created_at: Utils.to_masto_date(user.inserted_at), created_at: Utils.to_masto_date(user.inserted_at),
followers_count: followers_count, followers_count: followers_count,
following_count: following_count, following_count: following_count,
statuses_count: user_info.note_count, statuses_count: user.note_count,
note: bio || "", note: bio || "",
url: User.profile_url(user), url: User.profile_url(user),
avatar: image, avatar: image,
@ -140,9 +136,9 @@ defp do_render("show.json", %{user: user} = opts) do
source: %{ source: %{
note: HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")), note: HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
sensitive: false, sensitive: false,
fields: raw_fields, fields: user.raw_fields,
pleroma: %{ pleroma: %{
discoverable: discoverable discoverable: user.discoverable
} }
}, },
@ -150,14 +146,14 @@ defp do_render("show.json", %{user: user} = opts) do
pleroma: %{ pleroma: %{
confirmation_pending: user_info.confirmation_pending, confirmation_pending: user_info.confirmation_pending,
tags: user.tags, tags: user.tags,
hide_followers_count: user.info.hide_followers_count, hide_followers_count: user.hide_followers_count,
hide_follows_count: user.info.hide_follows_count, hide_follows_count: user.hide_follows_count,
hide_followers: user.info.hide_followers, hide_followers: user.hide_followers,
hide_follows: user.info.hide_follows, hide_follows: user.hide_follows,
hide_favorites: user.info.hide_favorites, hide_favorites: user.hide_favorites,
relationship: relationship, relationship: relationship,
skip_thread_containment: user.info.skip_thread_containment, skip_thread_containment: user.skip_thread_containment,
background_image: image_url(user.info.background) |> MediaProxy.url() background_image: image_url(user.background) |> MediaProxy.url()
} }
} }
|> maybe_put_role(user, opts[:for]) |> maybe_put_role(user, opts[:for])
@ -195,21 +191,21 @@ defp maybe_put_settings(
data, data,
%User{id: user_id} = user, %User{id: user_id} = user,
%User{id: user_id}, %User{id: user_id},
user_info _user_info
) do ) do
data data
|> Kernel.put_in([:source, :privacy], user_info.default_scope) |> Kernel.put_in([:source, :privacy], user.default_scope)
|> Kernel.put_in([:source, :pleroma, :show_role], user.info.show_role) |> Kernel.put_in([:source, :pleroma, :show_role], user.show_role)
|> Kernel.put_in([:source, :pleroma, :no_rich_text], user.info.no_rich_text) |> Kernel.put_in([:source, :pleroma, :no_rich_text], user.no_rich_text)
end end
defp maybe_put_settings(data, _, _, _), do: data defp maybe_put_settings(data, _, _, _), do: data
defp maybe_put_settings_store(data, %User{info: info, id: id}, %User{id: id}, %{ defp maybe_put_settings_store(data, %User{} = user, %User{}, %{
with_pleroma_settings: true with_pleroma_settings: true
}) do }) do
data data
|> Kernel.put_in([:pleroma, :settings_store], info.pleroma_settings_store) |> Kernel.put_in([:pleroma, :settings_store], user.pleroma_settings_store)
end end
defp maybe_put_settings_store(data, _, _, _), do: data defp maybe_put_settings_store(data, _, _, _), do: data
@ -223,28 +219,28 @@ defp maybe_put_chat_token(data, %User{id: id}, %User{id: id}, %{
defp maybe_put_chat_token(data, _, _, _), do: data defp maybe_put_chat_token(data, _, _, _), do: data
defp maybe_put_role(data, %User{info: %{show_role: true}} = user, _) do defp maybe_put_role(data, %User{show_role: true} = user, _) do
data data
|> Kernel.put_in([:pleroma, :is_admin], user.info.is_admin) |> Kernel.put_in([:pleroma, :is_admin], user.is_admin)
|> Kernel.put_in([:pleroma, :is_moderator], user.info.is_moderator) |> Kernel.put_in([:pleroma, :is_moderator], user.is_moderator)
end end
defp maybe_put_role(data, %User{id: user_id} = user, %User{id: user_id}) do defp maybe_put_role(data, %User{id: user_id} = user, %User{id: user_id}) do
data data
|> Kernel.put_in([:pleroma, :is_admin], user.info.is_admin) |> Kernel.put_in([:pleroma, :is_admin], user.is_admin)
|> Kernel.put_in([:pleroma, :is_moderator], user.info.is_moderator) |> Kernel.put_in([:pleroma, :is_moderator], user.is_moderator)
end end
defp maybe_put_role(data, _, _), do: data defp maybe_put_role(data, _, _), do: data
defp maybe_put_notification_settings(data, %User{id: user_id} = user, %User{id: user_id}) do defp maybe_put_notification_settings(data, %User{id: user_id} = user, %User{id: user_id}) do
Kernel.put_in(data, [:pleroma, :notification_settings], user.info.notification_settings) Kernel.put_in(data, [:pleroma, :notification_settings], user.notification_settings)
end end
defp maybe_put_notification_settings(data, _, _), do: data defp maybe_put_notification_settings(data, _, _), do: data
defp maybe_put_activation_status(data, user, %User{info: %{is_admin: true}}) do defp maybe_put_activation_status(data, user, %User{is_admin: true}) do
Kernel.put_in(data, [:pleroma, :deactivated], user.info.deactivated) Kernel.put_in(data, [:pleroma, :deactivated], user.deactivated)
end end
defp maybe_put_activation_status(data, _, _), do: data defp maybe_put_activation_status(data, _, _), do: data
@ -253,7 +249,7 @@ defp maybe_put_unread_conversation_count(data, %User{id: user_id} = user, %User{
data data
|> Kernel.put_in( |> Kernel.put_in(
[:pleroma, :unread_conversation_count], [:pleroma, :unread_conversation_count],
user.info.unread_conversation_count user.unread_conversation_count
) )
end end

View file

@ -498,6 +498,6 @@ defp present?(nil), do: false
defp present?(false), do: false defp present?(false), do: false
defp present?(_), do: true defp present?(_), do: true
defp pinned?(%Activity{id: id}, %User{info: %{pinned_activities: pinned_activities}}), defp pinned?(%Activity{id: id}, %User{pinned_activities: pinned_activities}),
do: id in pinned_activities do: id in pinned_activities
end end

View file

@ -202,9 +202,9 @@ def token_exchange(
with {:ok, %User{} = user} <- Authenticator.get_user(conn), with {:ok, %User{} = user} <- Authenticator.get_user(conn),
{:ok, app} <- Token.Utils.fetch_app(conn), {:ok, app} <- Token.Utils.fetch_app(conn),
{:auth_active, true} <- {:auth_active, User.auth_active?(user)}, {:auth_active, true} <- {:auth_active, User.auth_active?(user)},
{:user_active, true} <- {:user_active, !user.info.deactivated}, {:user_active, true} <- {:user_active, !user.deactivated},
{:password_reset_pending, false} <- {:password_reset_pending, false} <-
{:password_reset_pending, user.info.password_reset_pending}, {:password_reset_pending, user.password_reset_pending},
{:ok, scopes} <- validate_scopes(app, params), {:ok, scopes} <- validate_scopes(app, params),
{:ok, auth} <- Authorization.create_authorization(app, user, scopes), {:ok, auth} <- Authorization.create_authorization(app, user, scopes),
{:ok, token} <- Token.exchange_token(app, auth) do {:ok, token} <- Token.exchange_token(app, auth) do

View file

@ -14,7 +14,7 @@ def handle(entry, doc) do
followed_uri when not is_nil(followed_uri) <- followed_uri when not is_nil(followed_uri) <-
XML.string_from_xpath("/entry/activity:object/id", entry), XML.string_from_xpath("/entry/activity:object/id", entry),
{:ok, followed} <- OStatus.find_or_make_user(followed_uri), {:ok, followed} <- OStatus.find_or_make_user(followed_uri),
{:locked, false} <- {:locked, followed.info.locked}, {:locked, false} <- {:locked, followed.locked},
{:ok, activity} <- ActivityPub.follow(actor, followed, id, false) do {:ok, activity} <- ActivityPub.follow(actor, followed, id, false) do
User.follow(actor, followed) User.follow(actor, followed)
{:ok, activity} {:ok, activity}

View file

@ -287,14 +287,19 @@ def make_user(uri, update \\ false) do
end end
defp build_user_data(info) do defp build_user_data(info) do
%{ info_fields = Enum.map(User.info_fields(), &to_string/1)
info
|> Map.take(info_fields)
|> Map.new(fn {k, v} -> {String.to_atom(k), v} end)
|> Map.merge(%{
name: info["name"], name: info["name"],
nickname: info["nickname"] <> "@" <> info["host"], nickname: info["nickname"] <> "@" <> info["host"],
ap_id: info["uri"], ap_id: info["uri"],
info: info, info: info,
avatar: info["avatar"], avatar: info["avatar"],
bio: info["bio"] bio: info["bio"]
} })
end end
# TODO: Just takes the first one for now. # TODO: Just takes the first one for now.

View file

@ -80,9 +80,7 @@ def update_avatar(%{assigns: %{user: user}} = conn, params) do
@doc "PATCH /api/v1/pleroma/accounts/update_banner" @doc "PATCH /api/v1/pleroma/accounts/update_banner"
def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do
new_info = %{"banner" => %{}} with {:ok, user} <- User.update_banner(user, %{}) do
with {:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
CommonAPI.update(user) CommonAPI.update(user)
json(conn, %{url: nil}) json(conn, %{url: nil})
end end
@ -90,8 +88,7 @@ def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) 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}, {:ok, user} <- User.update_banner(user, object.data) do
{:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
CommonAPI.update(user) CommonAPI.update(user)
%{"url" => [%{"href" => href} | _]} = object.data %{"url" => [%{"href" => href} | _]} = object.data
@ -101,17 +98,14 @@ def update_banner(%{assigns: %{user: user}} = conn, params) do
@doc "PATCH /api/v1/pleroma/accounts/update_background" @doc "PATCH /api/v1/pleroma/accounts/update_background"
def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
new_info = %{"background" => %{}} with {:ok, _user} <- User.update_background(user, %{}) do
with {:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
json(conn, %{url: nil}) json(conn, %{url: nil})
end end
end end
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}, {:ok, _user} <- User.update_background(user, object.data) do
{:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
%{"url" => [%{"href" => href} | _]} = object.data %{"url" => [%{"href" => href} | _]} = object.data
json(conn, %{url: href}) json(conn, %{url: href})
@ -119,7 +113,7 @@ def update_background(%{assigns: %{user: user}} = conn, params) do
end end
@doc "GET /api/v1/pleroma/accounts/:id/favourites" @doc "GET /api/v1/pleroma/accounts/:id/favourites"
def favourites(%{assigns: %{account: %{info: %{hide_favorites: true}}}} = conn, _params) do def favourites(%{assigns: %{account: %{hide_favorites: true}}} = conn, _params) do
render_error(conn, :forbidden, "Can't get favorites") render_error(conn, :forbidden, "Can't get favorites")
end end

View file

@ -24,9 +24,7 @@ def update(%{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)),
# Reject if not an image # Reject if not an image
%{type: "image"} = attachment <- render_attachment(object) do %{type: "image"} = attachment <- render_attachment(object) do
# Sure! {:ok, _user} = User.mascot_update(user, attachment)
# Save to the user's info
{:ok, _user} = User.update_info(user, &User.Info.mascot_update(&1, attachment))
json(conn, attachment) json(conn, attachment)
else else

View file

@ -147,7 +147,7 @@ def remote_users(%User{id: user_id}, %{data: %{"to" => to} = data}) do
end end
@doc "Pushes an activity to remote account." @doc "Pushes an activity to remote account."
def publish_one(%{recipient: %{info: %{salmon: salmon}}} = params), def publish_one(%{recipient: %{salmon: salmon}} = params),
do: publish_one(Map.put(params, :recipient, salmon)) do: publish_one(Map.put(params, :recipient, salmon))
def publish_one(%{recipient: url, feed: feed} = params) when is_binary(url) do def publish_one(%{recipient: url, feed: feed} = params) when is_binary(url) do
@ -217,19 +217,19 @@ def publish(%{keys: keys} = user, %{data: %{"type" => type}} = activity)
remote_users = remote_users(user, activity) remote_users = remote_users(user, activity)
salmon_urls = Enum.map(remote_users, & &1.info.salmon) salmon_urls = Enum.map(remote_users, & &1.salmon)
reachable_urls_metadata = Instances.filter_reachable(salmon_urls) reachable_urls_metadata = Instances.filter_reachable(salmon_urls)
reachable_urls = Map.keys(reachable_urls_metadata) reachable_urls = Map.keys(reachable_urls_metadata)
remote_users remote_users
|> Enum.filter(&(&1.info.salmon in reachable_urls)) |> Enum.filter(&(&1.salmon in reachable_urls))
|> Enum.each(fn remote_user -> |> Enum.each(fn remote_user ->
Logger.debug(fn -> "Sending Salmon to #{remote_user.ap_id}" end) Logger.debug(fn -> "Sending Salmon to #{remote_user.ap_id}" end)
Publisher.enqueue_one(__MODULE__, %{ Publisher.enqueue_one(__MODULE__, %{
recipient_id: remote_user.id, recipient_id: remote_user.id,
feed: feed, feed: feed,
unreachable_since: reachable_urls_metadata[remote_user.info.salmon] unreachable_since: reachable_urls_metadata[remote_user.salmon]
}) })
end) end)
end end

View file

@ -212,7 +212,7 @@ def push_to_socket(topics, topic, item) do
end end
@spec thread_containment(Activity.t(), User.t()) :: boolean() @spec thread_containment(Activity.t(), User.t()) :: boolean()
defp thread_containment(_activity, %User{info: %{skip_thread_containment: true}}), do: true defp thread_containment(_activity, %User{skip_thread_containment: true}), do: true
defp thread_containment(activity, user) do defp thread_containment(activity, user) do
if Config.get([:instance, :skip_thread_containment]) do if Config.get([:instance, :skip_thread_containment]) do

View file

@ -20,11 +20,10 @@ 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
new_info = [need_confirmation: false] with %User{} = user <- User.get_cached_by_id(uid),
true <- user.local and user.confirmation_pending and user.confirmation_token == token,
with %User{info: info} = user <- User.get_cached_by_id(uid), {:ok, _} <-
true <- user.local and info.confirmation_pending and info.confirmation_token == token, User.update_and_set_cache(User.confirmation_changeset(user, need_confirmation: false)) do
{:ok, _} <- User.update_info(user, &User.Info.confirmation_changeset(&1, new_info)) do
redirect(conn, to: "/") redirect(conn, to: "/")
end end
end end

View file

@ -61,12 +61,12 @@ def initial_state(token, user, custom_emojis) do
}, },
poll_limits: Config.get([:instance, :poll_limits]), poll_limits: Config.get([:instance, :poll_limits]),
rights: %{ rights: %{
delete_others_notice: present?(user.info.is_moderator), delete_others_notice: present?(user.is_moderator),
admin: present?(user.info.is_admin) admin: present?(user.is_admin)
}, },
compose: %{ compose: %{
me: "#{user.id}", me: "#{user.id}",
default_privacy: user.info.default_scope, default_privacy: user.default_scope,
default_sensitive: false, default_sensitive: false,
allow_content_types: Config.get([:instance, :allowed_post_formats]) allow_content_types: Config.get([:instance, :allowed_post_formats])
}, },
@ -86,7 +86,7 @@ def initial_state(token, user, custom_emojis) do
"video\/mp4" "video\/mp4"
] ]
}, },
settings: user.info.settings || @default_settings, settings: user.settings || @default_settings,
push_subscription: nil, push_subscription: nil,
accounts: %{user.id => render(AccountView, "show.json", user: user, for: user)}, accounts: %{user.id => render(AccountView, "show.json", user: user, for: user)},
custom_emojis: render(CustomEmojiView, "index.json", custom_emojis: custom_emojis), custom_emojis: render(CustomEmojiView, "index.json", custom_emojis: custom_emojis),

View file

@ -181,7 +181,7 @@ defp valid_topic(%{"hub.topic" => topic}, user) do
end end
def subscribe(subscriber, subscribed, requester \\ &request_subscription/1) do def subscribe(subscriber, subscribed, requester \\ &request_subscription/1) do
topic = subscribed.info.topic topic = subscribed.topic
# FIXME: Race condition, use transactions # FIXME: Race condition, use transactions
{:ok, subscription} = {:ok, subscription} =
with subscription when not is_nil(subscription) <- with subscription when not is_nil(subscription) <-
@ -193,7 +193,7 @@ def subscribe(subscriber, subscribed, requester \\ &request_subscription/1) do
_e -> _e ->
subscription = %WebsubClientSubscription{ subscription = %WebsubClientSubscription{
topic: topic, topic: topic,
hub: subscribed.info.hub, hub: subscribed.hub,
subscribers: [subscriber.ap_id], subscribers: [subscriber.ap_id],
state: "requested", state: "requested",
secret: :crypto.strong_rand_bytes(8) |> Base.url_encode64(), secret: :crypto.strong_rand_bytes(8) |> Base.url_encode64(),

View file

@ -5,7 +5,11 @@ defmodule Pleroma.Repo.Migrations.AddFollowingAddressFromSourceData do
def change do def change do
query = query =
User.external_users_query() User.Query.build(%{
external: true,
legacy_active: true,
order_by: :id
})
|> select([u], struct(u, [:id, :ap_id, :info])) |> select([u], struct(u, [:id, :ap_id, :info]))
Pleroma.Repo.stream(query) Pleroma.Repo.stream(query)

View file

@ -1,6 +1,5 @@
defmodule Pleroma.Repo.Migrations.CopyMutedToMutedNotifications do defmodule Pleroma.Repo.Migrations.CopyMutedToMutedNotifications do
use Ecto.Migration use Ecto.Migration
alias Pleroma.User
def change do def change do
execute( execute(

View file

@ -0,0 +1,54 @@
defmodule Pleroma.Repo.Migrations.CopyUsersInfoaddsToUsers do
use Ecto.Migration
def change do
alter table(:users) do
add(:banner, :map, default: %{})
add(:background, :map, default: %{})
add(:source_data, :map, default: %{})
add(:note_count, :integer, default: 0)
add(:follower_count, :integer, default: 0)
# Should be filled in only for remote users
add(:following_count, :integer, default: nil)
add(:locked, :boolean, default: false)
add(:confirmation_pending, :boolean, default: false)
add(:password_reset_pending, :boolean, default: false)
add(:confirmation_token, :text, default: nil)
add(:default_scope, :string, default: "public")
add(:blocks, {:array, :text}, default: [])
add(:domain_blocks, {:array, :text}, default: [])
add(:mutes, {:array, :text}, default: [])
add(:muted_reblogs, {:array, :text}, default: [])
add(:muted_notifications, {:array, :text}, default: [])
add(:subscribers, {:array, :text}, default: [])
add(:deactivated, :boolean, default: false, null: false)
add(:no_rich_text, :boolean, default: false, null: false)
add(:ap_enabled, :boolean, default: false, null: false)
add(:is_moderator, :boolean, default: false, null: false)
add(:is_admin, :boolean, default: false, null: false)
add(:show_role, :boolean, default: true, null: false)
add(:settings, :map, default: nil)
add(:magic_key, :text, default: nil)
add(:uri, :text, default: nil)
add(:topic, :text, default: nil)
add(:hub, :text, default: nil)
add(:salmon, :text, default: nil)
add(:hide_followers_count, :boolean, default: false, null: false)
add(:hide_follows_count, :boolean, default: false, null: false)
add(:hide_followers, :boolean, default: false, null: false)
add(:hide_follows, :boolean, default: false, null: false)
add(:hide_favorites, :boolean, default: true, null: false)
add(:unread_conversation_count, :integer, default: 0)
add(:pinned_activities, {:array, :text}, default: [])
add(:email_notifications, :map, default: %{"digest" => false})
add(:mascot, :map, default: nil)
add(:emoji, {:array, :map}, default: [])
add(:pleroma_settings_store, :map, default: %{})
add(:fields, {:array, :map}, default: nil)
add(:raw_fields, {:array, :map}, default: [])
add(:discoverable, :boolean, default: false, null: false)
add(:notification_settings, :map, default: %{})
add(:skip_thread_containment, :boolean, default: false, null: false)
end
end
end

View file

@ -20,7 +20,7 @@ test "it sends digest emails" do
|> Timex.to_naive_datetime() |> Timex.to_naive_datetime()
user2 = insert(:user, last_digest_emailed_at: date) user2 = insert(:user, last_digest_emailed_at: date)
User.switch_email_notifications(user2, "digest", true) {:ok, _} = User.switch_email_notifications(user2, "digest", true)
CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}!"}) CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}!"})
DigestEmailDaemon.perform() DigestEmailDaemon.perform()

View file

@ -36,7 +36,7 @@ test "build user invitation email" do
test "build account confirmation email" do test "build account confirmation email" do
config = Pleroma.Config.get(:instance) config = Pleroma.Config.get(:instance)
user = insert(:user, info: %Pleroma.User.Info{confirmation_token: "conf-token"}) user = insert(:user, confirmation_token: "conf-token")
email = UserEmail.account_confirmation_email(user) email = UserEmail.account_confirmation_email(user)
assert email.from == {config[:name], config[:notify_email]} assert email.from == {config[:name], config[:notify_email]}
assert email.to == [{user.name, user.email}] assert email.to == [{user.name, user.email}]

View file

@ -125,10 +125,10 @@ test "gives a replacement for user links, using local nicknames in user links te
gsimg = insert(:user, %{nickname: "gsimg"}) gsimg = insert(:user, %{nickname: "gsimg"})
archaeme = archaeme =
insert(:user, %{ insert(:user,
nickname: "archa_eme_", nickname: "archa_eme_",
info: %User.Info{source_data: %{"url" => "https://archeme/@archa_eme_"}} source_data: %{"url" => "https://archeme/@archa_eme_"}
}) )
archaeme_remote = insert(:user, %{nickname: "archaeme@archae.me"}) archaeme_remote = insert(:user, %{nickname: "archaeme@archae.me"})

View file

@ -12,8 +12,8 @@ defmodule Pleroma.ModerationLogTest do
describe "user moderation" do describe "user moderation" do
setup do setup do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
moderator = insert(:user, info: %{is_moderator: true}) moderator = insert(:user, is_moderator: true)
subject1 = insert(:user) subject1 = insert(:user)
subject2 = insert(:user) subject2 = insert(:user)

View file

@ -136,7 +136,7 @@ test "it creates a notification for an activity from a muted thread" do
test "it disables notifications from followers" do test "it disables notifications from followers" do
follower = insert(:user) follower = insert(:user)
followed = insert(:user, info: %{notification_settings: %{"followers" => false}}) followed = insert(:user, notification_settings: %{"followers" => false})
User.follow(follower, followed) User.follow(follower, followed)
{:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"}) {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
refute Notification.create_notification(activity, followed) refute Notification.create_notification(activity, followed)
@ -144,13 +144,13 @@ test "it disables notifications from followers" do
test "it disables notifications from non-followers" do test "it disables notifications from non-followers" do
follower = insert(:user) follower = insert(:user)
followed = insert(:user, info: %{notification_settings: %{"non_followers" => false}}) followed = insert(:user, notification_settings: %{"non_followers" => false})
{:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"}) {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
refute Notification.create_notification(activity, followed) refute Notification.create_notification(activity, followed)
end end
test "it disables notifications from people the user follows" do test "it disables notifications from people the user follows" do
follower = insert(:user, info: %{notification_settings: %{"follows" => false}}) follower = insert(:user, notification_settings: %{"follows" => false})
followed = insert(:user) followed = insert(:user)
User.follow(follower, followed) User.follow(follower, followed)
follower = Repo.get(User, follower.id) follower = Repo.get(User, follower.id)
@ -159,7 +159,7 @@ test "it disables notifications from people the user follows" do
end end
test "it disables notifications from people the user does not follow" do test "it disables notifications from people the user does not follow" do
follower = insert(:user, info: %{notification_settings: %{"non_follows" => false}}) follower = insert(:user, notification_settings: %{"non_follows" => false})
followed = insert(:user) followed = insert(:user)
{:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"}) {:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
refute Notification.create_notification(activity, follower) refute Notification.create_notification(activity, follower)

View file

@ -37,6 +37,6 @@ test "with secret set and given in the 'admin_token' parameter, it assigns an ad
%{conn | params: %{"admin_token" => "password123"}} %{conn | params: %{"admin_token" => "password123"}}
|> AdminSecretAuthenticationPlug.call(%{}) |> AdminSecretAuthenticationPlug.call(%{})
assert conn.assigns[:user].info.is_admin assert conn.assigns[:user].is_admin
end end
end end

View file

@ -17,7 +17,7 @@ test "doesn't do anything if the user isn't set", %{conn: conn} do
end end
test "with a user that is deactivated, it removes that user", %{conn: conn} do test "with a user that is deactivated, it removes that user", %{conn: conn} do
user = insert(:user, info: %{deactivated: true}) user = insert(:user, deactivated: true)
conn = conn =
conn conn

View file

@ -9,7 +9,7 @@ defmodule Pleroma.Plugs.UserIsAdminPlugTest do
import Pleroma.Factory import Pleroma.Factory
test "accepts a user that is admin" do test "accepts a user that is admin" do
user = insert(:user, info: %{is_admin: true}) user = insert(:user, is_admin: true)
conn = conn =
build_conn() build_conn()

View file

@ -42,7 +42,7 @@ defp make_fake_conn(key_id),
test "it returns key" do test "it returns key" do
expected_result = {:ok, @rsa_public_key} expected_result = {:ok, @rsa_public_key}
user = insert(:user, %{info: %{source_data: %{"publicKey" => @public_key}}}) user = insert(:user, source_data: %{"publicKey" => @public_key})
assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == expected_result assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == expected_result
end end
@ -54,7 +54,7 @@ test "it returns error when not found user" do
end end
test "it returns error if public key is empty" do test "it returns error if public key is empty" do
user = insert(:user, %{info: %{source_data: %{"publicKey" => %{}}}}) user = insert(:user, source_data: %{"publicKey" => %{}})
assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == {:error, :error} assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == {:error, :error}
end end

View file

@ -22,18 +22,18 @@ test "counts statuses" do
user = refresh_record(user) user = refresh_record(user)
user2 = refresh_record(user2) user2 = refresh_record(user2)
assert %{info: %{note_count: 2}} = user assert %{note_count: 2} = user
assert %{info: %{note_count: 1}} = user2 assert %{note_count: 1} = user2
{:ok, user} = User.update_info(user, &User.Info.set_note_count(&1, 0)) {:ok, user} = User.update_note_count(user, 0)
{:ok, user2} = User.update_info(user2, &User.Info.set_note_count(&1, 0)) {:ok, user2} = User.update_note_count(user2, 0)
assert %{info: %{note_count: 0}} = user assert %{note_count: 0} = user
assert %{info: %{note_count: 0}} = user2 assert %{note_count: 0} = user2
assert capture_io(fn -> Mix.Tasks.Pleroma.CountStatuses.run([]) end) == "Done\n" assert capture_io(fn -> Mix.Tasks.Pleroma.CountStatuses.run([]) end) == "Done\n"
assert %{info: %{note_count: 2}} = refresh_record(user) assert %{note_count: 2} = refresh_record(user)
assert %{info: %{note_count: 1}} = refresh_record(user2) assert %{note_count: 1} = refresh_record(user2)
end end
end end

View file

@ -72,26 +72,25 @@ test "it prunes old objects from the database" do
describe "running update_users_following_followers_counts" do describe "running update_users_following_followers_counts" do
test "following and followers count are updated" do test "following and followers count are updated" do
[user, user2] = insert_pair(:user) [user, user2] = insert_pair(:user)
{:ok, %User{following: following, info: info} = user} = User.follow(user, user2) {:ok, %User{following: following} = user} = User.follow(user, user2)
assert length(following) == 2 assert length(following) == 2
assert info.follower_count == 0 assert user.follower_count == 0
{:ok, user} = {:ok, user} =
user user
|> Ecto.Changeset.change(%{following: following ++ following}) |> Ecto.Changeset.change(%{following: following ++ following, follower_count: 3})
|> User.change_info(&Ecto.Changeset.change(&1, %{follower_count: 3}))
|> Repo.update() |> Repo.update()
assert length(user.following) == 4 assert length(user.following) == 4
assert user.info.follower_count == 3 assert user.follower_count == 3
assert :ok == Mix.Tasks.Pleroma.Database.run(["update_users_following_followers_counts"]) assert :ok == Mix.Tasks.Pleroma.Database.run(["update_users_following_followers_counts"])
user = User.get_by_id(user.id) user = User.get_by_id(user.id)
assert length(user.following) == 2 assert length(user.following) == 2
assert user.info.follower_count == 0 assert user.follower_count == 0
end end
end end

View file

@ -58,8 +58,8 @@ test "user is created" do
assert user.name == unsaved.name assert user.name == unsaved.name
assert user.email == unsaved.email assert user.email == unsaved.email
assert user.bio == unsaved.bio assert user.bio == unsaved.bio
assert user.info.is_moderator assert user.is_moderator
assert user.info.is_admin assert user.is_admin
end end
test "user is not created" do test "user is not created" do
@ -113,11 +113,11 @@ test "user is deactivated" do
assert message =~ " deactivated" assert message =~ " deactivated"
user = User.get_cached_by_nickname(user.nickname) user = User.get_cached_by_nickname(user.nickname)
assert user.info.deactivated assert user.deactivated
end end
test "user is activated" do test "user is activated" do
user = insert(:user, info: %{deactivated: true}) user = insert(:user, deactivated: true)
Mix.Tasks.Pleroma.User.run(["toggle_activated", user.nickname]) Mix.Tasks.Pleroma.User.run(["toggle_activated", user.nickname])
@ -125,7 +125,7 @@ test "user is activated" do
assert message =~ " activated" assert message =~ " activated"
user = User.get_cached_by_nickname(user.nickname) user = User.get_cached_by_nickname(user.nickname)
refute user.info.deactivated refute user.deactivated
end end
test "no user to toggle" do test "no user to toggle" do
@ -155,7 +155,7 @@ test "user is unsubscribed" do
user = User.get_cached_by_nickname(user.nickname) user = User.get_cached_by_nickname(user.nickname)
assert Enum.empty?(user.following) assert Enum.empty?(user.following)
assert user.info.deactivated assert user.deactivated
end end
test "no user to unsubscribe" do test "no user to unsubscribe" do
@ -182,13 +182,13 @@ test "All statuses set" do
assert message =~ ~r/Admin status .* true/ assert message =~ ~r/Admin status .* true/
user = User.get_cached_by_nickname(user.nickname) user = User.get_cached_by_nickname(user.nickname)
assert user.info.is_moderator assert user.is_moderator
assert user.info.locked assert user.locked
assert user.info.is_admin assert user.is_admin
end end
test "All statuses unset" do test "All statuses unset" do
user = insert(:user, info: %{is_moderator: true, locked: true, is_admin: true}) user = insert(:user, locked: true, is_moderator: true, is_admin: true)
Mix.Tasks.Pleroma.User.run([ Mix.Tasks.Pleroma.User.run([
"set", "set",
@ -208,9 +208,9 @@ test "All statuses unset" do
assert message =~ ~r/Admin status .* false/ assert message =~ ~r/Admin status .* false/
user = User.get_cached_by_nickname(user.nickname) user = User.get_cached_by_nickname(user.nickname)
refute user.info.is_moderator refute user.is_moderator
refute user.info.locked refute user.locked
refute user.info.is_admin refute user.is_admin
end end
test "no user to set status" do test "no user to set status" do
@ -358,28 +358,28 @@ test "it prints an error message when user is not exist" do
describe "running toggle_confirmed" do describe "running toggle_confirmed" do
test "user is confirmed" do test "user is confirmed" do
%{id: id, nickname: nickname} = insert(:user, info: %{confirmation_pending: false}) %{id: id, nickname: nickname} = insert(:user, confirmation_pending: false)
assert :ok = Mix.Tasks.Pleroma.User.run(["toggle_confirmed", nickname]) assert :ok = Mix.Tasks.Pleroma.User.run(["toggle_confirmed", nickname])
assert_received {:mix_shell, :info, [message]} assert_received {:mix_shell, :info, [message]}
assert message == "#{nickname} needs confirmation." assert message == "#{nickname} needs confirmation."
user = Repo.get(User, id) user = Repo.get(User, id)
assert user.info.confirmation_pending assert user.confirmation_pending
assert user.info.confirmation_token assert user.confirmation_token
end end
test "user is not confirmed" do test "user is not confirmed" do
%{id: id, nickname: nickname} = %{id: id, nickname: nickname} =
insert(:user, info: %{confirmation_pending: true, confirmation_token: "some token"}) insert(:user, confirmation_pending: true, confirmation_token: "some token")
assert :ok = Mix.Tasks.Pleroma.User.run(["toggle_confirmed", nickname]) assert :ok = Mix.Tasks.Pleroma.User.run(["toggle_confirmed", nickname])
assert_received {:mix_shell, :info, [message]} assert_received {:mix_shell, :info, [message]}
assert message == "#{nickname} doesn't need confirmation." assert message == "#{nickname} doesn't need confirmation."
user = Repo.get(User, id) user = Repo.get(User, id)
refute user.info.confirmation_pending refute user.confirmation_pending
refute user.info.confirmation_token refute user.confirmation_token
end end
test "it prints an error message when user is not exist" do test "it prints an error message when user is not exist" do

View file

@ -1,24 +0,0 @@
defmodule Pleroma.UserInfoTest do
alias Pleroma.Repo
alias Pleroma.User.Info
use Pleroma.DataCase
import Pleroma.Factory
describe "update_email_notifications/2" do
setup do
user = insert(:user, %{info: %{email_notifications: %{"digest" => true}}})
{:ok, user: user}
end
test "Notifications are updated", %{user: user} do
true = user.info.email_notifications["digest"]
changeset = Info.update_email_notifications(user.info, %{"digest" => false})
assert changeset.valid?
{:ok, result} = Ecto.Changeset.apply_action(changeset, :insert)
assert result.email_notifications["digest"] == false
end
end
end

View file

@ -68,7 +68,7 @@ test "ap_following returns the following collection for the user" do
test "returns all pending follow requests" do test "returns all pending follow requests" do
unlocked = insert(:user) unlocked = insert(:user)
locked = insert(:user, %{info: %{locked: true}}) locked = insert(:user, locked: true)
follower = insert(:user) follower = insert(:user)
CommonAPI.follow(follower, unlocked) CommonAPI.follow(follower, unlocked)
@ -81,7 +81,7 @@ test "returns all pending follow requests" do
end end
test "doesn't return already accepted or duplicate follow requests" do test "doesn't return already accepted or duplicate follow requests" do
locked = insert(:user, %{info: %{locked: true}}) locked = insert(:user, locked: true)
pending_follower = insert(:user) pending_follower = insert(:user)
accepted_follower = insert(:user) accepted_follower = insert(:user)
@ -95,7 +95,7 @@ test "doesn't return already accepted or duplicate follow requests" do
end end
test "clears follow requests when requester is blocked" do test "clears follow requests when requester is blocked" do
followed = insert(:user, %{info: %{locked: true}}) followed = insert(:user, locked: true)
follower = insert(:user) follower = insert(:user)
CommonAPI.follow(follower, followed) CommonAPI.follow(follower, followed)
@ -151,14 +151,14 @@ test "follow takes a user and another user" do
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
followed = User.get_cached_by_ap_id(followed.ap_id) followed = User.get_cached_by_ap_id(followed.ap_id)
assert followed.info.follower_count == 1 assert followed.follower_count == 1
assert User.ap_followers(followed) in user.following assert User.ap_followers(followed) in user.following
end end
test "can't follow a deactivated users" do test "can't follow a deactivated users" do
user = insert(:user) user = insert(:user)
followed = insert(:user, info: %{deactivated: true}) followed = insert(:user, %{deactivated: true})
{:error, _} = User.follow(user, followed) {:error, _} = User.follow(user, followed)
end end
@ -182,8 +182,8 @@ test "can't subscribe to a user who blocked us" do
end end
test "local users do not automatically follow local locked accounts" do test "local users do not automatically follow local locked accounts" do
follower = insert(:user, info: %{locked: true}) follower = insert(:user, locked: true)
followed = insert(:user, info: %{locked: true}) followed = insert(:user, locked: true)
{:ok, follower} = User.maybe_direct_follow(follower, followed) {:ok, follower} = User.maybe_direct_follow(follower, followed)
@ -400,8 +400,8 @@ test "it creates unconfirmed user" do
{:ok, user} = Repo.insert(changeset) {:ok, user} = Repo.insert(changeset)
assert user.info.confirmation_pending assert user.confirmation_pending
assert user.info.confirmation_token assert user.confirmation_token
end end
test "it creates confirmed user if :confirmed option is given" do test "it creates confirmed user if :confirmed option is given" do
@ -410,8 +410,8 @@ test "it creates confirmed user if :confirmed option is given" do
{:ok, user} = Repo.insert(changeset) {:ok, user} = Repo.insert(changeset)
refute user.info.confirmation_pending refute user.confirmation_pending
refute user.info.confirmation_token refute user.confirmation_token
end end
end end
@ -505,7 +505,8 @@ test "updates an existing user, if stale" do
assert orig_user.last_refreshed_at == a_week_ago assert orig_user.last_refreshed_at == a_week_ago
{:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin") {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
assert user.info.source_data["endpoints"]
assert user.source_data["endpoints"]
refute user.last_refreshed_at == orig_user.last_refreshed_at refute user.last_refreshed_at == orig_user.last_refreshed_at
end end
@ -611,63 +612,63 @@ test "gets all friends (followed users) for a given user" do
end end
describe "updating note and follower count" do describe "updating note and follower count" do
test "it sets the info->note_count property" do test "it sets the note_count property" do
note = insert(:note) note = insert(:note)
user = User.get_cached_by_ap_id(note.data["actor"]) user = User.get_cached_by_ap_id(note.data["actor"])
assert user.info.note_count == 0 assert user.note_count == 0
{:ok, user} = User.update_note_count(user) {:ok, user} = User.update_note_count(user)
assert user.info.note_count == 1 assert user.note_count == 1
end end
test "it increases the info->note_count property" do test "it increases the note_count property" do
note = insert(:note) note = insert(:note)
user = User.get_cached_by_ap_id(note.data["actor"]) user = User.get_cached_by_ap_id(note.data["actor"])
assert user.info.note_count == 0 assert user.note_count == 0
{:ok, user} = User.increase_note_count(user) {:ok, user} = User.increase_note_count(user)
assert user.info.note_count == 1 assert user.note_count == 1
{:ok, user} = User.increase_note_count(user) {:ok, user} = User.increase_note_count(user)
assert user.info.note_count == 2 assert user.note_count == 2
end end
test "it decreases the info->note_count property" do test "it decreases the note_count property" do
note = insert(:note) note = insert(:note)
user = User.get_cached_by_ap_id(note.data["actor"]) user = User.get_cached_by_ap_id(note.data["actor"])
assert user.info.note_count == 0 assert user.note_count == 0
{:ok, user} = User.increase_note_count(user) {:ok, user} = User.increase_note_count(user)
assert user.info.note_count == 1 assert user.note_count == 1
{:ok, user} = User.decrease_note_count(user) {:ok, user} = User.decrease_note_count(user)
assert user.info.note_count == 0 assert user.note_count == 0
{:ok, user} = User.decrease_note_count(user) {:ok, user} = User.decrease_note_count(user)
assert user.info.note_count == 0 assert user.note_count == 0
end end
test "it sets the info->follower_count property" do test "it sets the follower_count property" do
user = insert(:user) user = insert(:user)
follower = insert(:user) follower = insert(:user)
User.follow(follower, user) User.follow(follower, user)
assert user.info.follower_count == 0 assert user.follower_count == 0
{:ok, user} = User.update_follower_count(user) {:ok, user} = User.update_follower_count(user)
assert user.info.follower_count == 1 assert user.follower_count == 1
end end
end end
@ -958,11 +959,11 @@ test "get recipients from activity" do
describe ".deactivate" do describe ".deactivate" do
test "can de-activate then re-activate a user" do test "can de-activate then re-activate a user" do
user = insert(:user) user = insert(:user)
assert false == user.info.deactivated assert false == user.deactivated
{:ok, user} = User.deactivate(user) {:ok, user} = User.deactivate(user)
assert true == user.info.deactivated assert true == user.deactivated
{:ok, user} = User.deactivate(user, false) {:ok, user} = User.deactivate(user, false)
assert false == user.info.deactivated assert false == user.deactivated
end end
test "hide a user from followers" do test "hide a user from followers" do
@ -1041,7 +1042,7 @@ test ".delete_user_activities deletes all create activities", %{user: user} do
end end
test "it deletes deactivated user" do test "it deletes deactivated user" do
{:ok, user} = insert(:user, info: %{deactivated: true}) |> User.set_cache() {:ok, user} = insert(:user, deactivated: true) |> User.set_cache()
{:ok, job} = User.delete(user) {:ok, job} = User.delete(user)
{:ok, _user} = ObanHelpers.perform(job) {:ok, _user} = ObanHelpers.perform(job)
@ -1180,7 +1181,7 @@ test "html_filter_policy returns default policies, when rich-text is enabled" do
end end
test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
user = insert(:user, %{info: %{no_rich_text: true}}) user = insert(:user, no_rich_text: true)
assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user) assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
end end
@ -1217,8 +1218,8 @@ test "User.delete() plugs any possible zombie objects" do
test "auth_active?/1 works correctly" do test "auth_active?/1 works correctly" do
Pleroma.Config.put([:instance, :account_activation_required], true) Pleroma.Config.put([:instance, :account_activation_required], true)
local_user = insert(:user, local: true, info: %{confirmation_pending: true}) local_user = insert(:user, local: true, confirmation_pending: true)
confirmed_user = insert(:user, local: true, info: %{confirmation_pending: false}) confirmed_user = insert(:user, local: true, confirmation_pending: false)
remote_user = insert(:user, local: false) remote_user = insert(:user, local: false)
refute User.auth_active?(local_user) refute User.auth_active?(local_user)
@ -1235,20 +1236,20 @@ test "returns false for unprivileged users" do
test "returns false for remote users" do test "returns false for remote users" do
user = insert(:user, local: false) user = insert(:user, local: false)
remote_admin_user = insert(:user, local: false, info: %{is_admin: true}) remote_admin_user = insert(:user, local: false, is_admin: true)
refute User.superuser?(user) refute User.superuser?(user)
refute User.superuser?(remote_admin_user) refute User.superuser?(remote_admin_user)
end end
test "returns true for local moderators" do test "returns true for local moderators" do
user = insert(:user, local: true, info: %{is_moderator: true}) user = insert(:user, local: true, is_moderator: true)
assert User.superuser?(user) assert User.superuser?(user)
end end
test "returns true for local admins" do test "returns true for local admins" do
user = insert(:user, local: true, info: %{is_admin: true}) user = insert(:user, local: true, is_admin: true)
assert User.superuser?(user) assert User.superuser?(user)
end end
@ -1264,14 +1265,14 @@ test "returns true when the account is itself" do
test "returns false when the account is unauthenticated and auth is required" do test "returns false when the account is unauthenticated and auth is required" do
Pleroma.Config.put([:instance, :account_activation_required], true) Pleroma.Config.put([:instance, :account_activation_required], true)
user = insert(:user, local: true, info: %{confirmation_pending: true}) user = insert(:user, local: true, confirmation_pending: true)
other_user = insert(:user, local: true) other_user = insert(:user, local: true)
refute User.visible_for?(user, other_user) refute User.visible_for?(user, other_user)
end end
test "returns true when the account is unauthenticated and auth is not required" do test "returns true when the account is unauthenticated and auth is not required" do
user = insert(:user, local: true, info: %{confirmation_pending: true}) user = insert(:user, local: true, confirmation_pending: true)
other_user = insert(:user, local: true) other_user = insert(:user, local: true)
assert User.visible_for?(user, other_user) assert User.visible_for?(user, other_user)
@ -1280,8 +1281,8 @@ test "returns true when the account is unauthenticated and auth is not required"
test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
Pleroma.Config.put([:instance, :account_activation_required], true) Pleroma.Config.put([:instance, :account_activation_required], true)
user = insert(:user, local: true, info: %{confirmation_pending: true}) user = insert(:user, local: true, confirmation_pending: true)
other_user = insert(:user, local: true, info: %{is_admin: true}) other_user = insert(:user, local: true, is_admin: true)
assert User.visible_for?(user, other_user) assert User.visible_for?(user, other_user)
end end
@ -1347,7 +1348,7 @@ test "Users are inactive by default" do
users = users =
Enum.map(1..total, fn _ -> Enum.map(1..total, fn _ ->
insert(:user, last_digest_emailed_at: days_ago(20), info: %{deactivated: false}) insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
end) end)
inactive_users_ids = inactive_users_ids =
@ -1365,7 +1366,7 @@ test "Only includes users who has no recent activity" do
users = users =
Enum.map(1..total, fn _ -> Enum.map(1..total, fn _ ->
insert(:user, last_digest_emailed_at: days_ago(20), info: %{deactivated: false}) insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
end) end)
{inactive, active} = Enum.split(users, trunc(total / 2)) {inactive, active} = Enum.split(users, trunc(total / 2))
@ -1398,7 +1399,7 @@ test "Only includes users with no read notifications" do
users = users =
Enum.map(1..total, fn _ -> Enum.map(1..total, fn _ ->
insert(:user, last_digest_emailed_at: days_ago(20), info: %{deactivated: false}) insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
end) end)
[sender | recipients] = users [sender | recipients] = users
@ -1438,19 +1439,19 @@ test "Only includes users with no read notifications" do
describe "toggle_confirmation/1" do describe "toggle_confirmation/1" do
test "if user is confirmed" do test "if user is confirmed" do
user = insert(:user, info: %{confirmation_pending: false}) user = insert(:user, confirmation_pending: false)
{:ok, user} = User.toggle_confirmation(user) {:ok, user} = User.toggle_confirmation(user)
assert user.info.confirmation_pending assert user.confirmation_pending
assert user.info.confirmation_token assert user.confirmation_token
end end
test "if user is unconfirmed" do test "if user is unconfirmed" do
user = insert(:user, info: %{confirmation_pending: true, confirmation_token: "some token"}) user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
{:ok, user} = User.toggle_confirmation(user) {:ok, user} = User.toggle_confirmation(user)
refute user.info.confirmation_pending refute user.confirmation_pending
refute user.info.confirmation_token refute user.confirmation_token
end end
end end
@ -1486,7 +1487,7 @@ test "it returns a list of AP ids for a given set of nicknames" do
user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed") user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2") user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
insert(:user, local: true) insert(:user, local: true)
insert(:user, local: false, info: %{deactivated: true}) insert(:user, local: false, deactivated: true)
{:ok, user1: user1, user2: user2} {:ok, user1: user1, user2: user2}
end end
@ -1605,7 +1606,7 @@ test "updates the counters normally on following/getting a follow when disabled"
local: false, local: false,
follower_address: "http://localhost:4001/users/masto_closed/followers", follower_address: "http://localhost:4001/users/masto_closed/followers",
following_address: "http://localhost:4001/users/masto_closed/following", following_address: "http://localhost:4001/users/masto_closed/following",
info: %{ap_enabled: true} ap_enabled: true
) )
assert User.user_info(other_user).following_count == 0 assert User.user_info(other_user).following_count == 0
@ -1628,7 +1629,7 @@ test "syncronizes the counters with the remote instance for the followed when en
local: false, local: false,
follower_address: "http://localhost:4001/users/masto_closed/followers", follower_address: "http://localhost:4001/users/masto_closed/followers",
following_address: "http://localhost:4001/users/masto_closed/following", following_address: "http://localhost:4001/users/masto_closed/following",
info: %{ap_enabled: true} ap_enabled: true
) )
assert User.user_info(other_user).following_count == 0 assert User.user_info(other_user).following_count == 0
@ -1651,7 +1652,7 @@ test "syncronizes the counters with the remote instance for the follower when en
local: false, local: false,
follower_address: "http://localhost:4001/users/masto_closed/followers", follower_address: "http://localhost:4001/users/masto_closed/followers",
following_address: "http://localhost:4001/users/masto_closed/following", following_address: "http://localhost:4001/users/masto_closed/following",
info: %{ap_enabled: true} ap_enabled: true
) )
assert User.user_info(other_user).following_count == 0 assert User.user_info(other_user).following_count == 0
@ -1691,41 +1692,6 @@ test "changes email", %{user: user} do
end end
end end
describe "set_password_reset_pending/2" do
setup do
[user: insert(:user)]
end
test "sets password_reset_pending to true", %{user: user} do
%{password_reset_pending: password_reset_pending} = user.info
refute password_reset_pending
{:ok, %{info: %{password_reset_pending: password_reset_pending}}} =
User.force_password_reset(user)
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
describe "get_cached_by_nickname_or_id" do describe "get_cached_by_nickname_or_id" do
setup do setup do
limit_to_local_content = Pleroma.Config.get([:instance, :limit_to_local_content]) limit_to_local_content = Pleroma.Config.get([:instance, :limit_to_local_content])
@ -1782,4 +1748,18 @@ test "allows getting local users by nickname no matter what :limit_to_local_cont
assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname) assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
end end
end end
describe "update_email_notifications/2" do
setup do
user = insert(:user, email_notifications: %{"digest" => true})
{:ok, user: user}
end
test "Notifications are updated", %{user: user} do
true = user.email_notifications["digest"]
assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
assert result.email_notifications["digest"] == false
end
end
end end

View file

@ -683,7 +683,7 @@ test "it returns the followers in a collection", %{conn: conn} do
test "it returns returns a uri if the user has 'hide_followers' set", %{conn: conn} do test "it returns returns a uri if the user has 'hide_followers' set", %{conn: conn} do
user = insert(:user) user = insert(:user)
user_two = insert(:user, %{info: %{hide_followers: true}}) user_two = insert(:user, hide_followers: true)
User.follow(user, user_two) User.follow(user, user_two)
result = result =
@ -696,7 +696,7 @@ test "it returns returns a uri if the user has 'hide_followers' set", %{conn: co
test "it returns a 403 error on pages, if the user has 'hide_followers' set and the request is not authenticated", test "it returns a 403 error on pages, if the user has 'hide_followers' set and the request is not authenticated",
%{conn: conn} do %{conn: conn} do
user = insert(:user, %{info: %{hide_followers: true}}) user = insert(:user, hide_followers: true)
result = result =
conn conn
@ -708,7 +708,7 @@ test "it returns a 403 error on pages, if the user has 'hide_followers' set and
test "it renders the page, if the user has 'hide_followers' set and the request is authenticated with the same user", test "it renders the page, if the user has 'hide_followers' set and the request is authenticated with the same user",
%{conn: conn} do %{conn: conn} do
user = insert(:user, %{info: %{hide_followers: true}}) user = insert(:user, hide_followers: true)
other_user = insert(:user) other_user = insert(:user)
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
@ -764,7 +764,7 @@ test "it returns the following in a collection", %{conn: conn} do
end end
test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} do test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} do
user = insert(:user, %{info: %{hide_follows: true}}) user = insert(:user, hide_follows: true)
user_two = insert(:user) user_two = insert(:user)
User.follow(user, user_two) User.follow(user, user_two)
@ -778,7 +778,7 @@ test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} do
test "it returns a 403 error on pages, if the user has 'hide_follows' set and the request is not authenticated", test "it returns a 403 error on pages, if the user has 'hide_follows' set and the request is not authenticated",
%{conn: conn} do %{conn: conn} do
user = insert(:user, %{info: %{hide_follows: true}}) user = insert(:user, hide_follows: true)
result = result =
conn conn
@ -790,7 +790,7 @@ test "it returns a 403 error on pages, if the user has 'hide_follows' set and th
test "it renders the page, if the user has 'hide_follows' set and the request is authenticated with the same user", test "it renders the page, if the user has 'hide_follows' set and the request is authenticated with the same user",
%{conn: conn} do %{conn: conn} do
user = insert(:user, %{info: %{hide_follows: true}}) user = insert(:user, hide_follows: true)
other_user = insert(:user) other_user = insert(:user)
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user) {:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)

View file

@ -93,8 +93,8 @@ test "it returns a user" do
{:ok, user} = ActivityPub.make_user_from_ap_id(user_id) {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
assert user.ap_id == user_id assert user.ap_id == user_id
assert user.nickname == "admin@mastodon.example.org" assert user.nickname == "admin@mastodon.example.org"
assert user.info.source_data assert user.source_data
assert user.info.ap_enabled assert user.ap_enabled
assert user.follower_address == "http://mastodon.example.org/users/admin/followers" assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
end end
@ -279,7 +279,7 @@ test "does not increase user note count" do
assert activity.actor == user.ap_id assert activity.actor == user.ap_id
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
assert user.info.note_count == 0 assert user.note_count == 0
end end
test "can be fetched into a timeline" do test "can be fetched into a timeline" do
@ -342,7 +342,7 @@ test "increases user note count only for public activities" do
}) })
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
assert user.info.note_count == 2 assert user.note_count == 2
end end
test "increases replies count" do test "increases replies count" do
@ -1009,7 +1009,7 @@ test "it creates a delete activity and deletes the original object" do
end end
test "decrements user note count only for public activities" do test "decrements user note count only for public activities" do
user = insert(:user, info: %{note_count: 10}) user = insert(:user, note_count: 10)
{:ok, a1} = {:ok, a1} =
CommonAPI.post(User.get_cached_by_id(user.id), %{ CommonAPI.post(User.get_cached_by_id(user.id), %{
@ -1041,7 +1041,7 @@ test "decrements user note count only for public activities" do
{:ok, _} = Object.normalize(a4) |> ActivityPub.delete() {:ok, _} = Object.normalize(a4) |> ActivityPub.delete()
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
assert user.info.note_count == 10 assert user.note_count == 10
end end
test "it creates a delete activity and checks that it is also sent to users mentioned by the deleted object" do test "it creates a delete activity and checks that it is also sent to users mentioned by the deleted object" do
@ -1305,9 +1305,9 @@ test "detects hidden followers" do
following_address: "http://localhost:4001/users/masto_closed/following" following_address: "http://localhost:4001/users/masto_closed/following"
) )
{:ok, info} = ActivityPub.fetch_follow_information_for_user(user) {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user)
assert info.hide_followers == true assert follow_info.hide_followers == true
assert info.hide_follows == false assert follow_info.hide_follows == false
end end
test "detects hidden follows" do test "detects hidden follows" do
@ -1328,9 +1328,9 @@ test "detects hidden follows" do
following_address: "http://localhost:4001/users/masto_closed/following" following_address: "http://localhost:4001/users/masto_closed/following"
) )
{:ok, info} = ActivityPub.fetch_follow_information_for_user(user) {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user)
assert info.hide_followers == false assert follow_info.hide_followers == false
assert info.hide_follows == true assert follow_info.hide_follows == true
end end
end end
end end

View file

@ -35,7 +35,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
test "it allows posts without links" do test "it allows posts without links" do
user = insert(:user) user = insert(:user)
assert user.info.note_count == 0 assert user.note_count == 0
message = message =
@linkless_message @linkless_message
@ -47,7 +47,7 @@ test "it allows posts without links" do
test "it disallows posts with links" do test "it disallows posts with links" do
user = insert(:user) user = insert(:user)
assert user.info.note_count == 0 assert user.note_count == 0
message = message =
@linkful_message @linkful_message
@ -59,9 +59,9 @@ test "it disallows posts with links" do
describe "with old user" do describe "with old user" do
test "it allows posts without links" do test "it allows posts without links" do
user = insert(:user, info: %{note_count: 1}) user = insert(:user, note_count: 1)
assert user.info.note_count == 1 assert user.note_count == 1
message = message =
@linkless_message @linkless_message
@ -71,9 +71,9 @@ test "it allows posts without links" do
end end
test "it allows posts with links" do test "it allows posts with links" do
user = insert(:user, info: %{note_count: 1}) user = insert(:user, note_count: 1)
assert user.info.note_count == 1 assert user.note_count == 1
message = message =
@linkful_message @linkful_message
@ -85,9 +85,9 @@ test "it allows posts with links" do
describe "with followed new user" do describe "with followed new user" do
test "it allows posts without links" do test "it allows posts without links" do
user = insert(:user, info: %{follower_count: 1}) user = insert(:user, follower_count: 1)
assert user.info.follower_count == 1 assert user.follower_count == 1
message = message =
@linkless_message @linkless_message
@ -97,9 +97,9 @@ test "it allows posts without links" do
end end
test "it allows posts with links" do test "it allows posts with links" do
user = insert(:user, info: %{follower_count: 1}) user = insert(:user, follower_count: 1)
assert user.info.follower_count == 1 assert user.follower_count == 1
message = message =
@linkful_message @linkful_message
@ -133,7 +133,7 @@ test "it rejects posts with links" do
describe "with contentless-objects" do describe "with contentless-objects" do
test "it does not reject them or error out" do test "it does not reject them or error out" do
user = insert(:user, info: %{note_count: 1}) user = insert(:user, note_count: 1)
message = message =
@response_message @response_message

View file

@ -27,7 +27,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
test "it returns sharedInbox for messages involving as:Public in to" do test "it returns sharedInbox for messages involving as:Public in to" do
user = user =
insert(:user, %{ insert(:user, %{
info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}} source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
}) })
activity = %Activity{ activity = %Activity{
@ -40,7 +40,7 @@ test "it returns sharedInbox for messages involving as:Public in to" do
test "it returns sharedInbox for messages involving as:Public in cc" do test "it returns sharedInbox for messages involving as:Public in cc" do
user = user =
insert(:user, %{ insert(:user, %{
info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}} source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
}) })
activity = %Activity{ activity = %Activity{
@ -53,7 +53,7 @@ test "it returns sharedInbox for messages involving as:Public in cc" do
test "it returns sharedInbox for messages involving multiple recipients in to" do test "it returns sharedInbox for messages involving multiple recipients in to" do
user = user =
insert(:user, %{ insert(:user, %{
info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}} source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
}) })
user_two = insert(:user) user_two = insert(:user)
@ -69,7 +69,7 @@ test "it returns sharedInbox for messages involving multiple recipients in to" d
test "it returns sharedInbox for messages involving multiple recipients in cc" do test "it returns sharedInbox for messages involving multiple recipients in cc" do
user = user =
insert(:user, %{ insert(:user, %{
info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}} source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
}) })
user_two = insert(:user) user_two = insert(:user)
@ -84,14 +84,12 @@ test "it returns sharedInbox for messages involving multiple recipients in cc" d
test "it returns sharedInbox for messages involving multiple recipients in total" do test "it returns sharedInbox for messages involving multiple recipients in total" do
user = user =
insert(:user, %{ insert(:user,
info: %{
source_data: %{ source_data: %{
"inbox" => "http://example.com/personal-inbox", "inbox" => "http://example.com/personal-inbox",
"endpoints" => %{"sharedInbox" => "http://example.com/inbox"} "endpoints" => %{"sharedInbox" => "http://example.com/inbox"}
} }
} )
})
user_two = insert(:user) user_two = insert(:user)
@ -104,14 +102,12 @@ test "it returns sharedInbox for messages involving multiple recipients in total
test "it returns inbox for messages involving single recipients in total" do test "it returns inbox for messages involving single recipients in total" do
user = user =
insert(:user, %{ insert(:user,
info: %{
source_data: %{ source_data: %{
"inbox" => "http://example.com/personal-inbox", "inbox" => "http://example.com/personal-inbox",
"endpoints" => %{"sharedInbox" => "http://example.com/inbox"} "endpoints" => %{"sharedInbox" => "http://example.com/inbox"}
} }
} )
})
activity = %Activity{ activity = %Activity{
data: %{"to" => [user.ap_id], "cc" => []} data: %{"to" => [user.ap_id], "cc" => []}
@ -241,10 +237,8 @@ test "it returns inbox for messages involving single recipients in total" do
follower = follower =
insert(:user, insert(:user,
local: false, local: false,
info: %{ source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"},
ap_enabled: true, ap_enabled: true
source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"}
}
) )
actor = insert(:user, follower_address: follower.ap_id) actor = insert(:user, follower_address: follower.ap_id)
@ -278,19 +272,15 @@ test "it returns inbox for messages involving single recipients in total" do
fetcher = fetcher =
insert(:user, insert(:user,
local: false, local: false,
info: %{ source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"},
ap_enabled: true, ap_enabled: true
source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"}
}
) )
another_fetcher = another_fetcher =
insert(:user, insert(:user,
local: false, local: false,
info: %{ source_data: %{"inbox" => "https://domain2.com/users/nick1/inbox"},
ap_enabled: true, ap_enabled: true
source_data: %{"inbox" => "https://domain2.com/users/nick1/inbox"}
}
) )
actor = insert(:user) actor = insert(:user)

View file

@ -58,7 +58,7 @@ test "it works for incoming follow requests" do
end end
test "with locked accounts, it does not create a follow or an accept" do test "with locked accounts, it does not create a follow or an accept" do
user = insert(:user, info: %{locked: true}) user = insert(:user, locked: true)
data = data =
File.read!("test/fixtures/mastodon-follow-activity.json") File.read!("test/fixtures/mastodon-follow-activity.json")

View file

@ -148,7 +148,7 @@ test "it works for incoming notices" do
user = User.get_cached_by_ap_id(object_data["actor"]) user = User.get_cached_by_ap_id(object_data["actor"])
assert user.info.note_count == 1 assert user.note_count == 1
end end
test "it works for incoming notices with hashtags" do test "it works for incoming notices with hashtags" do
@ -585,7 +585,7 @@ test "it works for incoming update activities" do
} }
] ]
assert user.info.banner["url"] == [ assert user.banner["url"] == [
%{ %{
"href" => "href" =>
"https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png" "https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
@ -604,7 +604,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(activity.actor) user = User.get_cached_by_ap_id(activity.actor)
assert User.Info.fields(user.info) == [ assert User.fields(user) == [
%{"name" => "foo", "value" => "bar"}, %{"name" => "foo", "value" => "bar"},
%{"name" => "foo1", "value" => "bar1"} %{"name" => "foo1", "value" => "bar1"}
] ]
@ -625,7 +625,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(user.ap_id) user = User.get_cached_by_ap_id(user.ap_id)
assert User.Info.fields(user.info) == [ assert User.fields(user) == [
%{"name" => "foo", "value" => "updated"}, %{"name" => "foo", "value" => "updated"},
%{"name" => "foo1", "value" => "updated"} %{"name" => "foo1", "value" => "updated"}
] ]
@ -643,7 +643,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(user.ap_id) user = User.get_cached_by_ap_id(user.ap_id)
assert User.Info.fields(user.info) == [ assert User.fields(user) == [
%{"name" => "foo", "value" => "updated"}, %{"name" => "foo", "value" => "updated"},
%{"name" => "foo1", "value" => "updated"} %{"name" => "foo1", "value" => "updated"}
] ]
@ -654,7 +654,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(user.ap_id) user = User.get_cached_by_ap_id(user.ap_id)
assert User.Info.fields(user.info) == [] assert User.fields(user) == []
end end
test "it works for incoming update activities which lock the account" do test "it works for incoming update activities which lock the account" do
@ -677,7 +677,7 @@ test "it works for incoming update activities which lock the account" do
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data) {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data)
user = User.get_cached_by_ap_id(data["actor"]) user = User.get_cached_by_ap_id(data["actor"])
assert user.info.locked == true assert user.locked == true
end end
test "it works for incoming deletes" do test "it works for incoming deletes" do
@ -918,7 +918,7 @@ test "it works for incoming accepts which were pre-accepted" do
test "it works for incoming accepts which were orphaned" do test "it works for incoming accepts which were orphaned" do
follower = insert(:user) follower = insert(:user)
followed = insert(:user, %{info: %User.Info{locked: true}}) followed = insert(:user, locked: true)
{:ok, follow_activity} = ActivityPub.follow(follower, followed) {:ok, follow_activity} = ActivityPub.follow(follower, followed)
@ -940,7 +940,7 @@ test "it works for incoming accepts which were orphaned" do
test "it works for incoming accepts which are referenced by IRI only" do test "it works for incoming accepts which are referenced by IRI only" do
follower = insert(:user) follower = insert(:user)
followed = insert(:user, %{info: %User.Info{locked: true}}) followed = insert(:user, locked: true)
{:ok, follow_activity} = ActivityPub.follow(follower, followed) {:ok, follow_activity} = ActivityPub.follow(follower, followed)
@ -960,7 +960,7 @@ test "it works for incoming accepts which are referenced by IRI only" do
test "it fails for incoming accepts which cannot be correlated" do test "it fails for incoming accepts which cannot be correlated" do
follower = insert(:user) follower = insert(:user)
followed = insert(:user, %{info: %User.Info{locked: true}}) followed = insert(:user, locked: true)
accept_data = accept_data =
File.read!("test/fixtures/mastodon-accept-activity.json") File.read!("test/fixtures/mastodon-accept-activity.json")
@ -979,7 +979,7 @@ test "it fails for incoming accepts which cannot be correlated" do
test "it fails for incoming rejects which cannot be correlated" do test "it fails for incoming rejects which cannot be correlated" do
follower = insert(:user) follower = insert(:user)
followed = insert(:user, %{info: %User.Info{locked: true}}) followed = insert(:user, locked: true)
accept_data = accept_data =
File.read!("test/fixtures/mastodon-reject-activity.json") File.read!("test/fixtures/mastodon-reject-activity.json")
@ -998,7 +998,7 @@ test "it fails for incoming rejects which cannot be correlated" do
test "it works for incoming rejects which are orphaned" do test "it works for incoming rejects which are orphaned" do
follower = insert(:user) follower = insert(:user)
followed = insert(:user, %{info: %User.Info{locked: true}}) followed = insert(:user, locked: true)
{:ok, follower} = User.follow(follower, followed) {:ok, follower} = User.follow(follower, followed)
{:ok, _follow_activity} = ActivityPub.follow(follower, followed) {:ok, _follow_activity} = ActivityPub.follow(follower, followed)
@ -1024,7 +1024,7 @@ test "it works for incoming rejects which are orphaned" do
test "it works for incoming rejects which are referenced by IRI only" do test "it works for incoming rejects which are referenced by IRI only" do
follower = insert(:user) follower = insert(:user)
followed = insert(:user, %{info: %User.Info{locked: true}}) followed = insert(:user, locked: true)
{:ok, follower} = User.follow(follower, followed) {:ok, follower} = User.follow(follower, followed)
{:ok, follow_activity} = ActivityPub.follow(follower, followed) {:ok, follow_activity} = ActivityPub.follow(follower, followed)
@ -1326,18 +1326,18 @@ test "it upgrades a user to activitypub" do
assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
assert user.info.note_count == 1 assert user.note_count == 1
{:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye") {:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye")
ObanHelpers.perform_all() ObanHelpers.perform_all()
assert user.info.ap_enabled assert user.ap_enabled
assert user.info.note_count == 1 assert user.note_count == 1
assert user.follower_address == "https://niu.moe/users/rye/followers" assert user.follower_address == "https://niu.moe/users/rye/followers"
assert user.following_address == "https://niu.moe/users/rye/following" assert user.following_address == "https://niu.moe/users/rye/following"
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
assert user.info.note_count == 1 assert user.note_count == 1
activity = Activity.get_by_id(activity.id) activity = Activity.get_by_id(activity.id)
assert user.follower_address in activity.recipients assert user.follower_address in activity.recipients
@ -1358,7 +1358,7 @@ test "it upgrades a user to activitypub" do
"https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png" "https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
} }
] ]
} = user.info.banner } = user.banner
refute "..." in activity.recipients refute "..." in activity.recipients

View file

@ -297,7 +297,7 @@ test "fetches only Create activities" do
describe "update_follow_state_for_all/2" do describe "update_follow_state_for_all/2" do
test "updates the state of all Follow activities with the same actor and object" do test "updates the state of all Follow activities with the same actor and object" do
user = insert(:user, info: %{locked: true}) user = insert(:user, locked: true)
follower = insert(:user) follower = insert(:user)
{:ok, follow_activity} = ActivityPub.follow(follower, user) {:ok, follow_activity} = ActivityPub.follow(follower, user)
@ -321,7 +321,7 @@ test "updates the state of all Follow activities with the same actor and object"
describe "update_follow_state/2" do describe "update_follow_state/2" do
test "updates the state of the given follow activity" do test "updates the state of the given follow activity" do
user = insert(:user, info: %{locked: true}) user = insert(:user, locked: true)
follower = insert(:user) follower = insert(:user)
{:ok, follow_activity} = ActivityPub.follow(follower, user) {:ok, follow_activity} = ActivityPub.follow(follower, user)

View file

@ -29,7 +29,7 @@ test "Renders profile fields" do
{:ok, user} = {:ok, user} =
insert(:user) insert(:user)
|> User.upgrade_changeset(%{info: %{fields: fields}}) |> User.upgrade_changeset(%{fields: fields})
|> User.update_and_set_cache() |> User.update_and_set_cache()
assert %{ assert %{
@ -38,7 +38,7 @@ test "Renders profile fields" do
end end
test "Renders with emoji tags" do test "Renders with emoji tags" do
user = insert(:user, %{info: %{emoji: [%{"bib" => "/test"}]}}) user = insert(:user, emoji: [%{"bib" => "/test"}])
assert %{ assert %{
"tag" => [ "tag" => [
@ -64,9 +64,7 @@ test "Does not add an avatar image if the user hasn't set one" do
user = user =
insert(:user, insert(:user,
avatar: %{"url" => [%{"href" => "https://someurl"}]}, avatar: %{"url" => [%{"href" => "https://someurl"}]},
info: %{
banner: %{"url" => [%{"href" => "https://somebanner"}]} banner: %{"url" => [%{"href" => "https://somebanner"}]}
}
) )
{:ok, user} = User.ensure_keys_present(user) {:ok, user} = User.ensure_keys_present(user)
@ -121,8 +119,7 @@ test "sets totalItems to zero when followers are hidden" do
other_user = insert(:user) other_user = insert(:user)
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user}) assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
info = Map.merge(user.info, %{hide_followers_count: true, hide_followers: true}) user = Map.merge(user, %{hide_followers_count: true, hide_followers: true})
user = Map.put(user, :info, info)
assert %{"totalItems" => 0} = UserView.render("followers.json", %{user: user}) assert %{"totalItems" => 0} = UserView.render("followers.json", %{user: user})
end end
@ -131,8 +128,7 @@ test "sets correct totalItems when followers are hidden but the follower counter
other_user = insert(:user) other_user = insert(:user)
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user}) assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
info = Map.merge(user.info, %{hide_followers_count: false, hide_followers: true}) user = Map.merge(user, %{hide_followers_count: false, hide_followers: true})
user = Map.put(user, :info, info)
assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user}) assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
end end
end end
@ -143,8 +139,7 @@ test "sets totalItems to zero when follows are hidden" do
other_user = insert(:user) other_user = insert(:user)
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user) {:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user}) assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
info = Map.merge(user.info, %{hide_follows_count: true, hide_follows: true}) user = Map.merge(user, %{hide_follows_count: true, hide_follows: true})
user = Map.put(user, :info, info)
assert %{"totalItems" => 0} = UserView.render("following.json", %{user: user}) assert %{"totalItems" => 0} = UserView.render("following.json", %{user: user})
end end
@ -153,8 +148,7 @@ test "sets correct totalItems when follows are hidden but the follow counter is
other_user = insert(:user) other_user = insert(:user)
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user) {:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user}) assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
info = Map.merge(user.info, %{hide_follows_count: false, hide_follows: true}) user = Map.merge(user, %{hide_follows_count: false, hide_follows: true})
user = Map.put(user, :info, info)
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user}) assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
end end
end end

View file

@ -19,7 +19,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
describe "/api/pleroma/admin/users" do describe "/api/pleroma/admin/users" do
test "Delete" do test "Delete" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
conn = conn =
@ -40,7 +40,7 @@ test "Delete" do
end end
test "Create" do test "Create" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
conn = conn =
build_conn() build_conn()
@ -70,7 +70,7 @@ test "Create" do
end end
test "Cannot create user with exisiting email" do test "Cannot create user with exisiting email" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
conn = conn =
@ -101,7 +101,7 @@ test "Cannot create user with exisiting email" do
end end
test "Cannot create user with exisiting nickname" do test "Cannot create user with exisiting nickname" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
conn = conn =
@ -132,7 +132,7 @@ test "Cannot create user with exisiting nickname" do
end end
test "Multiple user creation works in transaction" do test "Multiple user creation works in transaction" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
conn = conn =
@ -181,7 +181,7 @@ test "Multiple user creation works in transaction" do
describe "/api/pleroma/admin/users/:nickname" do describe "/api/pleroma/admin/users/:nickname" do
test "Show", %{conn: conn} do test "Show", %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
conn = conn =
@ -204,7 +204,7 @@ test "Show", %{conn: conn} do
end end
test "when the user doesn't exist", %{conn: conn} do test "when the user doesn't exist", %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = build(:user) user = build(:user)
conn = conn =
@ -218,7 +218,7 @@ test "when the user doesn't exist", %{conn: conn} do
describe "/api/pleroma/admin/users/follow" do describe "/api/pleroma/admin/users/follow" do
test "allows to force-follow another user" do test "allows to force-follow another user" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
follower = insert(:user) follower = insert(:user)
@ -244,7 +244,7 @@ test "allows to force-follow another user" do
describe "/api/pleroma/admin/users/unfollow" do describe "/api/pleroma/admin/users/unfollow" do
test "allows to force-unfollow another user" do test "allows to force-unfollow another user" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
follower = insert(:user) follower = insert(:user)
@ -272,7 +272,7 @@ test "allows to force-unfollow another user" do
describe "PUT /api/pleroma/admin/users/tag" do describe "PUT /api/pleroma/admin/users/tag" do
setup do setup do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user1 = insert(:user, %{tags: ["x"]}) user1 = insert(:user, %{tags: ["x"]})
user2 = insert(:user, %{tags: ["y"]}) user2 = insert(:user, %{tags: ["y"]})
user3 = insert(:user, %{tags: ["unchanged"]}) user3 = insert(:user, %{tags: ["unchanged"]})
@ -321,7 +321,7 @@ test "it does not modify tags of not specified users", %{conn: conn, user3: user
describe "DELETE /api/pleroma/admin/users/tag" do describe "DELETE /api/pleroma/admin/users/tag" do
setup do setup do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user1 = insert(:user, %{tags: ["x"]}) user1 = insert(:user, %{tags: ["x"]})
user2 = insert(:user, %{tags: ["y", "z"]}) user2 = insert(:user, %{tags: ["y", "z"]})
user3 = insert(:user, %{tags: ["unchanged"]}) user3 = insert(:user, %{tags: ["unchanged"]})
@ -370,7 +370,7 @@ test "it does not modify tags of not specified users", %{conn: conn, user3: user
describe "/api/pleroma/admin/users/:nickname/permission_group" do describe "/api/pleroma/admin/users/:nickname/permission_group" do
test "GET is giving user_info" do test "GET is giving user_info" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
conn = conn =
build_conn() build_conn()
@ -385,7 +385,7 @@ test "GET is giving user_info" do
end end
test "/:right POST, can add to a permission group" do test "/:right POST, can add to a permission group" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
conn = conn =
@ -405,8 +405,8 @@ test "/:right POST, can add to a permission group" do
end end
test "/:right DELETE, can remove from a permission group" do test "/:right DELETE, can remove from a permission group" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user, info: %{is_admin: true}) user = insert(:user, is_admin: true)
conn = conn =
build_conn() build_conn()
@ -427,7 +427,7 @@ test "/:right DELETE, can remove from a permission group" do
describe "PUT /api/pleroma/admin/users/:nickname/activation_status" do describe "PUT /api/pleroma/admin/users/:nickname/activation_status" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
conn = conn =
conn conn
@ -445,7 +445,7 @@ test "deactivates the user", %{conn: conn, admin: admin} do
|> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: false}) |> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: false})
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
assert user.info.deactivated == true assert user.deactivated == true
assert json_response(conn, :no_content) assert json_response(conn, :no_content)
log_entry = Repo.one(ModerationLog) log_entry = Repo.one(ModerationLog)
@ -455,14 +455,14 @@ test "deactivates the user", %{conn: conn, admin: admin} do
end end
test "activates the user", %{conn: conn, admin: admin} do test "activates the user", %{conn: conn, admin: admin} do
user = insert(:user, info: %{deactivated: true}) user = insert(:user, deactivated: true)
conn = conn =
conn conn
|> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: true}) |> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: true})
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
assert user.info.deactivated == false assert user.deactivated == false
assert json_response(conn, :no_content) assert json_response(conn, :no_content)
log_entry = Repo.one(ModerationLog) log_entry = Repo.one(ModerationLog)
@ -485,7 +485,7 @@ test "returns 403 when requested by a non-admin", %{conn: conn} do
describe "POST /api/pleroma/admin/email_invite, with valid config" do describe "POST /api/pleroma/admin/email_invite, with valid config" do
setup do setup do
[user: insert(:user, info: %{is_admin: true})] [user: insert(:user, is_admin: true)]
end end
clear_config([:instance, :registrations_open]) do clear_config([:instance, :registrations_open]) do
@ -545,7 +545,7 @@ test "it returns 403 if requested by a non-admin", %{conn: conn} do
describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
setup do setup do
[user: insert(:user, info: %{is_admin: true})] [user: insert(:user, is_admin: true)]
end end
clear_config([:instance, :registrations_open]) clear_config([:instance, :registrations_open])
@ -577,7 +577,7 @@ test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: us
end end
test "/api/pleroma/admin/users/:nickname/password_reset" do test "/api/pleroma/admin/users/:nickname/password_reset" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
conn = conn =
@ -593,7 +593,7 @@ test "/api/pleroma/admin/users/:nickname/password_reset" do
describe "GET /api/pleroma/admin/users" do describe "GET /api/pleroma/admin/users" do
setup do setup do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
conn = conn =
build_conn() build_conn()
@ -609,7 +609,7 @@ test "renders users array for the first page", %{conn: conn, admin: admin} do
users = users =
[ [
%{ %{
"deactivated" => admin.info.deactivated, "deactivated" => admin.deactivated,
"id" => admin.id, "id" => admin.id,
"nickname" => admin.nickname, "nickname" => admin.nickname,
"roles" => %{"admin" => true, "moderator" => false}, "roles" => %{"admin" => true, "moderator" => false},
@ -619,7 +619,7 @@ test "renders users array for the first page", %{conn: conn, admin: admin} do
"display_name" => HTML.strip_tags(admin.name || admin.nickname) "display_name" => HTML.strip_tags(admin.name || admin.nickname)
}, },
%{ %{
"deactivated" => user.info.deactivated, "deactivated" => user.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname, "nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -660,7 +660,7 @@ test "regular search", %{conn: conn} do
"page_size" => 50, "page_size" => 50,
"users" => [ "users" => [
%{ %{
"deactivated" => user.info.deactivated, "deactivated" => user.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname, "nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -684,7 +684,7 @@ test "search by domain", %{conn: conn} do
"page_size" => 50, "page_size" => 50,
"users" => [ "users" => [
%{ %{
"deactivated" => user.info.deactivated, "deactivated" => user.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname, "nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -708,7 +708,7 @@ test "search by full nickname", %{conn: conn} do
"page_size" => 50, "page_size" => 50,
"users" => [ "users" => [
%{ %{
"deactivated" => user.info.deactivated, "deactivated" => user.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname, "nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -732,7 +732,7 @@ test "search by display name", %{conn: conn} do
"page_size" => 50, "page_size" => 50,
"users" => [ "users" => [
%{ %{
"deactivated" => user.info.deactivated, "deactivated" => user.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname, "nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -756,7 +756,7 @@ test "search by email", %{conn: conn} do
"page_size" => 50, "page_size" => 50,
"users" => [ "users" => [
%{ %{
"deactivated" => user.info.deactivated, "deactivated" => user.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname, "nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -780,7 +780,7 @@ test "regular search with page size", %{conn: conn} do
"page_size" => 1, "page_size" => 1,
"users" => [ "users" => [
%{ %{
"deactivated" => user.info.deactivated, "deactivated" => user.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname, "nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -799,7 +799,7 @@ test "regular search with page size", %{conn: conn} do
"page_size" => 1, "page_size" => 1,
"users" => [ "users" => [
%{ %{
"deactivated" => user2.info.deactivated, "deactivated" => user2.deactivated,
"id" => user2.id, "id" => user2.id,
"nickname" => user2.nickname, "nickname" => user2.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -813,7 +813,7 @@ test "regular search with page size", %{conn: conn} do
end end
test "only local users" do test "only local users" do
admin = insert(:user, info: %{is_admin: true}, nickname: "john") admin = insert(:user, is_admin: true, nickname: "john")
user = insert(:user, nickname: "bob") user = insert(:user, nickname: "bob")
insert(:user, nickname: "bobb", local: false) insert(:user, nickname: "bobb", local: false)
@ -828,7 +828,7 @@ test "only local users" do
"page_size" => 50, "page_size" => 50,
"users" => [ "users" => [
%{ %{
"deactivated" => user.info.deactivated, "deactivated" => user.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname, "nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -842,7 +842,7 @@ test "only local users" do
end end
test "only local users with no query", %{admin: old_admin} do test "only local users with no query", %{admin: old_admin} do
admin = insert(:user, info: %{is_admin: true}, nickname: "john") admin = insert(:user, is_admin: true, nickname: "john")
user = insert(:user, nickname: "bob") user = insert(:user, nickname: "bob")
insert(:user, nickname: "bobb", local: false) insert(:user, nickname: "bobb", local: false)
@ -855,7 +855,7 @@ test "only local users with no query", %{admin: old_admin} do
users = users =
[ [
%{ %{
"deactivated" => user.info.deactivated, "deactivated" => user.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname, "nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -865,7 +865,7 @@ test "only local users with no query", %{admin: old_admin} do
"display_name" => HTML.strip_tags(user.name || user.nickname) "display_name" => HTML.strip_tags(user.name || user.nickname)
}, },
%{ %{
"deactivated" => admin.info.deactivated, "deactivated" => admin.deactivated,
"id" => admin.id, "id" => admin.id,
"nickname" => admin.nickname, "nickname" => admin.nickname,
"roles" => %{"admin" => true, "moderator" => false}, "roles" => %{"admin" => true, "moderator" => false},
@ -895,7 +895,7 @@ test "only local users with no query", %{admin: old_admin} do
end end
test "load only admins", %{conn: conn, admin: admin} do test "load only admins", %{conn: conn, admin: admin} do
second_admin = insert(:user, info: %{is_admin: true}) second_admin = insert(:user, is_admin: true)
insert(:user) insert(:user)
insert(:user) insert(:user)
@ -934,7 +934,7 @@ test "load only admins", %{conn: conn, admin: admin} do
end end
test "load only moderators", %{conn: conn} do test "load only moderators", %{conn: conn} do
moderator = insert(:user, info: %{is_moderator: true}) moderator = insert(:user, is_moderator: true)
insert(:user) insert(:user)
insert(:user) insert(:user)
@ -999,11 +999,11 @@ test "load users with tags list", %{conn: conn} do
end end
test "it works with multiple filters" do test "it works with multiple filters" do
admin = insert(:user, nickname: "john", info: %{is_admin: true}) admin = insert(:user, nickname: "john", is_admin: true)
user = insert(:user, nickname: "bob", local: false, info: %{deactivated: true}) user = insert(:user, nickname: "bob", local: false, deactivated: true)
insert(:user, nickname: "ken", local: true, info: %{deactivated: true}) insert(:user, nickname: "ken", local: true, deactivated: true)
insert(:user, nickname: "bobb", local: false, info: %{deactivated: false}) insert(:user, nickname: "bobb", local: false, deactivated: false)
conn = conn =
build_conn() build_conn()
@ -1015,7 +1015,7 @@ test "it works with multiple filters" do
"page_size" => 50, "page_size" => 50,
"users" => [ "users" => [
%{ %{
"deactivated" => user.info.deactivated, "deactivated" => user.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname, "nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -1030,7 +1030,7 @@ test "it works with multiple filters" do
end end
test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
conn = conn =
@ -1040,7 +1040,7 @@ test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
assert json_response(conn, 200) == assert json_response(conn, 200) ==
%{ %{
"deactivated" => !user.info.deactivated, "deactivated" => !user.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname, "nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false}, "roles" => %{"admin" => false, "moderator" => false},
@ -1058,7 +1058,7 @@ test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
describe "POST /api/pleroma/admin/users/invite_token" do describe "POST /api/pleroma/admin/users/invite_token" do
setup do setup do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
conn = conn =
build_conn() build_conn()
@ -1122,7 +1122,7 @@ test "with max use and expires_at", %{conn: conn} do
describe "GET /api/pleroma/admin/users/invites" do describe "GET /api/pleroma/admin/users/invites" do
setup do setup do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
conn = conn =
build_conn() build_conn()
@ -1160,7 +1160,7 @@ test "with invite", %{conn: conn} do
describe "POST /api/pleroma/admin/users/revoke_invite" do describe "POST /api/pleroma/admin/users/revoke_invite" do
test "with token" do test "with token" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
{:ok, invite} = UserInviteToken.create_invite() {:ok, invite} = UserInviteToken.create_invite()
conn = conn =
@ -1180,7 +1180,7 @@ test "with token" do
end end
test "with invalid token" do test "with invalid token" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
conn = conn =
build_conn() build_conn()
@ -1193,7 +1193,7 @@ test "with invalid token" do
describe "GET /api/pleroma/admin/reports/:id" do describe "GET /api/pleroma/admin/reports/:id" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
%{conn: assign(conn, :user, admin)} %{conn: assign(conn, :user, admin)}
end end
@ -1226,7 +1226,7 @@ test "returns 404 when report id is invalid", %{conn: conn} do
describe "PUT /api/pleroma/admin/reports/:id" do describe "PUT /api/pleroma/admin/reports/:id" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
[reporter, target_user] = insert_pair(:user) [reporter, target_user] = insert_pair(:user)
activity = insert(:note_activity, user: target_user) activity = insert(:note_activity, user: target_user)
@ -1287,7 +1287,7 @@ test "returns 404 when report is not exist", %{conn: conn} do
describe "GET /api/pleroma/admin/reports" do describe "GET /api/pleroma/admin/reports" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
%{conn: assign(conn, :user, admin)} %{conn: assign(conn, :user, admin)}
end end
@ -1407,7 +1407,7 @@ test "returns 403 when requested by anonymous" do
# #
describe "POST /api/pleroma/admin/reports/:id/respond" do describe "POST /api/pleroma/admin/reports/:id/respond" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
%{conn: assign(conn, :user, admin), admin: admin} %{conn: assign(conn, :user, admin), admin: admin}
end end
@ -1462,7 +1462,7 @@ test "returns 404 when report id is invalid", %{conn: conn} do
describe "PUT /api/pleroma/admin/statuses/:id" do describe "PUT /api/pleroma/admin/statuses/:id" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
activity = insert(:note_activity) activity = insert(:note_activity)
%{conn: assign(conn, :user, admin), id: activity.id, admin: admin} %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
@ -1528,7 +1528,7 @@ test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
describe "DELETE /api/pleroma/admin/statuses/:id" do describe "DELETE /api/pleroma/admin/statuses/:id" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
activity = insert(:note_activity) activity = insert(:note_activity)
%{conn: assign(conn, :user, admin), id: activity.id, admin: admin} %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
@ -1558,7 +1558,7 @@ test "returns error when status is not exist", %{conn: conn} do
describe "GET /api/pleroma/admin/config" do describe "GET /api/pleroma/admin/config" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
%{conn: assign(conn, :user, admin)} %{conn: assign(conn, :user, admin)}
end end
@ -1595,7 +1595,7 @@ test "with settings in db", %{conn: conn} do
describe "POST /api/pleroma/admin/config" do describe "POST /api/pleroma/admin/config" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
temp_file = "config/test.exported_from_db.secret.exs" temp_file = "config/test.exported_from_db.secret.exs"
@ -2163,7 +2163,7 @@ test "delete part of settings by atom subkeys", %{conn: conn} do
describe "config mix tasks run" do describe "config mix tasks run" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
temp_file = "config/test.exported_from_db.secret.exs" temp_file = "config/test.exported_from_db.secret.exs"
@ -2199,7 +2199,7 @@ test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
describe "GET /api/pleroma/admin/users/:nickname/statuses" do describe "GET /api/pleroma/admin/users/:nickname/statuses" do
setup do setup do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!() date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
@ -2256,8 +2256,8 @@ test "returns private statuses with godmode on", %{conn: conn, user: user} do
describe "GET /api/pleroma/admin/moderation_log" do describe "GET /api/pleroma/admin/moderation_log" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
moderator = insert(:user, info: %{is_moderator: true}) moderator = insert(:user, is_moderator: true)
%{conn: assign(conn, :user, admin), admin: admin, moderator: moderator} %{conn: assign(conn, :user, admin), admin: admin, moderator: moderator}
end end
@ -2465,14 +2465,14 @@ test "returns log filtered by search", %{conn: conn, moderator: moderator} do
describe "PATCH /users/:nickname/force_password_reset" do describe "PATCH /users/:nickname/force_password_reset" do
setup %{conn: conn} do setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
user = insert(:user) user = insert(:user)
%{conn: assign(conn, :user, admin), admin: admin, user: user} %{conn: assign(conn, :user, admin), admin: admin, user: user}
end end
test "sets password_reset_pending to true", %{admin: admin, user: user} do test "sets password_reset_pending to true", %{admin: admin, user: user} do
assert user.info.password_reset_pending == false assert user.password_reset_pending == false
conn = conn =
build_conn() build_conn()
@ -2483,7 +2483,7 @@ test "sets password_reset_pending to true", %{admin: admin, user: user} do
ObanHelpers.perform_all() ObanHelpers.perform_all()
assert User.get_by_id(user.id).info.password_reset_pending == true assert User.get_by_id(user.id).password_reset_pending == true
end end
end end
end end

View file

@ -47,9 +47,9 @@ test "it returns local/external users" do
end end
test "it returns active/deactivated users" do test "it returns active/deactivated users" do
insert(:user, info: %{deactivated: true}) insert(:user, deactivated: true)
insert(:user, info: %{deactivated: true}) insert(:user, deactivated: true)
insert(:user, info: %{deactivated: false}) insert(:user, deactivated: false)
{:ok, _results, active_count} = {:ok, _results, active_count} =
Search.user(%{ Search.user(%{
@ -70,7 +70,7 @@ test "it returns active/deactivated users" do
test "it returns specific user" do test "it returns specific user" do
insert(:user) insert(:user)
insert(:user) insert(:user)
user = insert(:user, nickname: "bob", local: true, info: %{deactivated: false}) user = insert(:user, nickname: "bob", local: true, deactivated: false)
{:ok, _results, total_count} = Search.user(%{query: ""}) {:ok, _results, total_count} = Search.user(%{query: ""})
@ -108,7 +108,7 @@ test "it return user by full nickname" do
end end
test "it returns admin user" do test "it returns admin user" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
insert(:user) insert(:user)
insert(:user) insert(:user)
@ -119,7 +119,7 @@ test "it returns admin user" do
end end
test "it returns moderator user" do test "it returns moderator user" do
moderator = insert(:user, info: %{is_moderator: true}) moderator = insert(:user, is_moderator: true)
insert(:user) insert(:user)
insert(:user) insert(:user)

View file

@ -49,6 +49,8 @@ test "includes reported statuses" do
{:ok, report_activity} = {:ok, report_activity} =
CommonAPI.report(user, %{"account_id" => other_user.id, "status_ids" => [activity.id]}) CommonAPI.report(user, %{"account_id" => other_user.id, "status_ids" => [activity.id]})
other_user = Pleroma.User.get_by_id(other_user.id)
expected = %{ expected = %{
content: nil, content: nil,
actor: actor:

View file

@ -100,7 +100,7 @@ test "it adds emoji when updating profiles" do
{:ok, activity} = CommonAPI.update(user) {:ok, activity} = CommonAPI.update(user)
user = User.get_cached_by_ap_id(user.ap_id) user = User.get_cached_by_ap_id(user.ap_id)
[firefox] = user.info.source_data["tag"] [firefox] = user.source_data["tag"]
assert firefox["name"] == ":firefox:" assert firefox["name"] == ":firefox:"
@ -291,7 +291,7 @@ test "pin status", %{user: user, activity: activity} do
id = activity.id id = activity.id
user = refresh_record(user) user = refresh_record(user)
assert %User{info: %{pinned_activities: [^id]}} = user assert %User{pinned_activities: [^id]} = user
end end
test "unlisted statuses can be pinned", %{user: user} do test "unlisted statuses can be pinned", %{user: user} do
@ -325,7 +325,7 @@ test "unpin status", %{user: user, activity: activity} do
user = refresh_record(user) user = refresh_record(user)
assert %User{info: %{pinned_activities: []}} = user assert %User{pinned_activities: []} = user
end end
test "should unpin when deleting a status", %{user: user, activity: activity} do test "should unpin when deleting a status", %{user: user, activity: activity} do
@ -337,7 +337,7 @@ test "should unpin when deleting a status", %{user: user, activity: activity} do
user = refresh_record(user) user = refresh_record(user)
assert %User{info: %{pinned_activities: []}} = user assert %User{pinned_activities: []} = user
end end
end end
@ -468,7 +468,7 @@ test "also unsubscribes a user" do
describe "accept_follow_request/2" do describe "accept_follow_request/2" do
test "after acceptance, it sets all existing pending follow request states to 'accept'" do test "after acceptance, it sets all existing pending follow request states to 'accept'" do
user = insert(:user, info: %{locked: true}) user = insert(:user, locked: true)
follower = insert(:user) follower = insert(:user)
follower_two = insert(:user) follower_two = insert(:user)
@ -488,7 +488,7 @@ test "after acceptance, it sets all existing pending follow request states to 'a
end end
test "after rejection, it sets all existing pending follow request states to 'reject'" do test "after rejection, it sets all existing pending follow request states to 'reject'" do
user = insert(:user, info: %{locked: true}) user = insert(:user, locked: true)
follower = insert(:user) follower = insert(:user)
follower_two = insert(:user) follower_two = insert(:user)

View file

@ -81,14 +81,16 @@ test "it federates only to reachable instances via AP" do
local: false, local: false,
nickname: "nick1@domain.com", nickname: "nick1@domain.com",
ap_id: "https://domain.com/users/nick1", ap_id: "https://domain.com/users/nick1",
info: %{ap_enabled: true, source_data: %{"inbox" => inbox1}} source_data: %{"inbox" => inbox1},
ap_enabled: true
}) })
insert(:user, %{ insert(:user, %{
local: false, local: false,
nickname: "nick2@domain2.com", nickname: "nick2@domain2.com",
ap_id: "https://domain2.com/users/nick2", ap_id: "https://domain2.com/users/nick2",
info: %{ap_enabled: true, source_data: %{"inbox" => inbox2}} source_data: %{"inbox" => inbox2},
ap_enabled: true
}) })
dt = NaiveDateTime.utc_now() dt = NaiveDateTime.utc_now()
@ -162,7 +164,7 @@ test "it federates only to reachable instances via Salmon" do
local: false, local: false,
nickname: "nick1@domain.com", nickname: "nick1@domain.com",
ap_id: "https://domain.com/users/nick1", ap_id: "https://domain.com/users/nick1",
info: %{salmon: "https://domain.com/salmon"} salmon: "https://domain.com/salmon"
}) })
remote_user2 = remote_user2 =
@ -170,7 +172,7 @@ test "it federates only to reachable instances via Salmon" do
local: false, local: false,
nickname: "nick2@domain2.com", nickname: "nick2@domain2.com",
ap_id: "https://domain2.com/users/nick2", ap_id: "https://domain2.com/users/nick2",
info: %{salmon: "https://domain2.com/salmon"} salmon: "https://domain2.com/salmon"
}) })
remote_user2_id = remote_user2.id remote_user2_id = remote_user2.id

View file

@ -23,7 +23,7 @@ test "put settings", %{conn: conn} do
assert _result = json_response(conn, 200) assert _result = json_response(conn, 200)
user = User.get_cached_by_ap_id(user.ap_id) user = User.get_cached_by_ap_id(user.ap_id)
assert user.info.settings == %{"programming" => "socks"} assert user.settings == %{"programming" => "socks"}
end end
describe "index/2 redirections" do describe "index/2 redirections" do

View file

@ -153,7 +153,7 @@ test "updates the user's skip_thread_containment option", %{conn: conn} do
|> json_response(200) |> json_response(200)
assert response["pleroma"]["skip_thread_containment"] == true assert response["pleroma"]["skip_thread_containment"] == true
assert refresh_record(user).info.skip_thread_containment assert refresh_record(user).skip_thread_containment
end end
test "updates the user's hide_follows status", %{conn: conn} do test "updates the user's hide_follows status", %{conn: conn} do

View file

@ -255,7 +255,7 @@ test "getting followers", %{conn: conn} do
test "getting followers, hide_followers", %{conn: conn} do test "getting followers, hide_followers", %{conn: conn} do
user = insert(:user) user = insert(:user)
other_user = insert(:user, %{info: %{hide_followers: true}}) other_user = insert(:user, hide_followers: true)
{:ok, _user} = User.follow(user, other_user) {:ok, _user} = User.follow(user, other_user)
conn = conn =
@ -267,7 +267,7 @@ test "getting followers, hide_followers", %{conn: conn} do
test "getting followers, hide_followers, same user requesting", %{conn: conn} do test "getting followers, hide_followers, same user requesting", %{conn: conn} do
user = insert(:user) user = insert(:user)
other_user = insert(:user, %{info: %{hide_followers: true}}) other_user = insert(:user, hide_followers: true)
{:ok, _user} = User.follow(user, other_user) {:ok, _user} = User.follow(user, other_user)
conn = conn =
@ -335,7 +335,7 @@ test "getting following", %{conn: conn} do
end end
test "getting following, hide_follows", %{conn: conn} do test "getting following, hide_follows", %{conn: conn} do
user = insert(:user, %{info: %{hide_follows: true}}) user = insert(:user, hide_follows: true)
other_user = insert(:user) other_user = insert(:user)
{:ok, user} = User.follow(user, other_user) {:ok, user} = User.follow(user, other_user)
@ -347,7 +347,7 @@ test "getting following, hide_follows", %{conn: conn} do
end end
test "getting following, hide_follows, same user requesting", %{conn: conn} do test "getting following, hide_follows, same user requesting", %{conn: conn} do
user = insert(:user, %{info: %{hide_follows: true}}) user = insert(:user, hide_follows: true)
other_user = insert(:user) other_user = insert(:user)
{:ok, user} = User.follow(user, other_user) {:ok, user} = User.follow(user, other_user)
@ -669,7 +669,7 @@ test "Account registration via Application", %{conn: conn} do
token_from_db = Repo.preload(token_from_db, :user) token_from_db = Repo.preload(token_from_db, :user)
assert token_from_db.user assert token_from_db.user
assert token_from_db.user.info.confirmation_pending assert token_from_db.user.confirmation_pending
end end
test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
@ -713,7 +713,7 @@ test "rate limit", %{conn: conn} do
token_from_db = Repo.preload(token_from_db, :user) token_from_db = Repo.preload(token_from_db, :user)
assert token_from_db.user assert token_from_db.user
assert token_from_db.user.info.confirmation_pending assert token_from_db.user.confirmation_pending
end end
conn = conn =
@ -798,7 +798,7 @@ test "verify_credentials", %{conn: conn} do
end end
test "verify_credentials default scope unlisted", %{conn: conn} do test "verify_credentials default scope unlisted", %{conn: conn} do
user = insert(:user, %{info: %User.Info{default_scope: "unlisted"}}) user = insert(:user, default_scope: "unlisted")
conn = conn =
conn conn
@ -810,7 +810,7 @@ test "verify_credentials default scope unlisted", %{conn: conn} do
end end
test "locked accounts", %{conn: conn} do test "locked accounts", %{conn: conn} do
user = insert(:user, %{info: %User.Info{default_scope: "private"}}) user = insert(:user, default_scope: "private")
conn = conn =
conn conn

View file

@ -17,7 +17,7 @@ test "returns a list of conversations", %{conn: conn} do
{:ok, user_two} = User.follow(user_two, user_one) {:ok, user_two} = User.follow(user_two, user_one)
assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 0 assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
{:ok, direct} = {:ok, direct} =
CommonAPI.post(user_one, %{ CommonAPI.post(user_one, %{
@ -25,7 +25,7 @@ test "returns a list of conversations", %{conn: conn} do
"visibility" => "direct" "visibility" => "direct"
}) })
assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 1 assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1
{:ok, _follower_only} = {:ok, _follower_only} =
CommonAPI.post(user_one, %{ CommonAPI.post(user_one, %{
@ -56,7 +56,7 @@ test "returns a list of conversations", %{conn: conn} do
assert is_binary(res_id) assert is_binary(res_id)
assert unread == true assert unread == true
assert res_last_status["id"] == direct.id assert res_last_status["id"] == direct.id
assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1
end end
test "updates the last_status on reply", %{conn: conn} do test "updates the last_status on reply", %{conn: conn} do
@ -107,7 +107,7 @@ test "the user marks a conversation as read", %{conn: conn} do
|> post("/api/v1/conversations/#{direct_conversation_id}/read") |> post("/api/v1/conversations/#{direct_conversation_id}/read")
|> json_response(200) |> json_response(200)
assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 0 assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0
# The conversation is marked as unread on reply # The conversation is marked as unread on reply
{:ok, _} = {:ok, _} =
@ -123,7 +123,7 @@ test "the user marks a conversation as read", %{conn: conn} do
|> get("/api/v1/conversations") |> get("/api/v1/conversations")
|> json_response(200) |> json_response(200)
assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1
# A reply doesn't increment the user's unread_conversation_count if the conversation is unread # A reply doesn't increment the user's unread_conversation_count if the conversation is unread
{:ok, _} = {:ok, _} =
@ -133,7 +133,7 @@ test "the user marks a conversation as read", %{conn: conn} do
"in_reply_to_status_id" => direct.id "in_reply_to_status_id" => direct.id
}) })
assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1
end end
test "(vanilla) Mastodon frontend behaviour", %{conn: conn} do test "(vanilla) Mastodon frontend behaviour", %{conn: conn} do

View file

@ -12,7 +12,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
describe "locked accounts" do describe "locked accounts" do
test "/api/v1/follow_requests works" do test "/api/v1/follow_requests works" do
user = insert(:user, %{info: %User.Info{locked: true}}) user = insert(:user, locked: true)
other_user = insert(:user) other_user = insert(:user)
{:ok, _activity} = ActivityPub.follow(other_user, user) {:ok, _activity} = ActivityPub.follow(other_user, user)
@ -32,7 +32,7 @@ test "/api/v1/follow_requests works" do
end end
test "/api/v1/follow_requests/:id/authorize works" do test "/api/v1/follow_requests/:id/authorize works" do
user = insert(:user, %{info: %User.Info{locked: true}}) user = insert(:user, locked: true)
other_user = insert(:user) other_user = insert(:user)
{:ok, _activity} = ActivityPub.follow(other_user, user) {:ok, _activity} = ActivityPub.follow(other_user, user)
@ -57,7 +57,7 @@ test "/api/v1/follow_requests/:id/authorize works" do
end end
test "/api/v1/follow_requests/:id/reject works" do test "/api/v1/follow_requests/:id/reject works" do
user = insert(:user, %{info: %User.Info{locked: true}}) user = insert(:user, locked: true)
other_user = insert(:user) other_user = insert(:user)
{:ok, _activity} = ActivityPub.follow(other_user, user) {:ok, _activity} = ActivityPub.follow(other_user, user)

View file

@ -41,20 +41,13 @@ test "get instance stats", %{conn: conn} do
user = insert(:user, %{local: true}) user = insert(:user, %{local: true})
user2 = insert(:user, %{local: true}) user2 = insert(:user, %{local: true})
{:ok, _user2} = User.deactivate(user2, !user2.info.deactivated) {:ok, _user2} = User.deactivate(user2, !user2.deactivated)
insert(:user, %{local: false, nickname: "u@peer1.com"}) insert(:user, %{local: false, nickname: "u@peer1.com"})
insert(:user, %{local: false, nickname: "u@peer2.com"}) insert(:user, %{local: false, nickname: "u@peer2.com"})
{:ok, _} = Pleroma.Web.CommonAPI.post(user, %{"status" => "cofe"}) {:ok, _} = Pleroma.Web.CommonAPI.post(user, %{"status" => "cofe"})
# Stats should count users with missing or nil `info.deactivated` value
{:ok, _user} =
user.id
|> User.get_cached_by_id()
|> User.update_info(&Ecto.Changeset.change(&1, %{deactivated: nil}))
Pleroma.Stats.force_update() Pleroma.Stats.force_update()
conn = get(conn, "/api/v1/instance") conn = get(conn, "/api/v1/instance")

View file

@ -526,8 +526,8 @@ test "when you didn't create it", %{conn: conn} do
test "when you're an admin or moderator", %{conn: conn} do test "when you're an admin or moderator", %{conn: conn} do
activity1 = insert(:note_activity) activity1 = insert(:note_activity)
activity2 = insert(:note_activity) activity2 = insert(:note_activity)
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
moderator = insert(:user, info: %{is_moderator: true}) moderator = insert(:user, is_moderator: true)
res_conn = res_conn =
conn conn

View file

@ -14,11 +14,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPITest do
import Pleroma.Factory import Pleroma.Factory
describe "follow/3" do describe "follow/3" do
test "returns error when user deactivated" do test "returns error when followed user is deactivated" do
follower = insert(:user) follower = insert(:user)
user = insert(:user, local: true, info: %{deactivated: true}) user = insert(:user, local: true, deactivated: true)
{:error, error} = MastodonAPI.follow(follower, user) {:error, error} = MastodonAPI.follow(follower, user)
assert error == "Could not follow user: You are deactivated." assert error == "Could not follow user: #{user.nickname} is deactivated."
end end
test "following for user" do test "following for user" do

View file

@ -26,12 +26,10 @@ test "Represent a user account" do
user = user =
insert(:user, %{ insert(:user, %{
info: %{
note_count: 5,
follower_count: 3, follower_count: 3,
note_count: 5,
source_data: source_data, source_data: source_data,
background: background_image background: background_image,
},
nickname: "shp@shitposter.club", nickname: "shp@shitposter.club",
name: ":karjalanpiirakka: shp", name: ":karjalanpiirakka: shp",
bio: "<script src=\"invalid-html\"></script><span>valid html</span>", bio: "<script src=\"invalid-html\"></script><span>valid html</span>",
@ -101,7 +99,7 @@ test "Represent the user account for the account owner" do
"non_followers" => true "non_followers" => true
} }
privacy = user.info.default_scope privacy = user.default_scope
assert %{ assert %{
pleroma: %{notification_settings: ^notification_settings}, pleroma: %{notification_settings: ^notification_settings},
@ -112,7 +110,9 @@ test "Represent the user account for the account owner" do
test "Represent a Service(bot) account" do test "Represent a Service(bot) account" do
user = user =
insert(:user, %{ insert(:user, %{
info: %{note_count: 5, follower_count: 3, source_data: %{"type" => "Service"}}, follower_count: 3,
note_count: 5,
source_data: %{"type" => "Service"},
nickname: "shp@shitposter.club", nickname: "shp@shitposter.club",
inserted_at: ~N[2017-08-15 15:47:06.597036] inserted_at: ~N[2017-08-15 15:47:06.597036]
}) })
@ -164,8 +164,8 @@ test "Represent a Service(bot) account" do
end end
test "Represent a deactivated user for an admin" do test "Represent a deactivated user for an admin" do
admin = insert(:user, %{info: %{is_admin: true}}) admin = insert(:user, is_admin: true)
deactivated_user = insert(:user, %{info: %{deactivated: true}}) deactivated_user = insert(:user, deactivated: true)
represented = AccountView.render("show.json", %{user: deactivated_user, for: admin}) represented = AccountView.render("show.json", %{user: deactivated_user, for: admin})
assert represented[:pleroma][:deactivated] == true assert represented[:pleroma][:deactivated] == true
end end
@ -253,7 +253,7 @@ test "represent a relationship for the user blocking a domain" do
test "represent a relationship for the user with a pending follow request" do test "represent a relationship for the user with a pending follow request" do
user = insert(:user) user = insert(:user)
other_user = insert(:user, %{info: %User.Info{locked: true}}) other_user = insert(:user, locked: true)
{:ok, user, other_user, _} = CommonAPI.follow(user, other_user) {:ok, user, other_user, _} = CommonAPI.follow(user, other_user)
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
@ -282,7 +282,9 @@ test "represent a relationship for the user with a pending follow request" do
test "represent an embedded relationship" do test "represent an embedded relationship" do
user = user =
insert(:user, %{ insert(:user, %{
info: %{note_count: 5, follower_count: 0, source_data: %{"type" => "Service"}}, follower_count: 0,
note_count: 5,
source_data: %{"type" => "Service"},
nickname: "shp@shitposter.club", nickname: "shp@shitposter.club",
inserted_at: ~N[2017-08-15 15:47:06.597036] inserted_at: ~N[2017-08-15 15:47:06.597036]
}) })
@ -352,7 +354,7 @@ test "represent an embedded relationship" do
end end
test "returns the settings store if the requesting user is the represented user and it's requested specifically" do test "returns the settings store if the requesting user is the represented user and it's requested specifically" do
user = insert(:user, %{info: %User.Info{pleroma_settings_store: %{fe: "test"}}}) user = insert(:user, pleroma_settings_store: %{fe: "test"})
result = result =
AccountView.render("show.json", %{user: user, for: user, with_pleroma_settings: true}) AccountView.render("show.json", %{user: user, for: user, with_pleroma_settings: true})
@ -374,14 +376,13 @@ test "sanitizes display names" do
describe "hiding follows/following" do describe "hiding follows/following" do
test "shows when follows/followers stats are hidden and sets follow/follower count to 0" do test "shows when follows/followers stats are hidden and sets follow/follower count to 0" do
info = %{ user =
insert(:user, %{
hide_followers: true, hide_followers: true,
hide_followers_count: true, hide_followers_count: true,
hide_follows: true, hide_follows: true,
hide_follows_count: true hide_follows_count: true
} })
user = insert(:user, info: info)
other_user = insert(:user) other_user = insert(:user)
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user) {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
@ -395,7 +396,7 @@ test "shows when follows/followers stats are hidden and sets follow/follower cou
end end
test "shows when follows/followers are hidden" do test "shows when follows/followers are hidden" do
user = insert(:user, info: %{hide_followers: true, hide_follows: true}) user = insert(:user, hide_followers: true, hide_follows: true)
other_user = insert(:user) other_user = insert(:user)
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user) {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
@ -408,7 +409,7 @@ test "shows when follows/followers are hidden" do
end end
test "shows actual follower/following count to the account owner" do test "shows actual follower/following count to the account owner" do
user = insert(:user, info: %{hide_followers: true, hide_follows: true}) user = insert(:user, hide_followers: true, hide_follows: true)
other_user = insert(:user) other_user = insert(:user)
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user) {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
@ -456,7 +457,7 @@ test "shows zero when no follow requests are pending" do
end end
test "shows non-zero when follow requests are pending" do test "shows non-zero when follow requests are pending" do
user = insert(:user, %{info: %{locked: true}}) user = insert(:user, locked: true)
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user}) assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
@ -468,7 +469,7 @@ test "shows non-zero when follow requests are pending" do
end end
test "decreases when accepting a follow request" do test "decreases when accepting a follow request" do
user = insert(:user, %{info: %{locked: true}}) user = insert(:user, locked: true)
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user}) assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
@ -485,7 +486,7 @@ test "decreases when accepting a follow request" do
end end
test "decreases when rejecting a follow request" do test "decreases when rejecting a follow request" do
user = insert(:user, %{info: %{locked: true}}) user = insert(:user, locked: true)
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user}) assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
@ -502,14 +503,14 @@ test "decreases when rejecting a follow request" do
end end
test "shows non-zero when historical unapproved requests are present" do test "shows non-zero when historical unapproved requests are present" do
user = insert(:user, %{info: %{locked: true}}) user = insert(:user, locked: true)
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user}) assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
other_user = insert(:user) other_user = insert(:user)
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
{:ok, user} = User.update_info(user, &User.Info.user_upgrade(&1, %{locked: false})) {:ok, user} = User.update_and_set_cache(user, %{locked: false})
assert %{locked: false, follow_requests_count: 1} = assert %{locked: false, follow_requests_count: 1} =
AccountView.render("show.json", %{user: user, for: user}) AccountView.render("show.json", %{user: user, for: user})

View file

@ -24,8 +24,8 @@ test "GET /.well-known/nodeinfo", %{conn: conn} do
end end
test "nodeinfo shows staff accounts", %{conn: conn} do test "nodeinfo shows staff accounts", %{conn: conn} do
moderator = insert(:user, %{local: true, info: %{is_moderator: true}}) moderator = insert(:user, local: true, is_moderator: true)
admin = insert(:user, %{local: true, info: %{is_admin: true}}) admin = insert(:user, local: true, is_admin: true)
conn = conn =
conn conn

View file

@ -780,8 +780,8 @@ test "rejects token exchange for valid credentials belonging to unconfirmed user
{:ok, user} = {:ok, user} =
insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password)) insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password))
|> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true)) |> User.confirmation_changeset(need_confirmation: true)
|> Repo.update() |> User.update_and_set_cache()
refute Pleroma.User.auth_active?(user) refute Pleroma.User.auth_active?(user)
@ -808,7 +808,7 @@ test "rejects token exchange for valid credentials belonging to deactivated user
user = user =
insert(:user, insert(:user,
password_hash: Comeonin.Pbkdf2.hashpwsalt(password), password_hash: Comeonin.Pbkdf2.hashpwsalt(password),
info: %{deactivated: true} deactivated: true
) )
app = insert(:oauth_app) app = insert(:oauth_app)
@ -834,7 +834,7 @@ test "rejects token exchange for user with password_reset_pending set to true" d
user = user =
insert(:user, insert(:user,
password_hash: Comeonin.Pbkdf2.hashpwsalt(password), password_hash: Comeonin.Pbkdf2.hashpwsalt(password),
info: %{password_reset_pending: true} password_reset_pending: true
) )
app = insert(:oauth_app, scopes: ["read", "write"]) app = insert(:oauth_app, scopes: ["read", "write"])

View file

@ -51,7 +51,7 @@ test "decodes a salmon with a changed magic key", %{conn: conn} do
end) =~ "[error]" end) =~ "[error]"
# Wrong key # Wrong key
info = %{ update_params = %{
magic_key: magic_key:
"RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB" "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB"
} }
@ -59,7 +59,8 @@ test "decodes a salmon with a changed magic key", %{conn: conn} do
# Set a wrong magic-key for a user so it has to refetch # Set a wrong magic-key for a user so it has to refetch
"http://gs.example.org:4040/index.php/user/1" "http://gs.example.org:4040/index.php/user/1"
|> User.get_cached_by_ap_id() |> User.get_cached_by_ap_id()
|> User.update_info(&User.Info.remote_user_creation(&1, info)) |> User.update_changeset(update_params)
|> User.update_and_set_cache()
assert capture_log(fn -> assert capture_log(fn ->
conn = conn =

View file

@ -33,7 +33,7 @@ test "handle incoming note - GS, Salmon" do
object = Object.normalize(activity) object = Object.normalize(activity)
user = User.get_cached_by_ap_id(activity.data["actor"]) user = User.get_cached_by_ap_id(activity.data["actor"])
assert user.info.note_count == 1 assert user.note_count == 1
assert activity.data["type"] == "Create" assert activity.data["type"] == "Create"
assert object.data["type"] == "Note" assert object.data["type"] == "Note"
@ -328,7 +328,7 @@ test "handle incoming follows" do
test "refuse following over OStatus if the followed's account is locked" do test "refuse following over OStatus if the followed's account is locked" do
incoming = File.read!("test/fixtures/follow.xml") incoming = File.read!("test/fixtures/follow.xml")
_user = insert(:user, info: %{locked: true}, ap_id: "https://pawoo.net/users/pekorino") _user = insert(:user, locked: true, ap_id: "https://pawoo.net/users/pekorino")
{:ok, [{:error, "It's not possible to follow locked accounts over OStatus"}]} = {:ok, [{:error, "It's not possible to follow locked accounts over OStatus"}]} =
OStatus.handle_incoming(incoming) OStatus.handle_incoming(incoming)
@ -392,7 +392,7 @@ test "tries to use the information in poco fields" do
assert user.name == "Constance Variable" assert user.name == "Constance Variable"
assert user.nickname == "lambadalambda@social.heldscal.la" assert user.nickname == "lambadalambda@social.heldscal.la"
assert user.local == false assert user.local == false
assert user.info.uri == uri assert user.uri == uri
assert user.ap_id == uri assert user.ap_id == uri
assert user.bio == "Call me Deacon Blues." assert user.bio == "Call me Deacon Blues."
assert user.avatar["type"] == "Image" assert user.avatar["type"] == "Image"
@ -402,36 +402,34 @@ test "tries to use the information in poco fields" do
assert user == user_again assert user == user_again
end end
test "find_or_make_user sets all the nessary input fields" do test "find_or_make_user sets all the necessary input fields" do
uri = "https://social.heldscal.la/user/23211" uri = "https://social.heldscal.la/user/23211"
{:ok, user} = OStatus.find_or_make_user(uri) {:ok, user} = OStatus.find_or_make_user(uri)
assert user.info == assert user.ap_enabled == false
%User.Info{ assert user.background == %{}
id: user.info.id, assert user.banner == %{}
ap_enabled: false, assert user.blocks == []
background: %{}, assert user.deactivated == false
banner: %{}, assert user.default_scope == "public"
blocks: [], assert user.domain_blocks == []
deactivated: false, assert user.follower_count == 0
default_scope: "public", assert user.is_admin == false
domain_blocks: [], assert user.is_moderator == false
follower_count: 0, assert user.is_moderator == false
is_admin: false, assert is_nil(user.keys)
is_moderator: false, assert user.locked == false
keys: nil,
locked: false, assert user.magic_key ==
no_rich_text: false, "RSA.uzg6r1peZU0vXGADWxGJ0PE34WvmhjUmydbX5YYdOiXfODVLwCMi1umGoqUDm-mRu4vNEdFBVJU1CpFA7dKzWgIsqsa501i2XqElmEveXRLvNRWFB6nG03Q5OUY2as8eE54BJm0p20GkMfIJGwP6TSFb-ICp3QjzbatuSPJ6xCE=.AQAB"
note_count: 0,
settings: nil, assert user.no_rich_text == false
source_data: %{}, assert user.note_count == 0
hub: "https://social.heldscal.la/main/push/hub", assert is_nil(user.settings)
magic_key: assert user.hub == "https://social.heldscal.la/main/push/hub"
"RSA.uzg6r1peZU0vXGADWxGJ0PE34WvmhjUmydbX5YYdOiXfODVLwCMi1umGoqUDm-mRu4vNEdFBVJU1CpFA7dKzWgIsqsa501i2XqElmEveXRLvNRWFB6nG03Q5OUY2as8eE54BJm0p20GkMfIJGwP6TSFb-ICp3QjzbatuSPJ6xCE=.AQAB", assert user.salmon == "https://social.heldscal.la/main/salmon/user/23211"
salmon: "https://social.heldscal.la/main/salmon/user/23211", assert user.topic == "https://social.heldscal.la/api/statuses/user_timeline/23211.atom"
topic: "https://social.heldscal.la/api/statuses/user_timeline/23211.atom", assert user.uri == "https://social.heldscal.la/user/23211"
uri: "https://social.heldscal.la/user/23211"
}
end end
test "find_make_or_update_actor takes an author element and returns an updated user" do test "find_make_or_update_actor takes an author element and returns an updated user" do
@ -465,7 +463,7 @@ test "find_or_make_user disallows protocol downgrade" do
user = user =
insert(:user, %{ insert(:user, %{
ap_id: "https://social.heldscal.la/user/23211", ap_id: "https://social.heldscal.la/user/23211",
info: %{ap_enabled: true}, ap_enabled: true,
local: false local: false
}) })
@ -484,7 +482,7 @@ test "find_make_or_update_actor disallows protocol downgrade" do
user = user =
insert(:user, %{ insert(:user, %{
ap_id: "https://social.heldscal.la/user/23211", ap_id: "https://social.heldscal.la/user/23211",
info: %{ap_enabled: true}, ap_enabled: true,
local: false local: false
}) })

View file

@ -6,7 +6,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
use Pleroma.Web.ConnCase use Pleroma.Web.ConnCase
alias Pleroma.Config alias Pleroma.Config
alias Pleroma.Repo
alias Pleroma.Tests.ObanHelpers alias Pleroma.Tests.ObanHelpers
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
@ -20,10 +19,10 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
setup do setup do
{:ok, user} = {:ok, user} =
insert(:user) insert(:user)
|> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true)) |> User.confirmation_changeset(need_confirmation: true)
|> Repo.update() |> User.update_and_set_cache()
assert user.info.confirmation_pending assert user.confirmation_pending
[user: user] [user: user]
end end
@ -105,7 +104,7 @@ test "can set profile banner", %{conn: conn} do
|> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image}) |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})
user = refresh_record(user) user = refresh_record(user)
assert user.info.banner["type"] == "Image" assert user.banner["type"] == "Image"
assert %{"url" => _} = json_response(conn, 200) assert %{"url" => _} = json_response(conn, 200)
end end
@ -119,7 +118,7 @@ test "can reset profile banner", %{conn: conn} do
|> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""}) |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})
user = refresh_record(user) user = refresh_record(user)
assert user.info.banner == %{} assert user.banner == %{}
assert %{"url" => nil} = json_response(conn, 200) assert %{"url" => nil} = json_response(conn, 200)
end end
@ -135,7 +134,7 @@ test "background image can be set", %{conn: conn} do
|> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image}) |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image})
user = refresh_record(user) user = refresh_record(user)
assert user.info.background["type"] == "Image" assert user.background["type"] == "Image"
assert %{"url" => _} = json_response(conn, 200) assert %{"url" => _} = json_response(conn, 200)
end end
@ -148,14 +147,14 @@ test "background image can be reset", %{conn: conn} do
|> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""}) |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""})
user = refresh_record(user) user = refresh_record(user)
assert user.info.background == %{} assert user.background == %{}
assert %{"url" => nil} = json_response(conn, 200) assert %{"url" => nil} = json_response(conn, 200)
end end
end end
describe "getting favorites timeline of specified user" do describe "getting favorites timeline of specified user" do
setup do setup do
[current_user, user] = insert_pair(:user, %{info: %{hide_favorites: false}}) [current_user, user] = insert_pair(:user, hide_favorites: false)
[current_user: current_user, user: user] [current_user: current_user, user: user]
end end
@ -319,7 +318,7 @@ test "returns 403 error when user has hidden own favorites", %{
conn: conn, conn: conn,
current_user: current_user current_user: current_user
} do } do
user = insert(:user, %{info: %{hide_favorites: true}}) user = insert(:user, hide_favorites: true)
activity = insert(:note_activity) activity = insert(:note_activity)
CommonAPI.favorite(activity.id, user) CommonAPI.favorite(activity.id, user)
@ -341,7 +340,7 @@ test "hides favorites for new users by default", %{conn: conn, current_user: cur
|> assign(:user, current_user) |> assign(:user, current_user)
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites") |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
assert user.info.hide_favorites assert user.hide_favorites
assert json_response(conn, 403) == %{"error" => "Can't get favorites"} assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
end end
end end

View file

@ -38,7 +38,7 @@ test "shared & non-shared pack information in list_packs is ok" do
end end
test "listing remote packs" do test "listing remote packs" do
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
conn = build_conn() |> assign(:user, admin) conn = build_conn() |> assign(:user, admin)
resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200) resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
@ -121,7 +121,7 @@ test "downloading shared & unshared packs from another instance via download_fro
text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip")) text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip"))
end) end)
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
conn = build_conn() |> assign(:user, admin) conn = build_conn() |> assign(:user, admin)
@ -206,7 +206,7 @@ test "downloading shared & unshared packs from another instance via download_fro
end) end)
{:ok, {:ok,
admin: insert(:user, info: %{is_admin: true}), admin: insert(:user, is_admin: true),
pack_file: pack_file, pack_file: pack_file,
new_data: %{ new_data: %{
"license" => "Test license changed", "license" => "Test license changed",
@ -303,7 +303,7 @@ test "updating pack files" do
File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2") File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2")
end) end)
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
conn = build_conn() conn = build_conn()
@ -391,7 +391,7 @@ test "creating and deleting a pack" do
File.rm_rf!("#{@emoji_dir_path}/test_created") File.rm_rf!("#{@emoji_dir_path}/test_created")
end) end)
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
conn = build_conn() |> assign(:user, admin) conn = build_conn() |> assign(:user, admin)
@ -431,7 +431,7 @@ test "filesystem import" do
refute Map.has_key?(resp, "test_pack_for_import") refute Map.has_key?(resp, "test_pack_for_import")
admin = insert(:user, info: %{is_admin: true}) admin = insert(:user, is_admin: true)
assert conn assert conn
|> assign(:user, admin) |> assign(:user, admin)

View file

@ -71,9 +71,7 @@ test "it gets a magic key" do
[:passthrough], [:passthrough],
[] do [] do
user_data = %{ user_data = %{
info: %{ salmon: "http://test-example.org/salmon",
salmon: "http://test-example.org/salmon"
},
local: false local: false
} }

View file

@ -213,7 +213,7 @@ test "it sends message if recipients invalid and thread containment is disabled"
test "it sends message if recipients invalid and thread containment is enabled but user's thread containment is disabled" do test "it sends message if recipients invalid and thread containment is enabled but user's thread containment is disabled" do
Pleroma.Config.put([:instance, :skip_thread_containment], false) Pleroma.Config.put([:instance, :skip_thread_containment], false)
author = insert(:user) author = insert(:user)
user = insert(:user, following: [author.ap_id], info: %{skip_thread_containment: true}) user = insert(:user, following: [author.ap_id], skip_thread_containment: true)
activity = activity =
insert(:note_activity, insert(:note_activity,

View file

@ -59,7 +59,7 @@ test "it returns HTTP 200", %{conn: conn} do
end end
test "it sets password_reset_pending to false", %{conn: conn} do test "it sets password_reset_pending to false", %{conn: conn} do
user = insert(:user, info: %{password_reset_pending: true}) user = insert(:user, password_reset_pending: true)
{:ok, token} = PasswordResetToken.create_token(user) {:ok, token} = PasswordResetToken.create_token(user)
{:ok, _access_token} = Token.create_token(insert(:oauth_app), user, %{}) {:ok, _access_token} = Token.create_token(insert(:oauth_app), user, %{})
@ -75,7 +75,7 @@ test "it sets password_reset_pending to false", %{conn: conn} do
|> post("/api/pleroma/password_reset", %{data: params}) |> post("/api/pleroma/password_reset", %{data: params})
|> html_response(:ok) |> html_response(:ok)
assert User.get_by_id(user.id).info.password_reset_pending == false assert User.get_by_id(user.id).password_reset_pending == false
end end
end end
end end

View file

@ -71,7 +71,7 @@ test "it sends confirmation email if :account_activation_required is specified i
{:ok, user} = TwitterAPI.register_user(data) {:ok, user} = TwitterAPI.register_user(data)
ObanHelpers.perform_all() ObanHelpers.perform_all()
assert user.info.confirmation_pending assert user.confirmation_pending
email = Pleroma.Emails.UserEmail.account_confirmation_email(user) email = Pleroma.Emails.UserEmail.account_confirmation_email(user)

View file

@ -164,7 +164,7 @@ test "it updates notification settings", %{conn: conn} do
"follows" => true, "follows" => true,
"non_follows" => true, "non_follows" => true,
"non_followers" => true "non_followers" => true
} == user.info.notification_settings } == user.notification_settings
end end
end end
@ -370,7 +370,7 @@ test "follows user", %{conn: conn} do
end end
test "returns error when user is deactivated", %{conn: conn} do test "returns error when user is deactivated", %{conn: conn} do
user = insert(:user, info: %{deactivated: true}) user = insert(:user, deactivated: true)
user2 = insert(:user) user2 = insert(:user)
response = response =
@ -568,7 +568,7 @@ test "it returns HTTP 200", %{conn: conn} do
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
assert user.info.deactivated == true assert user.deactivated == true
end end
test "it returns returns when password invalid", %{conn: conn} do test "it returns returns when password invalid", %{conn: conn} do
@ -583,7 +583,7 @@ test "it returns returns when password invalid", %{conn: conn} do
assert response == %{"error" => "Invalid password."} assert response == %{"error" => "Invalid password."}
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
refute user.info.deactivated refute user.deactivated
end end
end end

View file

@ -109,7 +109,7 @@ def accepting_verifier(subscription) do
test "initiate a subscription for a given user and topic" do test "initiate a subscription for a given user and topic" do
subscriber = insert(:user) subscriber = insert(:user)
user = insert(:user, %{info: %Pleroma.User.Info{topic: "some_topic", hub: "some_hub"}}) user = insert(:user, topic: "some_topic", hub: "some_hub")
{:ok, websub} = Websub.subscribe(subscriber, user, &accepting_verifier/1) {:ok, websub} = Websub.subscribe(subscriber, user, &accepting_verifier/1)
assert websub.subscribers == [subscriber.ap_id] assert websub.subscribers == [subscriber.ap_id]