MastoAPI: Don't break on missing users.
[akkoma] / lib / pleroma / user.ex
index 5491e8b9a499bf8e32dbb217a94b0ad732945689..a52e536d3397f1e96e43ae46fb4b31128894e981 100644 (file)
@@ -44,6 +44,8 @@ defmodule Pleroma.User do
     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}}),
@@ -51,20 +53,18 @@ defmodule Pleroma.User do
 
   def auth_active?(_), do: false
 
-  def remote_or_auth_active?(%User{local: false}), do: true
-  def remote_or_auth_active?(%User{local: true} = user), do: auth_active?(user)
-
   def visible_for?(user, for_user \\ nil)
 
   def visible_for?(%User{id: user_id}, %User{id: for_id}) when user_id == for_id, do: true
 
   def visible_for?(%User{} = user, for_user) do
-    remote_or_auth_active?(user) || superuser?(for_user)
+    auth_active?(user) || superuser?(for_user)
   end
 
   def visible_for?(_, _), do: false
 
-  def superuser?(%User{info: %User.Info{} = info}), do: User.Info.superuser?(info)
+  def superuser?(%User{local: true, info: %User.Info{is_admin: true}}), do: true
+  def superuser?(%User{local: true, info: %User.Info{is_moderator: true}}), do: true
   def superuser?(_), do: false
 
   def avatar_url(user) do
@@ -237,10 +237,24 @@ defmodule Pleroma.User do
     end
   end
 
+  defp autofollow_users(user) do
+    candidates = Pleroma.Config.get([:instance, :autofollowed_nicknames])
+
+    autofollowed_users =
+      from(u in User,
+        where: u.local == true,
+        where: u.nickname in ^candidates
+      )
+      |> Repo.all()
+
+    follow_all(user, autofollowed_users)
+  end
+
   @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, _} = try_send_confirmation_email(user) do
+         {:ok, _} <- try_send_confirmation_email(user),
+         {:ok, user} <- autofollow_users(user) do
       {:ok, user}
     end
   end
@@ -290,6 +304,25 @@ defmodule Pleroma.User do
     end
   end
 
+  @doc "A mass follow for local users. Ignores blocks and has no side effects"
+  @spec follow_all(User.t(), list(User.t())) :: {atom(), User.t()}
+  def follow_all(follower, followeds) do
+    following =
+      (follower.following ++ Enum.map(followeds, fn %{follower_address: fa} -> fa end))
+      |> Enum.uniq()
+
+    {:ok, follower} =
+      follower
+      |> follow_changeset(%{following: following})
+      |> update_and_set_cache
+
+    Enum.each(followeds, fn followed ->
+      update_follower_count(followed)
+    end)
+
+    {:ok, follower}
+  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)
@@ -454,7 +487,7 @@ defmodule Pleroma.User do
     end
   end
 
-  def get_followers_query(%User{id: id, follower_address: follower_address}) do
+  def get_followers_query(%User{id: id, follower_address: follower_address}, nil) do
     from(
       u in User,
       where: fragment("? <@ ?", ^[follower_address], u.following),
@@ -462,13 +495,23 @@ defmodule Pleroma.User do
     )
   end
 
-  def get_followers(user) do
-    q = get_followers_query(user)
+  def get_followers_query(user, page) do
+    from(
+      u in get_followers_query(user, nil),
+      limit: 20,
+      offset: ^((page - 1) * 20)
+    )
+  end
+
+  def get_followers_query(user), do: get_followers_query(user, nil)
+
+  def get_followers(user, page \\ nil) do
+    q = get_followers_query(user, page)
 
     {:ok, Repo.all(q)}
   end
 
-  def get_friends_query(%User{id: id, following: following}) do
+  def get_friends_query(%User{id: id, following: following}, nil) do
     from(
       u in User,
       where: u.follower_address in ^following,
@@ -476,8 +519,18 @@ defmodule Pleroma.User do
     )
   end
 
-  def get_friends(user) do
-    q = get_friends_query(user)
+  def get_friends_query(user, page) do
+    from(
+      u in get_friends_query(user, nil),
+      limit: 20,
+      offset: ^((page - 1) * 20)
+    )
+  end
+
+  def get_friends_query(user), do: get_friends_query(user, nil)
+
+  def get_friends(user, page \\ nil) do
+    q = get_friends_query(user, page)
 
     {:ok, Repo.all(q)}
   end
@@ -987,4 +1040,14 @@ defmodule Pleroma.User do
       @strict_local_nickname_regex
     end
   end
+
+  def error_user(ap_id) do
+    %User{
+      name: ap_id,
+      ap_id: ap_id,
+      info: %User.Info{},
+      nickname: "erroruser@example.com",
+      inserted_at: NaiveDateTime.utc_now()
+    }
+  end
 end