From e473bcf7a0390584377d89ff68267a25fe31e44d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Sun, 6 Feb 2022 17:41:15 +0100 Subject: [PATCH] Max media attachment count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- config/config.exs | 3 ++- config/description.exs | 8 ++++++ lib/pleroma/web/common_api/activity_draft.ex | 7 ++++- lib/pleroma/web/common_api/utils.ex | 15 +++++++++++ .../web/mastodon_api/views/instance_view.ex | 1 + test/pleroma/web/common_api_test.exs | 26 +++++++++++++++++++ 6 files changed, 58 insertions(+), 2 deletions(-) diff --git a/config/config.exs b/config/config.exs index 5e82f203c..6a5acda09 100644 --- a/config/config.exs +++ b/config/config.exs @@ -259,7 +259,8 @@ config :pleroma, :instance, privileged_staff: false, max_endorsed_users: 20, birthday_required: false, - birthday_min_age: 0 + birthday_min_age: 0, + max_media_attachments: 1_000 config :pleroma, :welcome, direct_message: [ diff --git a/config/description.exs b/config/description.exs index 3f66877e4..704af8f68 100644 --- a/config/description.exs +++ b/config/description.exs @@ -552,6 +552,14 @@ config :pleroma, :config_description, [ 100_000 ] }, + %{ + key: :max_media_attachments, + type: :integer, + description: "Maximum number of post media attachments", + suggestions: [ + 1_000_000 + ] + }, %{ key: :upload_limit, type: :integer, diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex index b4e3e37ae..451d7323a 100644 --- a/lib/pleroma/web/common_api/activity_draft.ex +++ b/lib/pleroma/web/common_api/activity_draft.ex @@ -112,7 +112,12 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do defp attachments(%{params: params} = draft) do attachments = Utils.attachments_from_ids(params) - %__MODULE__{draft | attachments: attachments} + draft = %__MODULE__{draft | attachments: attachments} + + case Utils.validate_attachments_count(attachments) do + :ok -> draft + {:error, message} -> add_error(draft, message) + end end defp in_reply_to(%{params: %{in_reply_to_status_id: ""}} = draft), do: draft diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index b6feaf32a..5bba01cc4 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -492,4 +492,19 @@ defmodule Pleroma.Web.CommonAPI.Utils do {:error, dgettext("errors", "The status is over the character limit")} end end + + def validate_attachments_count([] = _attachments) do + :ok + end + + def validate_attachments_count(attachments) do + limit = Config.get([:instance, :max_media_attachments]) + count = length(attachments) + + if count <= limit do + :ok + else + {:error, dgettext("errors", "Too many attachments")} + end + end end diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex index fa6c20a30..23770f671 100644 --- a/lib/pleroma/web/mastodon_api/views/instance_view.ex +++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -31,6 +31,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do approval_required: Keyword.get(instance, :account_approval_required), # Extra (not present in Mastodon): max_toot_chars: Keyword.get(instance, :limit), + max_media_attachments: Keyword.get(instance, :max_media_attachments), poll_limits: Keyword.get(instance, :poll_limits), upload_limit: Keyword.get(instance, :upload_limit), avatar_upload_limit: Keyword.get(instance, :avatar_upload_limit), diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs index 4b186ccfc..16af4b923 100644 --- a/test/pleroma/web/common_api_test.exs +++ b/test/pleroma/web/common_api_test.exs @@ -683,6 +683,32 @@ defmodule Pleroma.Web.CommonAPITest do assert {:ok, _activity} = CommonAPI.post(user, %{status: "12345"}) end + test "it validates media attachment limits are correctly enforced" do + clear_config([:instance, :max_media_attachments], 4) + + user = insert(:user) + + file = %Plug.Upload{ + content_type: "image/jpeg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } + + {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id) + + assert {:error, "Too many attachments"} = + CommonAPI.post(user, %{ + status: "", + media_ids: List.duplicate(upload.id, 5) + }) + + assert {:ok, _activity} = + CommonAPI.post(user, %{ + status: "", + media_ids: [upload.id] + }) + end + test "it can handle activities that expire" do user = insert(:user)