akkoma/lib/pleroma/uploaders/s3.ex

102 lines
2.7 KiB
Elixir
Raw Normal View History

# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
2018-08-27 19:20:54 -06:00
defmodule Pleroma.Uploaders.S3 do
@behaviour Pleroma.Uploaders.Uploader
2018-11-23 09:40:45 -07:00
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
@impl true
2018-11-23 09:40:45 -07:00
def get_file(file) do
config = Config.get([__MODULE__])
2019-01-21 06:42:16 -07:00
bucket = Keyword.fetch!(config, :bucket)
bucket_with_namespace =
cond do
truncated_namespace = Keyword.get(config, :truncated_namespace) ->
truncated_namespace
namespace = Keyword.get(config, :bucket_namespace) ->
namespace <> ":" <> bucket
true ->
bucket
2019-01-21 06:42:16 -07:00
end
2018-11-23 09:40:45 -07:00
{:ok,
{:url,
Path.join([
Keyword.fetch!(config, :public_endpoint),
2019-01-21 06:42:16 -07:00
bucket_with_namespace,
2018-11-23 09:40:45 -07:00
strict_encode(URI.decode(file))
])}}
end
2018-08-27 19:20:54 -06:00
@impl true
2019-02-06 12:19:39 -07:00
def put_file(%Pleroma.Upload{} = upload) do
config = Config.get([__MODULE__])
2018-11-23 09:40:45 -07:00
bucket = Keyword.get(config, :bucket)
streaming = Keyword.get(config, :streaming_enabled)
2018-08-27 19:20:54 -06:00
2018-11-29 13:11:45 -07:00
s3_name = strict_encode(upload.path)
2018-08-27 19:20:54 -06:00
2018-11-23 09:40:45 -07:00
op =
if streaming do
op =
upload.tempfile
|> ExAws.S3.Upload.stream_file()
|> ExAws.S3.upload(bucket, s3_name, [
{:acl, :public_read},
{:content_type, upload.content_type}
])
if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Gun do
# set s3 upload timeout to respect :upload pool timeout
# timeout should be slightly larger, so s3 can retry upload on fail
timeout = Pleroma.HTTP.AdapterHelper.Gun.pool_timeout(:upload) + 1_000
opts = Keyword.put(op.opts, :timeout, timeout)
Map.put(op, :opts, opts)
else
op
end
else
{:ok, file_data} = File.read(upload.tempfile)
ExAws.S3.put_object(bucket, s3_name, file_data, [
{:acl, :public_read},
{:content_type, upload.content_type}
])
end
2018-11-23 09:40:45 -07:00
case ExAws.request(op) do
{:ok, _} ->
{:ok, {:file, s3_name}}
2018-11-23 09:40:45 -07:00
error ->
Logger.error("#{__MODULE__}: #{inspect(error)}")
{:error, "S3 Upload failed"}
end
2018-08-27 19:20:54 -06:00
end
@impl true
def delete_file(file) do
[__MODULE__, :bucket]
|> Config.get()
|> ExAws.S3.delete_object(file)
|> ExAws.request()
|> case do
{:ok, %{status_code: 204}} -> :ok
error -> {:error, inspect(error)}
end
end
2018-11-23 09:40:45 -07:00
@regex Regex.compile!("[^0-9a-zA-Z!.*/'()_-]")
def strict_encode(name) do
String.replace(name, @regex, "-")
end
2018-08-27 19:20:54 -06:00
end