diff options
Diffstat (limited to 'lib/pleroma/uploaders')
-rw-r--r-- | lib/pleroma/uploaders/local.ex | 51 | ||||
-rw-r--r-- | lib/pleroma/uploaders/s3.ex | 24 | ||||
-rw-r--r-- | lib/pleroma/uploaders/swift/keystone.ex | 48 | ||||
-rw-r--r-- | lib/pleroma/uploaders/swift/swift.ex | 28 | ||||
-rw-r--r-- | lib/pleroma/uploaders/swift/uploader.ex | 10 | ||||
-rw-r--r-- | lib/pleroma/uploaders/uploader.ex | 20 |
6 files changed, 181 insertions, 0 deletions
diff --git a/lib/pleroma/uploaders/local.ex b/lib/pleroma/uploaders/local.ex new file mode 100644 index 000000000..d96481c8d --- /dev/null +++ b/lib/pleroma/uploaders/local.ex @@ -0,0 +1,51 @@ +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 + settings = Application.get_env(:pleroma, Pleroma.Uploaders.Local) + + Keyword.get(settings, :uploads_url) + |> String.replace("{{file}}", file) + |> String.replace("{{base_url}}", Web.base_url()) + 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 |