X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fuser.ex;h=6e2269aff220030a3ef81de3fde2ab58911a4d87;hb=e5d553aa45ffa218b0695d7976f012bfc1dcbafe;hp=41289b4d0591cb6cad4b07d768075726ba95d4b2;hpb=750de7d84272c050ce7158f9c51dfe6d9823e81c;p=akkoma diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 41289b4d0..6e2269aff 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -13,6 +13,7 @@ defmodule Pleroma.User do alias Pleroma.Formatter alias Pleroma.Notification alias Pleroma.Object + alias Pleroma.Registration alias Pleroma.Repo alias Pleroma.User alias Pleroma.Web @@ -55,19 +56,16 @@ defmodule Pleroma.User do field(:bookmarks, {:array, :string}, default: []) field(:last_refreshed_at, :naive_datetime_usec) has_many(:notifications, Notification) + has_many(:registrations, Registration) embeds_one(:info, Pleroma.User.Info) timestamps() end - def auth_active?(%User{local: false}), do: true - - def auth_active?(%User{info: %User.Info{confirmation_pending: false}}), do: true - def auth_active?(%User{info: %User.Info{confirmation_pending: true}}), do: !Pleroma.Config.get([:instance, :account_activation_required]) - def auth_active?(_), do: false + def auth_active?(%User{}), do: true def visible_for?(user, for_user \\ nil) @@ -83,17 +81,17 @@ defmodule Pleroma.User do def superuser?(%User{local: true, info: %User.Info{is_moderator: true}}), do: true def superuser?(_), do: false - def avatar_url(user) do + def avatar_url(user, options \\ []) do case user.avatar do %{"url" => [%{"href" => href} | _]} -> href - _ -> "#{Web.base_url()}/images/avi.png" + _ -> !options[:no_default] && "#{Web.base_url()}/images/avi.png" end end - def banner_url(user) do + def banner_url(user, options \\ []) do case user.info.banner do %{"url" => [%{"href" => href} | _]} -> href - _ -> "#{Web.base_url()}/images/banner.png" + _ -> !options[:no_default] && "#{Web.base_url()}/images/banner.png" end end @@ -220,7 +218,7 @@ defmodule Pleroma.User do changeset = struct |> cast(params, [:bio, :email, :name, :nickname, :password, :password_confirmation]) - |> validate_required([:email, :name, :nickname, :password, :password_confirmation]) + |> validate_required([:name, :nickname, :password, :password_confirmation]) |> validate_confirmation(:password) |> unique_constraint(:email) |> unique_constraint(:nickname) @@ -231,6 +229,13 @@ defmodule Pleroma.User do |> validate_length(:name, min: 1, max: 100) |> put_change(:info, info_change) + changeset = + if opts[:external] do + changeset + else + validate_required(changeset, [:email]) + end + if changeset.valid? do hashed = Pbkdf2.hashpwsalt(changeset.changes[:password]) ap_id = User.ap_id(%User{nickname: changeset.changes[:nickname]}) @@ -509,11 +514,10 @@ defmodule Pleroma.User do end end + def get_by_email(email), do: Repo.get_by(User, email: email) + def get_by_nickname_or_email(nickname_or_email) do - case user = Repo.get_by(User, nickname: nickname_or_email) do - %User{} -> user - nil -> Repo.get_by(User, email: nickname_or_email) - end + get_by_nickname(nickname_or_email) || get_by_email(nickname_or_email) end def get_cached_user_info(user) do @@ -772,52 +776,6 @@ defmodule Pleroma.User do Repo.all(query) end - @spec search_for_admin(%{ - local: boolean(), - page: number(), - page_size: number() - }) :: {:ok, [Pleroma.User.t()], number()} - def search_for_admin(%{query: nil, local: local, page: page, page_size: page_size}) do - query = - from(u in User, order_by: u.nickname) - |> maybe_local_user_query(local) - - paginated_query = - query - |> paginate(page, page_size) - - count = - query - |> Repo.aggregate(:count, :id) - - {:ok, Repo.all(paginated_query), count} - end - - @spec search_for_admin(%{ - query: binary(), - local: boolean(), - page: number(), - page_size: number() - }) :: {:ok, [Pleroma.User.t()], number()} - def search_for_admin(%{ - query: term, - local: local, - page: page, - page_size: page_size - }) do - maybe_local_query = User |> maybe_local_user_query(local) - - search_query = from(u in maybe_local_query, where: ilike(u.nickname, ^"%#{term}%")) - count = search_query |> Repo.aggregate(:count, :id) - - results = - search_query - |> paginate(page, page_size) - |> Repo.all() - - {:ok, results, count} - end - def search(query, resolve \\ false, for_user \\ nil) do # Strip the beginning @ off if there is a query query = String.trim_leading(query, "@") @@ -856,7 +814,7 @@ defmodule Pleroma.User do search_rank: fragment( """ - CASE WHEN (?) THEN (?) * 1.3 + CASE WHEN (?) THEN (?) * 1.3 WHEN (?) THEN (?) * 1.2 WHEN (?) THEN (?) * 1.1 ELSE (?) END @@ -973,6 +931,38 @@ defmodule Pleroma.User do update_and_set_cache(cng) end + def subscribe(subscriber, %{ap_id: ap_id}) do + deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked]) + + with %User{} = subscribed <- get_cached_by_ap_id(ap_id) do + blocked = blocks?(subscribed, subscriber) and deny_follow_blocked + + if blocked do + {:error, "Could not subscribe: #{subscribed.nickname} is blocking you"} + else + info_cng = + subscribed.info + |> User.Info.add_to_subscribers(subscriber.ap_id) + + change(subscribed) + |> put_embed(:info, info_cng) + |> update_and_set_cache() + end + end + end + + def unsubscribe(unsubscriber, %{ap_id: ap_id}) do + with %User{} = user <- get_cached_by_ap_id(ap_id) do + info_cng = + user.info + |> User.Info.remove_from_subscribers(unsubscriber.ap_id) + + change(user) + |> put_embed(:info, info_cng) + |> update_and_set_cache() + end + end + def block(blocker, %User{ap_id: ap_id} = blocked) do # sever any follow relationships to prevent leaks per activitypub (Pleroma issue #213) blocker = @@ -983,10 +973,20 @@ defmodule Pleroma.User do blocker end + blocker = + if subscribed_to?(blocked, blocker) do + {:ok, blocker} = unsubscribe(blocked, blocker) + blocker + else + blocker + end + if following?(blocked, blocker) do unfollow(blocked, blocker) end + {:ok, blocker} = update_follower_count(blocker) + info_cng = blocker.info |> User.Info.add_to_block(ap_id) @@ -1029,12 +1029,21 @@ defmodule Pleroma.User do end) end + def subscribed_to?(user, %{ap_id: ap_id}) do + with %User{} = target <- User.get_by_ap_id(ap_id) do + Enum.member?(target.info.subscribers, user.ap_id) + end + end + def muted_users(user), do: Repo.all(from(u in User, where: u.ap_id in ^user.info.mutes)) def blocked_users(user), do: Repo.all(from(u in User, where: u.ap_id in ^user.info.blocks)) + def subscribers(user), + do: Repo.all(from(u in User, where: u.ap_id in ^user.info.subscribers)) + def block_domain(user, domain) do info_cng = user.info @@ -1071,6 +1080,42 @@ defmodule Pleroma.User do ) end + def maybe_external_user_query(query, external) do + if external, do: external_user_query(query), else: query + end + + def external_user_query(query \\ User) do + from( + u in query, + where: u.local == false, + where: not is_nil(u.nickname) + ) + end + + def maybe_active_user_query(query, active) do + if active, do: active_user_query(query), else: query + end + + def active_user_query(query \\ User) do + from( + u in query, + where: fragment("not (?->'deactivated' @> 'true')", u.info), + where: not is_nil(u.nickname) + ) + end + + def maybe_deactivated_user_query(query, deactivated) do + if deactivated, do: deactivated_user_query(query), else: query + end + + def deactivated_user_query(query \\ User) do + from( + u in query, + where: fragment("(?->'deactivated' @> 'true')", u.info), + where: not is_nil(u.nickname) + ) + end + def active_local_user_query do from( u in local_user_query(), @@ -1096,34 +1141,41 @@ defmodule Pleroma.User do update_and_set_cache(cng) end + def update_notification_settings(%User{} = user, settings \\ %{}) do + info_changeset = User.Info.update_notification_settings(user.info, settings) + + change(user) + |> put_embed(:info, info_changeset) + |> update_and_set_cache() + end + def delete(%User{} = user) do {:ok, user} = User.deactivate(user) # Remove all relationships {:ok, followers} = User.get_followers(user) - followers - |> Enum.each(fn follower -> User.unfollow(follower, user) end) + Enum.each(followers, fn follower -> User.unfollow(follower, user) end) {:ok, friends} = User.get_friends(user) - friends - |> Enum.each(fn followed -> User.unfollow(user, followed) end) + Enum.each(friends, fn followed -> User.unfollow(user, followed) end) - query = - from(a in Activity, where: a.actor == ^user.ap_id) - |> Activity.with_preloaded_object() + delete_user_activities(user) + end - Repo.all(query) - |> Enum.each(fn activity -> - case activity.data["type"] do - "Create" -> - ActivityPub.delete(Object.normalize(activity)) + def delete_user_activities(%User{ap_id: ap_id} = user) do + Activity + |> where(actor: ^ap_id) + |> Activity.with_preloaded_object() + |> Repo.all() + |> Enum.each(fn + %{data: %{"type" => "Create"}} = activity -> + activity |> Object.normalize() |> ActivityPub.delete() - # TODO: Do something with likes, follows, repeats. - _ -> - "Doing nothing" - end + # TODO: Do something with likes, follows, repeats. + _ -> + "Doing nothing" end) {:ok, user} @@ -1245,8 +1297,8 @@ defmodule Pleroma.User do # this is because we have synchronous follow APIs and need to simulate them # with an async handshake def wait_and_refresh(_, %User{local: true} = a, %User{local: true} = b) do - with %User{} = a <- Repo.get(User, a.id), - %User{} = b <- Repo.get(User, b.id) do + with %User{} = a <- User.get_by_id(a.id), + %User{} = b <- User.get_by_id(b.id) do {:ok, a, b} else _e -> @@ -1256,8 +1308,8 @@ defmodule Pleroma.User do def wait_and_refresh(timeout, %User{} = a, %User{} = b) do with :ok <- :timer.sleep(timeout), - %User{} = a <- Repo.get(User, a.id), - %User{} = b <- Repo.get(User, b.id) do + %User{} = a <- User.get_by_id(a.id), + %User{} = b <- User.get_by_id(b.id) do {:ok, a, b} else _e ->