Merge branch 'feature/upload-limits' into 'develop'

configurable media upload limits

Closes #118

See merge request pleroma/pleroma!401
This commit is contained in:
kaniini 2018-10-29 20:14:10 +00:00
commit a880e0a527
6 changed files with 101 additions and 54 deletions

View File

@ -85,6 +85,9 @@
description: "A Pleroma instance, an alternative fediverse server", description: "A Pleroma instance, an alternative fediverse server",
limit: 5000, limit: 5000,
upload_limit: 16_000_000, upload_limit: 16_000_000,
avatar_upload_limit: 2_000_000,
background_upload_limit: 4_000_000,
banner_upload_limit: 4_000_000,
registrations_open: true, registrations_open: true,
federating: true, federating: true,
allow_relay: true, allow_relay: true,

View File

@ -4,61 +4,76 @@ defmodule Pleroma.Upload do
@storage_backend Application.get_env(:pleroma, Pleroma.Upload) @storage_backend Application.get_env(:pleroma, Pleroma.Upload)
|> Keyword.fetch!(:uploader) |> Keyword.fetch!(:uploader)
def store(%Plug.Upload{} = file, should_dedupe) do def check_file_size(path, nil), do: true
content_type = get_content_type(file.path)
uuid = get_uuid(file, should_dedupe) def check_file_size(path, size_limit) do
name = get_name(file, uuid, content_type, should_dedupe) {:ok, %{size: size}} = File.stat(path)
size <= size_limit
strip_exif_data(content_type, file.path)
{:ok, url_path} =
@storage_backend.put_file(name, uuid, file.path, content_type, should_dedupe)
%{
"type" => "Document",
"url" => [
%{
"type" => "Link",
"mediaType" => content_type,
"href" => url_path
}
],
"name" => name
}
end end
def store(%{"img" => "data:image/" <> image_data}, should_dedupe) do def store(file, should_dedupe, size_limit \\ nil)
def store(%Plug.Upload{} = file, should_dedupe, size_limit) do
content_type = get_content_type(file.path)
with uuid <- get_uuid(file, should_dedupe),
name <- get_name(file, uuid, content_type, should_dedupe),
true <- check_file_size(file.path, size_limit) do
strip_exif_data(content_type, file.path)
{:ok, url_path} =
@storage_backend.put_file(name, uuid, file.path, content_type, should_dedupe)
%{
"type" => "Document",
"url" => [
%{
"type" => "Link",
"mediaType" => content_type,
"href" => url_path
}
],
"name" => name
}
else
_e -> nil
end
end
def store(%{"img" => "data:image/" <> image_data}, should_dedupe, size_limit) do
parsed = Regex.named_captures(~r/(?<filetype>jpeg|png|gif);base64,(?<data>.*)/, image_data) parsed = Regex.named_captures(~r/(?<filetype>jpeg|png|gif);base64,(?<data>.*)/, image_data)
data = Base.decode64!(parsed["data"], ignore: :whitespace) data = Base.decode64!(parsed["data"], ignore: :whitespace)
tmp_path = tempfile_for_image(data) with tmp_path <- tempfile_for_image(data),
uuid <- UUID.generate(),
true <- check_file_size(tmp_path, size_limit) do
content_type = get_content_type(tmp_path)
strip_exif_data(content_type, tmp_path)
uuid = UUID.generate() name =
create_name(
String.downcase(Base.encode16(:crypto.hash(:sha256, data))),
parsed["filetype"],
content_type
)
content_type = get_content_type(tmp_path) {:ok, url_path} =
strip_exif_data(content_type, tmp_path) @storage_backend.put_file(name, uuid, tmp_path, content_type, should_dedupe)
name = %{
create_name( "type" => "Image",
String.downcase(Base.encode16(:crypto.hash(:sha256, data))), "url" => [
parsed["filetype"], %{
content_type "type" => "Link",
) "mediaType" => content_type,
"href" => url_path
{:ok, url_path} = @storage_backend.put_file(name, uuid, tmp_path, content_type, should_dedupe) }
],
%{ "name" => name
"type" => "Image", }
"url" => [ else
%{ _e -> nil
"type" => "Link", end
"mediaType" => content_type,
"href" => url_path
}
],
"name" => name
}
end end
@doc """ @doc """

View File

@ -575,9 +575,12 @@ def fetch_activities_bounded(recipients_to, recipients_cc, opts \\ %{}) do
|> Enum.reverse() |> Enum.reverse()
end end
def upload(file) do def upload(file, size_limit \\ nil) do
data = Upload.store(file, Application.get_env(:pleroma, :instance)[:dedupe_media]) with data <-
Repo.insert(%Object{data: data}) Upload.store(file, Application.get_env(:pleroma, :instance)[:dedupe_media], size_limit),
false <- is_nil(data) do
Repo.insert(%Object{data: data})
end
end end
def user_data_from_user_object(data) do def user_data_from_user_object(data) do

View File

