Add failing test, which exposes a bug
[akkoma] / lib / pleroma / activity.ex
index ec558168ae05e43ad5e85f76c18b72623752c87d..37b2c041eb97222588241f13feabe45ad994d9ae 100644 (file)
@@ -12,6 +12,7 @@ defmodule Pleroma.Activity do
   alias Pleroma.Notification
   alias Pleroma.Object
   alias Pleroma.Repo
+  alias Pleroma.ReportNote
   alias Pleroma.ThreadMute
   alias Pleroma.User
 
@@ -21,7 +22,7 @@ defmodule Pleroma.Activity do
   @type t :: %__MODULE__{}
   @type actor :: String.t()
 
-  @primary_key {:id, Pleroma.FlakeId, autogenerate: true}
+  @primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}
 
   # https://github.com/tootsuite/mastodon/blob/master/app/models/notification.rb#L19
   @mastodon_notification_types %{
@@ -41,8 +42,14 @@ defmodule Pleroma.Activity do
     field(:actor, :string)
     field(:recipients, {:array, :string}, default: [])
     field(:thread_muted?, :boolean, virtual: true)
+
+    # This is a fake relation,
+    # do not use outside of with_preloaded_user_actor/with_joined_user_actor
+    has_one(:user_actor, User, on_delete: :nothing, foreign_key: :id)
     # This is a fake relation, do not use outside of with_preloaded_bookmark/get_bookmark
     has_one(:bookmark, Bookmark)
+    # This is a fake relation, do not use outside of with_preloaded_report_notes
+    has_many(:report_notes, ReportNote)
     has_many(:notifications, Notification, on_delete: :delete_all)
 
     # Attention: this is a fake relation, don't try to preload it blindly and expect it to work!
@@ -86,6 +93,19 @@ defmodule Pleroma.Activity do
     |> preload([activity, object: object], object: object)
   end
 
+  def with_joined_user_actor(query, join_type \\ :inner) do
+    join(query, join_type, [activity], u in User,
+      on: u.ap_id == activity.actor,
+      as: :user_actor
+    )
+  end
+
+  def with_preloaded_user_actor(query, join_type \\ :inner) do
+    query
+    |> with_joined_user_actor(join_type)
+    |> preload([activity, user_actor: user_actor], user_actor: user_actor)
+  end
+
   def with_preloaded_bookmark(query, %User{} = user) do
     from([a] in query,
       left_join: b in Bookmark,
@@ -96,6 +116,16 @@ defmodule Pleroma.Activity do
 
   def with_preloaded_bookmark(query, _), do: query
 
+  def with_preloaded_report_notes(query) do
+    from([a] in query,
+      left_join: r in ReportNote,
+      on: a.id == r.activity_id,
+      preload: [report_notes: r]
+    )
+  end
+
+  def with_preloaded_report_notes(query, _), do: query
+
   def with_set_thread_muted_field(query, %User{} = user) do
     from([a] in query,
       left_join: tm in ThreadMute,
@@ -137,11 +167,18 @@ defmodule Pleroma.Activity do
     |> Repo.one()
   end
 
+  @spec get_by_id(String.t()) :: Activity.t() | nil
   def get_by_id(id) do
-    Activity
-    |> where([a], a.id == ^id)
-    |> restrict_deactivated_users()
-    |> Repo.one()
+    case FlakeId.flake_id?(id) do
+      true ->
+        Activity
+        |> where([a], a.id == ^id)
+        |> restrict_deactivated_users()
+        |> Repo.one()
+
+      _ ->
+        nil
+    end
   end
 
   def get_by_id_with_object(id) do
@@ -279,4 +316,17 @@ defmodule Pleroma.Activity do
   end
 
   defdelegate search(user, query, options \\ []), to: Pleroma.Activity.Search
+
+  def direct_conversation_id(activity, for_user) do
+    alias Pleroma.Conversation.Participation
+
+    with %{data: %{"context" => context}} when is_binary(context) <- activity,
+         %Pleroma.Conversation{} = conversation <- Pleroma.Conversation.get_for_ap_id(context),
+         %Participation{id: participation_id} <-
+           Participation.for_user_and_conversation(for_user, conversation) do
+      participation_id
+    else
+      _ -> nil
+    end
+  end
 end