defmodule AwsClientUploaderEx.S3Client do
@moduledoc """
module that wraps S3 functions we need to sign / upload files from the client
"""
alias ExAws.S3
import AwsClientUploaderEx.S3Config
require Logger
def signed_download_url(filename, options \\ []),
do: build_presigned_download_url(filename, options)
def signed_upload_url(filename), do: build_presigned_upload_url(filename)
@doc """
if our response does not include a body...
TODO: we need to determine the status of the response!
"""
def list_objects(bucket, opts \\ []) do
options = opts || config_opts()
response =
bucket
|> S3.list_objects()
|> ExAws.request!(options)
case response do
%{body: %{contents: objects}, status_code: 200} ->
objects
|> Enum.map(& &1.key)
|> Enum.map(
&(String.split(&1, "/")
|> List.last())
)
{:error, {:http_error, error_code, "redirected"}} ->
["files not listed due to: #{error_code}"]
_ ->
["files not listed due to: generic aws error"]
end
end
defp config_opts do
[
scheme: scheme(),
host: host(),
region: region(),
access_key_id: aws_access_key_id(),
secret_access_key: aws_secret_key()
]
end
defp build_presigned_upload_url(s3_key) do
signed_url =
AWSAuth.sign_url(
aws_access_key_id(),
aws_secret_key(),
"PUT",
"#{bucket_url()}/#{s3_key}",
region(),
"s3"
)
log_url(signed_url, "upload")
signed_url
end
defp build_presigned_download_url(filename, options) do
if filename do
# we are using the additional `uploads` folder here
s3_key = "/#{bucket_divider()}/#{filename}"
{:ok, signed_url} = S3.presigned_url(aws_config(), :get, bucket(), s3_key, options)
log_url(signed_url, "download")
signed_url
else
nil
end
end
defp log_url(url, type) do
Logger.debug("\n\n-------Signed #{type} url:")
Logger.debug(url)
Logger.debug("----------\n\n")
end
end