user: harden auth_active?/1, superuser?/1, visible_for?/1
[akkoma] / lib / pleroma / user.ex
index d4a6b13fb51676bc789f4dc02f0150944d7a5234..5491e8b9a499bf8e32dbb217a94b0ad732945689 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.User do
@@ -44,12 +44,28 @@ defmodule Pleroma.User do
     timestamps()
   end
 
-  def auth_active?(%User{} = user) do
-    (user.info && !user.info.confirmation_pending) ||
-      !Pleroma.Config.get([:instance, :account_activation_required])
+  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 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)
   end
 
-  def superuser?(%User{} = user), do: user.info && User.Info.superuser?(user.info)
+  def visible_for?(_, _), do: false
+
+  def superuser?(%User{info: %User.Info{} = info}), do: User.Info.superuser?(info)
+  def superuser?(_), do: false
 
   def avatar_url(user) do
     case user.avatar do
@@ -359,6 +375,15 @@ defmodule Pleroma.User do
     Repo.get_by(User, ap_id: ap_id)
   end
 
+  # This is mostly an SPC migration fix. This guesses the user nickname (by taking the last part of the ap_id and the domain) and tries to get that user
+  def get_by_guessed_nickname(ap_id) do
+    domain = URI.parse(ap_id).host
+    name = List.last(String.split(ap_id, "/"))
+    nickname = "#{name}@#{domain}"
+
+    get_by_nickname(nickname)
+  end
+
   def update_and_set_cache(changeset) do
     with {:ok, user} <- Repo.update(changeset) do
       Cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
@@ -388,7 +413,7 @@ defmodule Pleroma.User do
 
   def get_by_nickname(nickname) do
     Repo.get_by(User, nickname: nickname) ||
-      if String.ends_with?(nickname, "@" <> Pleroma.Web.Endpoint.host()) do
+      if Regex.match?(~r(@#{Pleroma.Web.Endpoint.host()})i, nickname) do
         [local_nickname, _] = String.split(nickname, "@")
         Repo.get_by(User, nickname: local_nickname)
       end
@@ -487,6 +512,7 @@ defmodule Pleroma.User do
       Enum.map(reqs, fn req -> req.actor end)
       |> Enum.uniq()
       |> Enum.map(fn ap_id -> get_by_ap_id(ap_id) end)
+      |> Enum.filter(fn u -> !is_nil(u) end)
       |> Enum.filter(fn u -> !following?(u, user) end)
 
     {:ok, users}
@@ -601,7 +627,7 @@ defmodule Pleroma.User do
         select_merge: %{
           search_distance:
             fragment(
-              "? <-> (? || ?)",
+              "? <-> (? || coalesce(?, ''))",
               ^query,
               u.nickname,
               u.name
@@ -778,7 +804,9 @@ defmodule Pleroma.User do
     Pleroma.HTML.Scrubber.TwitterText
   end
 
-  def html_filter_policy(_), do: nil
+  @default_scrubbers Pleroma.Config.get([:markup, :scrub_policy])
+
+  def html_filter_policy(_), do: @default_scrubbers
 
   def get_or_fetch_by_ap_id(ap_id) do
     user = get_by_ap_id(ap_id)