Merge branch 'length-limit-bio' into 'develop'
[akkoma] / lib / pleroma / uploaders / s3.ex
index ce0ed3e34f38ae8ff72ce0dd8c766287a2fbc8a5..8c353bed3d71914b0f7fac8425bd1c972655acd0 100644 (file)
@@ -1,24 +1,66 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
 defmodule Pleroma.Uploaders.S3 do
   @behaviour Pleroma.Uploaders.Uploader
+  require Logger
+
+  alias Pleroma.Config
+
+  # The file name is re-encoded with S3's constraints here to comply with previous
+  # links with less strict filenames
+  def get_file(file) do
+    config = Config.get([__MODULE__])
+    bucket = Keyword.fetch!(config, :bucket)
 
-  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)
+    bucket_with_namespace =
+      cond do
+        truncated_namespace = Keyword.get(config, :truncated_namespace) ->
+          truncated_namespace
 
-    {:ok, file_data} = File.read(path)
+        namespace = Keyword.get(config, :bucket_namespace) ->
+          namespace <> ":" <> bucket
 
-    File.rm!(path)
+        true ->
+          bucket
+      end
+
+    {:ok,
+     {:url,
+      Path.join([
+        Keyword.fetch!(config, :public_endpoint),
+        bucket_with_namespace,
+        strict_encode(URI.decode(file))
+      ])}}
+  end
 
-    s3_name = "#{uuid}/#{name}"
+  def put_file(%Pleroma.Upload{} = upload) do
+    config = Config.get([__MODULE__])
+    bucket = Keyword.get(config, :bucket)
 
-    {:ok, _} =
-      ExAws.S3.put_object(bucket, s3_name, file_data, [
+    s3_name = strict_encode(upload.path)
+
+    op =
+      upload.tempfile
+      |> ExAws.S3.Upload.stream_file()
+      |> ExAws.S3.upload(bucket, s3_name, [
         {:acl, :public_read},
-        {:content_type, content_type}
+        {:content_type, upload.content_type}
       ])
-      |> ExAws.request()
 
-    {:ok, "#{public_endpoint}/#{bucket}/#{s3_name}"}
+    case ExAws.request(op) do
+      {:ok, _} ->
+        {:ok, {:file, s3_name}}
+
+      error ->
+        Logger.error("#{__MODULE__}: #{inspect(error)}")
+        {:error, "S3 Upload failed"}
+    end
+  end
+
+  @regex Regex.compile!("[^0-9a-zA-Z!.*/'()_-]")
+  def strict_encode(name) do
+    String.replace(name, @regex, "-")
   end
 end