logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

s3.ex (2624B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Uploaders.S3 do
  5. @behaviour Pleroma.Uploaders.Uploader
  6. require Logger
  7. @ex_aws_impl Application.compile_env(:pleroma, [__MODULE__, :ex_aws_impl], ExAws)
  8. @config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config)
  9. # The file name is re-encoded with S3's constraints here to comply with previous
  10. # links with less strict filenames
  11. @impl true
  12. def get_file(file) do
  13. {:ok,
  14. {:url,
  15. Path.join([
  16. Pleroma.Upload.base_url(),
  17. strict_encode(URI.decode(file))
  18. ])}}
  19. end
  20. @impl true
  21. def put_file(%Pleroma.Upload{} = upload) do
  22. config = @config_impl.get([__MODULE__])
  23. bucket = Keyword.get(config, :bucket)
  24. streaming = Keyword.get(config, :streaming_enabled)
  25. s3_name = strict_encode(upload.path)
  26. op =
  27. if streaming do
  28. op =
  29. upload.tempfile
  30. |> ExAws.S3.Upload.stream_file()
  31. |> ExAws.S3.upload(bucket, s3_name, [
  32. {:acl, :public_read},
  33. {:content_type, upload.content_type}
  34. ])
  35. if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Gun do
  36. # set s3 upload timeout to respect :upload pool timeout
  37. # timeout should be slightly larger, so s3 can retry upload on fail
  38. timeout = Pleroma.HTTP.AdapterHelper.Gun.pool_timeout(:upload) + 1_000
  39. opts = Keyword.put(op.opts, :timeout, timeout)
  40. Map.put(op, :opts, opts)
  41. else
  42. op
  43. end
  44. else
  45. {:ok, file_data} = File.read(upload.tempfile)
  46. ExAws.S3.put_object(bucket, s3_name, file_data, [
  47. {:acl, :public_read},
  48. {:content_type, upload.content_type}
  49. ])
  50. end
  51. case @ex_aws_impl.request(op) do
  52. {:ok, _} ->
  53. {:ok, {:file, s3_name}}
  54. error ->
  55. Logger.error("#{__MODULE__}: #{inspect(error)}")
  56. {:error, "S3 Upload failed"}
  57. end
  58. end
  59. @impl true
  60. def delete_file(file) do
  61. [__MODULE__, :bucket]
  62. |> @config_impl.get()
  63. |> ExAws.S3.delete_object(file)
  64. |> @ex_aws_impl.request()
  65. |> case do
  66. {:ok, %{status_code: 204}} -> :ok
  67. error -> {:error, inspect(error)}
  68. end
  69. end
  70. @regex Regex.compile!("[^0-9a-zA-Z!.*/'()_-]")
  71. def strict_encode(name) do
  72. String.replace(name, @regex, "-")
  73. end
  74. end
  75. defmodule Pleroma.Uploaders.S3.ExAwsAPI do
  76. @callback request(op :: ExAws.Operation.t()) :: {:ok, ExAws.Operation.t()} | {:error, term()}
  77. end