aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/uploaders
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/uploaders')
-rw-r--r--lib/pleroma/uploaders/local.ex47
-rw-r--r--lib/pleroma/uploaders/s3.ex24
-rw-r--r--lib/pleroma/uploaders/swift/keystone.ex48
-rw-r--r--lib/pleroma/uploaders/swift/swift.ex28
-rw-r--r--lib/pleroma/uploaders/swift/uploader.ex10
-rw-r--r--lib/pleroma/uploaders/uploader.ex20
6 files changed, 177 insertions, 0 deletions
diff --git a/lib/pleroma/uploaders/local.ex b/lib/pleroma/uploaders/local.ex
new file mode 100644
index 000000000..d4624661f
--- /dev/null
+++ b/lib/pleroma/uploaders/local.ex
@@ -0,0 +1,47 @@
+defmodule Pleroma.Uploaders.Local do
+ @behaviour Pleroma.Uploaders.Uploader
+
+ alias Pleroma.Web
+
+ def put_file(name, uuid, tmpfile, _content_type, should_dedupe) do
+ upload_folder = get_upload_path(uuid, should_dedupe)
+ url_path = get_url(name, uuid, should_dedupe)
+
+ File.mkdir_p!(upload_folder)
+
+ result_file = Path.join(upload_folder, name)
+
+ if File.exists?(result_file) do
+ File.rm!(tmpfile)
+ else
+ File.cp!(tmpfile, result_file)
+ end
+
+ {:ok, url_path}
+ end
+
+ def upload_path do
+ settings = Application.get_env(:pleroma, Pleroma.Uploaders.Local)
+ Keyword.fetch!(settings, :uploads)
+ end
+
+ defp get_upload_path(uuid, should_dedupe) do
+ if should_dedupe do
+ upload_path()
+ else
+ Path.join(upload_path(), uuid)
+ end
+ end
+
+ defp get_url(name, uuid, should_dedupe) do
+ if should_dedupe do
+ url_for(:cow_uri.urlencode(name))
+ else
+ url_for(Path.join(uuid, :cow_uri.urlencode(name)))
+ end
+ end
+
+ defp url_for(file) do
+ "#{Web.base_url()}/media/#{file}"
+ end
+end
diff --git a/lib/pleroma/uploaders/s3.ex b/lib/pleroma/uploaders/s3.ex
new file mode 100644
index 000000000..ce0ed3e34
--- /dev/null
+++ b/lib/pleroma/uploaders/s3.ex
@@ -0,0 +1,24 @@
+defmodule Pleroma.Uploaders.S3 do
+ @behaviour Pleroma.Uploaders.Uploader
+
+ def put_file(name, uuid, path, content_type, _should_dedupe) do
+ settings = Application.get_env(:pleroma, Pleroma.Uploaders.S3)
+ bucket = Keyword.fetch!(settings, :bucket)
+ public_endpoint = Keyword.fetch!(settings, :public_endpoint)
+
+ {:ok, file_data} = File.read(path)
+
+ File.rm!(path)
+
+ s3_name = "#{uuid}/#{name}"
+
+ {:ok, _} =
+ ExAws.S3.put_object(bucket, s3_name, file_data, [
+ {:acl, :public_read},
+ {:content_type, content_type}
+ ])
+ |> ExAws.request()
+
+ {:ok, "#{public_endpoint}/#{bucket}/#{s3_name}"}
+ end
+end
diff --git a/lib/pleroma/uploaders/swift/keystone.ex b/lib/pleroma/uploaders/swift/keystone.ex
new file mode 100644
index 000000000..a79214319
--- /dev/null
+++ b/lib/pleroma/uploaders/swift/keystone.ex
@@ -0,0 +1,48 @@
+defmodule Pleroma.Uploaders.Swift.Keystone do
+ use HTTPoison.Base
+
+ @settings Application.get_env(:pleroma, Pleroma.Uploaders.Swift)
+
+ def process_url(url) do
+ Enum.join(
+ [Keyword.fetch!(@settings, :auth_url), url],
+ "/"
+ )
+ end
+
+ def process_response_body(body) do
+ body
+ |> Poison.decode!()
+ end
+
+ def get_token() do
+ username = Keyword.fetch!(@settings, :username)
+ password = Keyword.fetch!(@settings, :password)
+ tenant_id = Keyword.fetch!(@settings, :tenant_id)
+
+ case post(
+ "/tokens",
+ make_auth_body(username, password, tenant_id),
+ ["Content-Type": "application/json"],
+ hackney: [:insecure]
+ ) do
+ {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
+ body["access"]["token"]["id"]
+
+ {:ok, %HTTPoison.Response{status_code: _}} ->
+ ""
+ end
+ end
+
+ def make_auth_body(username, password, tenant) do
+ Poison.encode!(%{
+ :auth => %{
+ :passwordCredentials => %{
+ :username => username,
+ :password => password
+ },
+ :tenantId => tenant
+ }
+ })
+ end
+end
diff --git a/lib/pleroma/uploaders/swift/swift.ex b/lib/pleroma/uploaders/swift/swift.ex
new file mode 100644
index 000000000..819dfebda
--- /dev/null
+++ b/lib/pleroma/uploaders/swift/swift.ex
@@ -0,0 +1,28 @@
+defmodule Pleroma.Uploaders.Swift.Client do
+ use HTTPoison.Base
+
+ @settings Application.get_env(:pleroma, Pleroma.Uploaders.Swift)
+
+ def process_url(url) do
+ Enum.join(
+ [Keyword.fetch!(@settings, :storage_url), url],
+ "/"
+ )
+ end
+
+ def upload_file(filename, body, content_type) do
+ object_url = Keyword.fetch!(@settings, :object_url)
+ token = Pleroma.Uploaders.Swift.Keystone.get_token()
+
+ case put("#{filename}", body, "X-Auth-Token": token, "Content-Type": content_type) do
+ {:ok, %HTTPoison.Response{status_code: 201}} ->
+ {:ok, "#{object_url}/#{filename}"}
+
+ {:ok, %HTTPoison.Response{status_code: 401}} ->
+ {:error, "Unauthorized, Bad Token"}
+
+ {:error, _} ->
+ {:error, "Swift Upload Error"}
+ end
+ end
+end
diff --git a/lib/pleroma/uploaders/swift/uploader.ex b/lib/pleroma/uploaders/swift/uploader.ex
new file mode 100644
index 000000000..794f76cb0
--- /dev/null
+++ b/lib/pleroma/uploaders/swift/uploader.ex
@@ -0,0 +1,10 @@
+defmodule Pleroma.Uploaders.Swift do
+ @behaviour Pleroma.Uploaders.Uploader
+
+ def put_file(name, uuid, tmp_path, content_type, _should_dedupe) do
+ {:ok, file_data} = File.read(tmp_path)
+ remote_name = "#{uuid}/#{name}"
+
+ Pleroma.Uploaders.Swift.Client.upload_file(remote_name, file_data, content_type)
+ end
+end
diff --git a/lib/pleroma/uploaders/uploader.ex b/lib/pleroma/uploaders/uploader.ex
new file mode 100644
index 000000000..b58fc6d71
--- /dev/null
+++ b/lib/pleroma/uploaders/uploader.ex
@@ -0,0 +1,20 @@
+defmodule Pleroma.Uploaders.Uploader do
+ @moduledoc """
+ Defines the contract to put an uploaded file to any backend.
+ """
+
+ @doc """
+ Put a file to the backend.
+
+ Returns `{:ok, String.t } | {:error, String.t} containing the path of the
+ uploaded file, or error information if the file failed to be saved to the
+ respective backend.
+ """
+ @callback put_file(
+ name :: String.t(),
+ uuid :: String.t(),
+ file :: File.t(),
+ content_type :: String.t(),
+ should_dedupe :: Boolean.t()
+ ) :: {:ok, String.t()} | {:error, String.t()}
+end