Uploader callback controller
authorhref <href@random.sh>
Mon, 21 Jan 2019 21:44:14 +0000 (22:44 +0100)
committerhref <href@random.sh>
Mon, 21 Jan 2019 21:44:14 +0000 (22:44 +0100)
lib/pleroma/uploaders/uploader.ex
lib/pleroma/web/router.ex
lib/pleroma/web/uploader_controller.ex [new file with mode: 0644]

index 0959d7a3ec28f44e668104c41a3322155d36fc95..ce83cbbbc76584afdc0dc45de40e64b33f0cae2f 100644 (file)
@@ -27,18 +27,47 @@ 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.
+  * `: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.
 
 
   """
+  @type file_spec :: {:file | :url, String.t()}
   @callback put_file(Pleroma.Upload.t()) ::
-              :ok | {:ok, {:file | :url, String.t()}} | {:error, String.t()}
+              :ok | {:ok, file_spec()} | {:error, String.t()} | :wait_callback
+
+  @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(), Pleroma.Upload.t()) :: {:ok, file_spec()} | {:error, String.t()}
 
-  @spec put_file(module(), Pleroma.Upload.t()) ::
-          {:ok, {:file | :url, String.t()}} | {:error, String.t()}
   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
+      30_000 -> {:error, "Uploader callback timeout"}
     end
   end
 end
index 7a0c9fd25d33de7451160465599af45a7b339b3f..69ab58c6addd44036c1f131e3f0352dcd8198808 100644 (file)
@@ -107,6 +107,11 @@ defmodule Pleroma.Web.Router do
     get("/captcha", UtilController, :captcha)
   end
 
+  scope "/api/pleroma", Pleroma.Web do
+    pipe_through(:pleroma_api)
+    post("/uploader_callback/:upload_path", UploaderController, :callback)
+  end
+
   scope "/api/pleroma/admin", Pleroma.Web.AdminAPI do
     pipe_through(:admin_api)
     delete("/user", AdminAPIController, :user_delete)
diff --git a/lib/pleroma/web/uploader_controller.ex b/lib/pleroma/web/uploader_controller.ex
new file mode 100644 (file)
index 0000000..6c28d11
--- /dev/null
@@ -0,0 +1,25 @@
+defmodule Pleroma.Web.UploaderController do
+  use Pleroma.Web, :controller
+
+  alias Pleroma.Uploaders.Uploader
+
+  def callback(conn, params = %{"upload_path" => upload_path}) do
+    process_callback(conn, :global.whereis_name({Uploader, upload_path}), params)
+  end
+
+  def callbacks(conn, _) do
+    send_resp(conn, 400, "bad request")
+  end
+
+  defp process_callback(conn, pid, params) when is_pid(pid) do
+    send(pid, {Uploader, self(), conn, params})
+
+    receive do
+      {Uploader, conn} -> conn
+    end
+  end
+
+  defp process_callback(conn, _, _) do
+    send_resp(conn, 400, "bad request")
+  end
+end