Merge remote-tracking branch 'pleroma/develop' into feature/disable-account
[akkoma] / lib / pleroma / web / twitter_api / twitter_api.ex
index feadf86705474eac122f2414ab454271d6067dd1..41e1c287744b48813b0f1a582b420e4855adf341 100644 (file)
@@ -4,11 +4,10 @@
 
 defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
   alias Pleroma.Activity
-  alias Pleroma.Mailer
-  alias Pleroma.Object
+  alias Pleroma.Emails.Mailer
+  alias Pleroma.Emails.UserEmail
   alias Pleroma.Repo
   alias Pleroma.User
-  alias Pleroma.UserEmail
   alias Pleroma.UserInviteToken
   alias Pleroma.Web.ActivityPub.ActivityPub
   alias Pleroma.Web.CommonAPI
@@ -21,7 +20,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
   end
 
   def delete(%User{} = user, id) do
-    with %Activity{data: %{"type" => _type}} <- Repo.get(Activity, id),
+    with %Activity{data: %{"type" => _type}} <- Activity.get_by_id(id),
          {:ok, activity} <- CommonAPI.delete(id, user) do
       {:ok, activity}
     end
@@ -129,8 +128,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
     end
   end
 
-  def register_user(params) do
-    token_string = params["token"]
+  def register_user(params, opts \\ []) do
+    token = params["token"]
 
     params = %{
       nickname: params["nickname"],
@@ -163,37 +162,55 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
       # I have no idea how this error handling works
       {:error, %{error: Jason.encode!(%{captcha: [error]})}}
     else
-      registrations_open = Pleroma.Config.get([:instance, :registrations_open])
+      registration_process(
+        params,
+        %{
+          registrations_open: Pleroma.Config.get([:instance, :registrations_open]),
+          token: token
+        },
+        opts
+      )
+    end
+  end
 
-      # no need to query DB if registration is open
-      token =
-        unless registrations_open || is_nil(token_string) do
-          Repo.get_by(UserInviteToken, %{token: token_string})
-        end
+  defp registration_process(params, %{registrations_open: true}, opts) do
+    create_user(params, opts)
+  end
 
-      cond do
-        registrations_open || (!is_nil(token) && !token.used) ->
-          changeset = User.register_changeset(%User{}, params)
+  defp registration_process(params, %{token: token}, opts) do
+    invite =
+      unless is_nil(token) do
+        Repo.get_by(UserInviteToken, %{token: token})
+      end
 
-          with {:ok, user} <- User.register(changeset) do
-            !registrations_open && UserInviteToken.mark_as_used(token.token)
+    valid_invite? = invite && UserInviteToken.valid_invite?(invite)
 
-            {:ok, user}
-          else
-            {:error, changeset} ->
-              errors =
-                Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> msg end)
-                |> Jason.encode!()
+    case invite do
+      nil ->
+        {:error, "Invalid token"}
 
-              {:error, %{error: errors}}
-          end
+      invite when valid_invite? ->
+        UserInviteToken.update_usage!(invite)
+        create_user(params, opts)
 
-        !registrations_open && is_nil(token) ->
-          {:error, "Invalid token"}
+      _ ->
+        {:error, "Expired token"}
+    end
+  end
 
-        !registrations_open && token.used ->
-          {:error, "Expired token"}
-      end
+  defp create_user(params, opts) do
+    changeset = User.register_changeset(%User{}, params, opts)
+
+    case User.register(changeset) do
+      {:ok, user} ->
+        {:ok, user}
+
+      {:error, changeset} ->
+        errors =
+          Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> msg end)
+          |> Jason.encode!()
+
+        {:error, %{error: errors}}
     end
   end
 
@@ -219,21 +236,21 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
   def get_user(user \\ nil, params) do
     case params do
       %{"user_id" => user_id} ->
-        case target = User.get_cached_by_nickname_or_id(user_id) do
+        case User.get_cached_by_nickname_or_id(user_id) do
           nil ->
             {:error, "No user with such user_id"}
 
-          _ ->
-            {:ok, target}
+          %User{info: %{deactivated: true}} ->
+            {:error, "User has been disabled"}
+
+          user ->
+            {:ok, user}
         end
 
       %{"screen_name" => nickname} ->
-        case target = Repo.get_by(User, nickname: nickname) do
-          nil ->
-            {:error, "No user with such screen_name"}
-
-          _ ->
-            {:ok, target}
+        case User.get_cached_by_nickname(nickname) do
+          nil -> {:error, "No user with such screen_name"}
+          target -> {:ok, target}
         end
 
       _ ->
@@ -257,6 +274,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
 
   defp parse_int(_, default), do: default
 
+  # TODO: unify the search query with MastoAPI one and do only pagination here
   def search(_user, %{"q" => query} = params) do
     limit = parse_int(params["rpp"], 20)
     page = parse_int(params["page"], 1)
@@ -264,13 +282,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
 
     q =
       from(
-        a in Activity,
+        [a, o] in Activity.with_preloaded_object(Activity),
         where: fragment("?->>'type' = 'Create'", a.data),
         where: "https://www.w3.org/ns/activitystreams#Public" in a.recipients,
         where:
           fragment(
-            "to_tsvector('english', ?->'object'->>'content') @@ plainto_tsquery('english', ?)",
-            a.data,
+            "to_tsvector('english', ?->>'content') @@ plainto_tsquery('english', ?)",
+            o.data,
             ^query
           ),
         limit: ^limit,
@@ -282,35 +300,6 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
     _activities = Repo.all(q)
   end
 
-  # DEPRECATED mostly, context objects are now created at insertion time.
-  def context_to_conversation_id(context) do
-    with %Object{id: id} <- Object.get_cached_by_ap_id(context) do
-      id
-    else
-      _e ->
-        changeset = Object.context_mapping(context)
-
-        case Repo.insert(changeset) do
-          {:ok, %{id: id}} ->
-            id
-
-          # This should be solved by an upsert, but it seems ecto
-          # has problems accessing the constraint inside the jsonb.
-          {:error, _} ->
-            Object.get_cached_by_ap_id(context).id
-        end
-    end
-  end
-
-  def conversation_id_to_context(id) do
-    with %Object{data: %{"id" => context}} <- Repo.get(Object, id) do
-      context
-    else
-      _e ->
-        {:error, "No such conversation"}
-    end
-  end
-
   def get_external_profile(for_user, uri) do
     with {:ok, %User{} = user} <- User.get_or_fetch(uri) do
       {:ok, UserView.render("show.json", %{user: user, for: for_user})}