in dev, allow dev FE
[akkoma] / lib / pleroma / uploaders / uploader.ex
index 0959d7a3ec28f44e668104c41a3322155d36fc95..deba548b7a9eeb2524e11173324435fa629e8cb8 100644 (file)
@@ -1,8 +1,12 @@
 # Pleroma: A lightweight social networking server
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Uploaders.Uploader do
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Uploaders.Uploader do
+  import Pleroma.Web.Gettext
+
+  @mix_env Mix.env()
+
   @moduledoc """
   Defines the contract to put and get an uploaded file to any backend.
   """
   @moduledoc """
   Defines the contract to put and get an uploaded file to any backend.
   """
@@ -10,7 +14,7 @@ defmodule Pleroma.Uploaders.Uploader do
   @doc """
   Instructs how to get the file from the backend.
 
   @doc """
   Instructs how to get the file from the backend.
 
-  Used by `Pleroma.Plugs.UploadedMedia`.
+  Used by `Pleroma.Web.Plugs.UploadedMedia`.
   """
   @type get_method :: {:static_dir, directory :: String.t()} | {:url, url :: String.t()}
   @callback get_file(file :: String.t()) :: {:ok, get_method()}
   """
   @type get_method :: {:static_dir, directory :: String.t()} | {:url, url :: String.t()}
   @callback get_file(file :: String.t()) :: {:ok, get_method()}
@@ -27,18 +31,54 @@ defmodule Pleroma.Uploaders.Uploader do
     This allows to correctly proxy or redirect requests to the backend, while allowing to migrate backends without breaking any URL.
   * `{url, url :: String.t}` to bypass `get_file/2` and use the `url` directly in the activity.
   * `{:error, String.t}` error information if the file failed to be saved to the backend.
     This allows to correctly proxy or redirect requests to the backend, while allowing to migrate backends without breaking any URL.
   * `{url, url :: String.t}` to bypass `get_file/2` and use the `url` directly in the activity.
   * `{:error, String.t}` error information if the file failed to be saved to the backend.
-
+  * `:wait_callback` will wait for an http post request at `/api/pleroma/upload_callback/:upload_path` and call the uploader's `http_callback/3` method.
 
   """
 
   """
-  @callback put_file(Pleroma.Upload.t()) ::
-              :ok | {:ok, {:file | :url, String.t()}} | {:error, String.t()}
+  @type file_spec :: {:file | :url, String.t()}
+  @callback put_file(upload :: struct()) ::
+              :ok | {:ok, file_spec()} | {:error, String.t()} | :wait_callback
+
+  @callback delete_file(file :: String.t()) :: :ok | {:error, String.t()}
 
 
-  @spec put_file(module(), Pleroma.Upload.t()) ::
-          {:ok, {:file | :url, String.t()}} | {:error, String.t()}
+  @callback http_callback(Plug.Conn.t(), Map.t()) ::
+              {:ok, Plug.Conn.t()}
+              | {:ok, Plug.Conn.t(), file_spec()}
+              | {:error, Plug.Conn.t(), String.t()}
+  @optional_callbacks http_callback: 2
+
+  @spec put_file(module(), upload :: struct()) :: {:ok, file_spec()} | {:error, String.t()}
   def put_file(uploader, upload) do
     case uploader.put_file(upload) do
       :ok -> {:ok, {:file, upload.path}}
   def put_file(uploader, upload) do
     case uploader.put_file(upload) do
       :ok -> {:ok, {:file, upload.path}}
-      other -> other
+      :wait_callback -> handle_callback(uploader, upload)
+      {:ok, _} = ok -> ok
+      {:error, _} = error -> error
+    end
+  end
+
+  defp handle_callback(uploader, upload) do
+    :global.register_name({__MODULE__, upload.path}, self())
+
+    receive do
+      {__MODULE__, pid, conn, params} ->
+        case uploader.http_callback(conn, params) do
+          {:ok, conn, ok} ->
+            send(pid, {__MODULE__, conn})
+            {:ok, ok}
+
+          {:error, conn, error} ->
+            send(pid, {__MODULE__, conn})
+            {:error, error}
+        end
+    after
+      callback_timeout() -> {:error, dgettext("errors", "Uploader callback timeout")}
+    end
+  end
+
+  defp callback_timeout do
+    case @mix_env do
+      :test -> 1_000
+      _ -> 30_000
     end
   end
 end
     end
   end
 end