@ -35,6 +35,14 @@ def create_app(conn, params) do
def update_credentials(%{assigns: %{user: user}} = conn, params) do def update_credentials(%{assigns: %{user: user}} = conn, params) do
original_user = user original_user = user
avatar_upload_limit =
Application.get_env(:pleroma, :instance)
|> Keyword.fetch(:avatar_upload_limit)
banner_upload_limit =
Application.get_env(:pleroma, :instance)
|> Keyword.fetch(:banner_upload_limit)
params = params =
if bio = params["note"] do if bio = params["note"] do
Map.put(params, "bio", bio) Map.put(params, "bio", bio)
@ -52,7 +60,7 @@ def update_credentials(%{assigns: %{user: user}} = conn, params) do
user = user =
if avatar = params["avatar"] do if avatar = params["avatar"] do
with %Plug.Upload{} <- avatar, with %Plug.Upload{} <- avatar,
{:ok, object} <- ActivityPub.upload(avatar), {:ok, object} <- ActivityPub.upload(avatar, avatar_upload_limit),
change = Ecto.Changeset.change(user, %{avatar: object.data}), change = Ecto.Changeset.change(user, %{avatar: object.data}),
{:ok, user} = User.update_and_set_cache(change) do {:ok, user} = User.update_and_set_cache(change) do
user user
@ -66,7 +74,7 @@ def update_credentials(%{assigns: %{user: user}} = conn, params) do
user = user =
if banner = params["header"] do if banner = params["header"] do
with %Plug.Upload{} <- banner, with %Plug.Upload{} <- banner,
{:ok, object} <- ActivityPub.upload(banner), {:ok, object} <- ActivityPub.upload(banner, banner_upload_limit),
new_info <- Map.put(user.info, "banner", object.data), new_info <- Map.put(user.info, "banner", object.data),
change <- User.info_changeset(user, %{info: new_info}), change <- User.info_changeset(user, %{info: new_info}),
{:ok, user} <- User.update_and_set_cache(change) do {:ok, user} <- User.update_and_set_cache(change) do

View File

@ -113,6 +113,12 @@ def nodeinfo(conn, %{"version" => "2.0"}) do
staffAccounts: staff_accounts, staffAccounts: staff_accounts,
federation: federation_response, federation: federation_response,
postFormats: Keyword.get(instance, :allowed_post_formats), postFormats: Keyword.get(instance, :allowed_post_formats),
uploadLimits: %{
general: Keyword.get(instance, :upload_limit),
avatar: Keyword.get(instance, :avatar_upload_limit),
banner: Keyword.get(instance, :banner_upload_limit),
background: Keyword.get(instance, :background_upload_limit)
},
features: features features: features
} }
} }

View File

@ -263,7 +263,11 @@ def register(conn, params) do
end end
def update_avatar(%{assigns: %{user: user}} = conn, params) do def update_avatar(%{assigns: %{user: user}} = conn, params) do
{:ok, object} = ActivityPub.upload(params) upload_limit =
Application.get_env(:pleroma, :instance)
|> Keyword.fetch(:avatar_upload_limit)
{:ok, object} = ActivityPub.upload(params, upload_limit)
change = Changeset.change(user, %{avatar: object.data}) change = Changeset.change(user, %{avatar: object.data})
{:ok, user} = User.update_and_set_cache(change) {:ok, user} = User.update_and_set_cache(change)
CommonAPI.update(user) CommonAPI.update(user)
@ -272,7 +276,11 @@ def update_avatar(%{assigns: %{user: user}} = conn, params) do
end end
def update_banner(%{assigns: %{user: user}} = conn, params) do def update_banner(%{assigns: %{user: user}} = conn, params) do
with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}), upload_limit =
Application.get_env(:pleroma, :instance)
|> Keyword.fetch(:banner_upload_limit)
with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, upload_limit),
new_info <- Map.put(user.info, "banner", object.data), new_info <- Map.put(user.info, "banner", object.data),
change <- User.info_changeset(user, %{info: new_info}), change <- User.info_changeset(user, %{info: new_info}),
{:ok, user} <- User.update_and_set_cache(change) do {:ok, user} <- User.update_and_set_cache(change) do
@ -286,7 +294,11 @@ def update_banner(%{assigns: %{user: user}} = conn, params) do
end end
def update_background(%{assigns: %{user: user}} = conn, params) do def update_background(%{assigns: %{user: user}} = conn, params) do
with {:ok, object} <- ActivityPub.upload(params), upload_limit =
Application.get_env(:pleroma, :instance)
|> Keyword.fetch(:background_upload_limit)
with {:ok, object} <- ActivityPub.upload(params, upload_limit),
new_info <- Map.put(user.info, "background", object.data), new_info <- Map.put(user.info, "background", object.data),
change <- User.info_changeset(user, %{info: new_info}), change <- User.info_changeset(user, %{info: new_info}),
{:ok, _user} <- User.update_and_set_cache(change) do {:ok, _user} <- User.update_and_set_cache(change) do