X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fuser.ex;h=6abcb7288f5f3237a80cb212409656430cc153ef;hb=ad5263c647aea65dbeb4c329825671895e0a8863;hp=417d57d727c5b8025bd9afa12f6b9c87c56bfe00;hpb=ac3a3abf6bfae5a6217e0a212abd6be0b4a17309;p=akkoma diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 417d57d72..6abcb7288 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -10,6 +10,7 @@ defmodule Pleroma.User do alias Comeonin.Pbkdf2 alias Pleroma.Activity + alias Pleroma.Keys alias Pleroma.Notification alias Pleroma.Object alias Pleroma.Registration @@ -55,7 +56,7 @@ defmodule Pleroma.User do field(:last_refreshed_at, :naive_datetime_usec) has_many(:notifications, Notification) has_many(:registrations, Registration) - embeds_one(:info, Pleroma.User.Info) + embeds_one(:info, User.Info) timestamps() end @@ -105,10 +106,8 @@ defmodule Pleroma.User do def ap_followers(%User{} = user), do: "#{ap_id(user)}/followers" def user_info(%User{} = user) do - oneself = if user.local, do: 1, else: 0 - %{ - following_count: length(user.following) - oneself, + following_count: following_count(user), note_count: user.info.note_count, follower_count: user.info.follower_count, locked: user.info.locked, @@ -117,6 +116,20 @@ defmodule Pleroma.User do } end + def restrict_deactivated(query) do + from(u in query, + where: not fragment("? \\? 'deactivated' AND ?->'deactivated' @> 'true'", u.info, u.info) + ) + end + + def following_count(%User{following: []}), do: 0 + + def following_count(%User{} = user) do + user + |> get_friends_query() + |> Repo.aggregate(:count, :id) + end + def remote_user_creation(params) do params = params @@ -154,7 +167,7 @@ defmodule Pleroma.User do def update_changeset(struct, params \\ %{}) do struct - |> cast(params, [:bio, :name, :avatar]) + |> cast(params, [:bio, :name, :avatar, :following]) |> unique_constraint(:nickname) |> validate_format(:nickname, local_nickname_regex()) |> validate_length(:bio, max: 5000) @@ -221,7 +234,7 @@ defmodule Pleroma.User do |> validate_confirmation(:password) |> unique_constraint(:email) |> unique_constraint(:nickname) - |> validate_exclusion(:nickname, Pleroma.Config.get([Pleroma.User, :restricted_nicknames])) + |> validate_exclusion(:nickname, Pleroma.Config.get([User, :restricted_nicknames])) |> validate_format(:nickname, local_nickname_regex()) |> validate_format(:email, @email_regex) |> validate_length(:bio, max: 1000) @@ -255,7 +268,7 @@ defmodule Pleroma.User do candidates = Pleroma.Config.get([:instance, :autofollowed_nicknames]) autofollowed_users = - User.Query.build(%{nickname: candidates, local: true}) + User.Query.build(%{nickname: candidates, local: true, deactivated: false}) |> Repo.all() follow_all(user, autofollowed_users) @@ -264,9 +277,15 @@ defmodule Pleroma.User do @doc "Inserts provided changeset, performs post-registration actions (confirmation email sending etc.)" def register(%Ecto.Changeset{} = changeset) do with {:ok, user} <- Repo.insert(changeset), - {:ok, user} <- autofollow_users(user), + {:ok, user} <- post_register_action(user) do + {:ok, user} + end + end + + def post_register_action(%User{} = user) do + with {:ok, user} <- autofollow_users(user), {:ok, user} <- set_cache(user), - {:ok, _} <- Pleroma.User.WelcomeMessage.post_welcome_message_to_user(user), + {:ok, _} <- User.WelcomeMessage.post_welcome_message_to_user(user), {:ok, _} <- try_send_confirmation_email(user) do {:ok, user} end @@ -353,9 +372,7 @@ defmodule Pleroma.User do end def follow(%User{} = follower, %User{info: info} = followed) do - user_config = Application.get_env(:pleroma, :user) - deny_follow_blocked = Keyword.get(user_config, :deny_follow_blocked) - + deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked]) ap_followers = followed.follower_address cond do @@ -550,7 +567,7 @@ defmodule Pleroma.User do @spec get_followers_query(User.t(), pos_integer() | nil) :: Ecto.Query.t() def get_followers_query(%User{} = user, nil) do - User.Query.build(%{followers: user}) + User.Query.build(%{followers: user, deactivated: false}) end def get_followers_query(user, page) do @@ -575,7 +592,7 @@ defmodule Pleroma.User do @spec get_friends_query(User.t(), pos_integer() | nil) :: Ecto.Query.t() def get_friends_query(%User{} = user, nil) do - User.Query.build(%{friends: user}) + User.Query.build(%{friends: user, deactivated: false}) end def get_friends_query(user, page) do @@ -665,16 +682,16 @@ defmodule Pleroma.User do info_cng = User.Info.set_note_count(user.info, note_count) - cng = - change(user) - |> put_embed(:info, info_cng) - - update_and_set_cache(cng) + user + |> change() + |> put_embed(:info, info_cng) + |> update_and_set_cache() end def update_follower_count(%User{} = user) do follower_count_query = - User.Query.build(%{followers: user}) |> select([u], %{count: count(u.id)}) + User.Query.build(%{followers: user, deactivated: false}) + |> select([u], %{count: count(u.id)}) User |> where(id: ^user.id) @@ -697,9 +714,21 @@ defmodule Pleroma.User do end end + def remove_duplicated_following(%User{following: following} = user) do + uniq_following = Enum.uniq(following) + + if length(following) == length(uniq_following) do + {:ok, user} + else + user + |> update_changeset(%{following: uniq_following}) + |> update_and_set_cache() + end + end + @spec get_users_from_set([String.t()], boolean()) :: [User.t()] def get_users_from_set(ap_ids, local_only \\ true) do - criteria = %{ap_id: ap_ids} + criteria = %{ap_id: ap_ids, deactivated: false} criteria = if local_only, do: Map.put(criteria, :local, true), else: criteria User.Query.build(criteria) @@ -708,7 +737,7 @@ defmodule Pleroma.User do @spec get_recipients_from_activity(Activity.t()) :: [User.t()] def get_recipients_from_activity(%Activity{recipients: to}) do - User.Query.build(%{recipients_from_activity: to, local: true}) + User.Query.build(%{recipients_from_activity: to, local: true, deactivated: false}) |> Repo.all() end @@ -735,7 +764,7 @@ defmodule Pleroma.User do from(s in subquery(boost_search_rank_query(distinct_query, for_user)), order_by: [desc: s.search_rank], - limit: 20 + limit: 40 ) end @@ -806,6 +835,7 @@ defmodule Pleroma.User do ^processed_query ) ) + |> restrict_deactivated() end defp trigram_search_subquery(term) do @@ -824,6 +854,7 @@ defmodule Pleroma.User do }, where: fragment("trim(? || ' ' || coalesce(?, '')) % ?", u.nickname, u.name, ^term) ) + |> restrict_deactivated() end def mute(muter, %User{ap_id: ap_id}) do @@ -956,19 +987,19 @@ defmodule Pleroma.User do @spec muted_users(User.t()) :: [User.t()] def muted_users(user) do - User.Query.build(%{ap_id: user.info.mutes}) + User.Query.build(%{ap_id: user.info.mutes, deactivated: false}) |> Repo.all() end @spec blocked_users(User.t()) :: [User.t()] def blocked_users(user) do - User.Query.build(%{ap_id: user.info.blocks}) + User.Query.build(%{ap_id: user.info.blocks, deactivated: false}) |> Repo.all() end @spec subscribers(User.t()) :: [User.t()] def subscribers(user) do - User.Query.build(%{ap_id: user.info.subscribers}) + User.Query.build(%{ap_id: user.info.subscribers, deactivated: false}) |> Repo.all() end @@ -996,14 +1027,25 @@ defmodule Pleroma.User do update_and_set_cache(cng) end + def deactivate_async(user, status \\ true) do + PleromaJobQueue.enqueue(:background, __MODULE__, [:deactivate_async, user, status]) + end + def deactivate(%User{} = user, status \\ true) do info_cng = User.Info.set_activation_status(user.info, status) - cng = - change(user) - |> put_embed(:info, info_cng) + with {:ok, friends} <- User.get_friends(user), + {:ok, followers} <- User.get_followers(user), + {:ok, user} <- + user + |> change() + |> put_embed(:info, info_cng) + |> update_and_set_cache() do + Enum.each(followers, &invalidate_cache(&1)) + Enum.each(friends, &update_follower_count(&1)) - update_and_set_cache(cng) + {:ok, user} + end end def update_notification_settings(%User{} = user, settings \\ %{}) do @@ -1047,6 +1089,8 @@ defmodule Pleroma.User do {:ok, user} end + def perform(:deactivate_async, user, status), do: deactivate(user, status) + @spec perform(atom(), User.t(), list()) :: list() | {:error, any()} def perform(:blocks_import, %User{} = blocker, blocked_identifiers) when is_list(blocked_identifiers) do @@ -1105,7 +1149,6 @@ defmodule Pleroma.User do stream = ap_id |> Activity.query_by_actor() - |> Activity.with_preloaded_object() |> Repo.stream() Repo.transaction(fn -> Enum.each(stream, &delete_activity(&1)) end, timeout: :infinity) @@ -1344,11 +1387,64 @@ defmodule Pleroma.User do @spec all_superusers() :: [User.t()] def all_superusers do - User.Query.build(%{super_users: true, local: true}) + User.Query.build(%{super_users: true, local: true, deactivated: false}) |> Repo.all() end def showing_reblogs?(%User{} = user, %User{} = target) do target.ap_id not in user.info.muted_reblogs end + + @spec toggle_confirmation(User.t()) :: {:ok, User.t()} | {:error, Changeset.t()} + def toggle_confirmation(%User{} = user) do + need_confirmation? = !user.info.confirmation_pending + + info_changeset = + User.Info.confirmation_changeset(user.info, need_confirmation: need_confirmation?) + + user + |> change() + |> put_embed(:info, info_changeset) + |> update_and_set_cache() + end + + def get_mascot(%{info: %{mascot: %{} = mascot}}) when not is_nil(mascot) do + mascot + end + + def get_mascot(%{info: %{mascot: mascot}}) when is_nil(mascot) do + # use instance-default + config = Pleroma.Config.get([:assets, :mascots]) + default_mascot = Pleroma.Config.get([:assets, :default_mascot]) + mascot = Keyword.get(config, default_mascot) + + %{ + "id" => "default-mascot", + "url" => mascot[:url], + "preview_url" => mascot[:url], + "pleroma" => %{ + "mime_type" => mascot[:mime_type] + } + } + end + + def ensure_keys_present(user) do + info = user.info + + if info.keys do + {:ok, user} + else + {:ok, pem} = Keys.generate_rsa_pem() + + info_cng = + info + |> User.Info.set_keys(pem) + + cng = + Ecto.Changeset.change(user) + |> Ecto.Changeset.put_embed(:info, info_cng) + + update_and_set_cache(cng) + end + end end