From 5bf543ca2402647d55e7517749566070bc50a468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Fri, 12 Jan 2024 16:49:47 +0900 Subject: [PATCH 01/23] =?UTF-8?q?Add:=20Iceshrimp=E3=82=92=E3=82=B9?= =?UTF-8?q?=E3=82=BF=E3=83=B3=E3=83=97=E5=88=A9=E7=94=A8=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E3=82=B5=E3=83=BC=E3=83=90=E3=83=BC=E3=81=A8=E3=81=97=E3=81=A6?= =?UTF-8?q?=E7=99=BB=E9=8C=B2=E3=80=81=E8=A5=A6=E8=A2=A2=E3=82=92=E6=8F=83?= =?UTF-8?q?=E3=81=88=E3=82=8B=20(#451)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/instance_info.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/models/instance_info.rb b/app/models/instance_info.rb index 07e276b4f9..dc6c533c98 100644 --- a/app/models/instance_info.rb +++ b/app/models/instance_info.rb @@ -17,17 +17,17 @@ class InstanceInfo < ApplicationRecord after_commit :reset_cache EMOJI_REACTION_AVAILABLE_SOFTWARES = %w( - misskey - calckey - cherrypick - meisskey - sharkey - firefish - catodon - renedon - fedibird - pleroma akkoma + calckey + catodon + cherrypick + fedibird + firefish + iceshrimp + meisskey + misskey + pleroma + sharkey ).freeze def self.emoji_reaction_available?(domain) From 8cd1d7e5d01faa1996aa6c3194defa9e67df3cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Mon, 15 Jan 2024 12:27:20 +0900 Subject: [PATCH 02/23] =?UTF-8?q?Remove:=20#454=20=E3=83=AA=E3=83=B3?= =?UTF-8?q?=E3=82=AF=E3=83=97=E3=83=AC=E3=83=93=E3=83=A5=E3=83=BC=E3=82=92?= =?UTF-8?q?=E7=94=9F=E6=88=90=E3=81=99=E3=82=8B=E8=A8=AD=E5=AE=9A=E3=81=AE?= =?UTF-8?q?=E5=89=8A=E9=99=A4=E3=80=81=E7=84=A1=E5=8A=B9=E5=8C=96=20(#458)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/concerns/account/other_settings.rb | 8 -------- app/models/concerns/user/has_settings.rb | 4 ---- app/models/user_settings.rb | 1 - app/services/fetch_link_card_service.rb | 2 +- app/views/settings/privacy_extra/show.html.haml | 14 ++++++++++---- config/locales/simple_form.en.yml | 1 - config/locales/simple_form.ja.yml | 2 -- spec/models/account_spec.rb | 16 +++++++++------- spec/services/fetch_link_card_service_spec.rb | 17 ----------------- 9 files changed, 20 insertions(+), 45 deletions(-) diff --git a/app/models/concerns/account/other_settings.rb b/app/models/concerns/account/other_settings.rb index a62bc4195d..7968f857ff 100644 --- a/app/models/concerns/account/other_settings.rb +++ b/app/models/concerns/account/other_settings.rb @@ -15,13 +15,6 @@ module Account::OtherSettings false end - def link_preview? - return user.setting_link_preview if local? && user.present? - return settings['link_preview'] if settings.present? && settings.key?('link_preview') - - true - end - def allow_quote? return user.setting_allow_quote if local? && user.present? return settings['allow_quote'] if settings.present? && settings.key?('allow_quote') @@ -95,7 +88,6 @@ module Account::OtherSettings 'hide_following_count' => hide_following_count?, 'hide_followers_count' => hide_followers_count?, 'translatable_private' => translatable_private?, - 'link_preview' => link_preview?, 'allow_quote' => allow_quote?, 'emoji_reaction_policy' => Setting.enable_emoji_reaction ? emoji_reaction_policy.to_s : 'block', } diff --git a/app/models/concerns/user/has_settings.rb b/app/models/concerns/user/has_settings.rb index adb2257ee9..79072a7f30 100644 --- a/app/models/concerns/user/has_settings.rb +++ b/app/models/concerns/user/has_settings.rb @@ -135,10 +135,6 @@ module User::HasSettings settings['translatable_private'] end - def setting_link_preview - settings['link_preview'] - end - def setting_dtl_force_visibility settings['dtl_force_visibility']&.to_sym || :unchange end diff --git a/app/models/user_settings.rb b/app/models/user_settings.rb index 06dde3f72b..ba5883d03f 100644 --- a/app/models/user_settings.rb +++ b/app/models/user_settings.rb @@ -12,7 +12,6 @@ class UserSettings setting :theme, default: -> { ::Setting.theme } setting :noindex, default: -> { ::Setting.noindex } setting :translatable_private, default: false - setting :link_preview, default: true setting :bio_markdown, default: false setting :discoverable_local, default: false setting :hide_statuses_count, default: false diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index f40abf2ad0..fa445faf2c 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -20,7 +20,7 @@ class FetchLinkCardService < BaseService @status = status @original_url = parse_urls - return if @original_url.nil? || @status.with_preview_card? || !@status.account.link_preview? + return if @original_url.nil? || @status.with_preview_card? @url = @original_url.to_s diff --git a/app/views/settings/privacy_extra/show.html.haml b/app/views/settings/privacy_extra/show.html.haml index 2d0927eeb2..9c63542b26 100644 --- a/app/views/settings/privacy_extra/show.html.haml +++ b/app/views/settings/privacy_extra/show.html.haml @@ -19,10 +19,16 @@ = ff.input :translatable_private, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_translatable_private') .fields-group - = ff.input :link_preview, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_link_preview'), hint: I18n.t('simple_form.hints.defaults.setting_link_preview') - - .fields-group - = f.input :subscription_policy, kmyblue: true, collection: %w(allow followers_only block), label_method: ->(item) { safe_join([t("simple_form.labels.subscription_policy.#{item}")]) }, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', wrapper: :with_floating_label, label: t('simple_form.labels.defaults.subscription_policy'), hint: t('simple_form.hints.defaults.subscription_policy') + = f.input :subscription_policy, + as: :radio_buttons, + collection: %w(allow followers_only block), + collection_wrapper_tag: 'ul', + hint: t('simple_form.hints.defaults.subscription_policy'), + item_wrapper_tag: 'li', + kmyblue: true, + label: t('simple_form.labels.defaults.subscription_policy'), + label_method: ->(item) { safe_join([t("simple_form.labels.subscription_policy.#{item}")]) }, + wrapper: :with_floating_label .fields-group = ff.input :allow_quote, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_allow_quote'), hint: false diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 8fc1cb93f3..c0dc68c385 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -278,7 +278,6 @@ en: setting_hide_network: Hide your social graph setting_hide_recent_emojis: Hide recent emojis setting_hide_statuses_count: Hide statuses count - setting_link_preview: Generate post link preview card setting_lock_follow_from_bot: Request approval about bot follow setting_public_post_to_unlisted: Convert public post to public unlisted if not using Web app setting_reduce_motion: Reduce motion in animations diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index ec28fb0f06..ffefa6b347 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -79,7 +79,6 @@ ja: setting_emoji_reaction_streaming_notify_impl2: 当該サーバーの独自機能に対応したアプリを利用時に、スタンプ機能を利用できます。動作確認していないため(そもそもそのようなアプリ自体を確認できていないため)正しく動かない場合があります setting_enable_emoji_reaction: この機能を無効にしても、他の人はあなたの投稿にスタンプをつけられます setting_hide_network: フォローとフォロワーの情報がプロフィールページで見られないようにします - setting_link_preview: プレビュー生成を停止することは、センシティブなサイトへのリンクを頻繁に投稿する人にも有効かもしれません setting_public_post_to_unlisted: 未対応のサードパーティアプリからもローカル公開で投稿できますが、公開投稿はWeb以外できなくなります setting_reject_unlisted_subscription: Misskeyやそのフォークは、フォローしていないアカウントの「非収載」投稿を **購読・検索** することができます。これはkmyblueの挙動と異なります。そのようなサーバーに、指定した公開範囲の投稿を「フォロワーのみ」として配送します。ただし構造上、完璧な対応は困難でたまに非収載として配信されること、ご理解ください setting_show_application: 投稿するのに使用したアプリが投稿の詳細ビューに表示されるようになります @@ -287,7 +286,6 @@ ja: setting_hide_network: 繋がりを隠す setting_hide_recent_emojis: 絵文字ピッカーで最近使用した絵文字を隠す(絵文字デッキのみを表示する) setting_hide_statuses_count: 投稿数を隠す - setting_link_preview: リンクのプレビューを生成する setting_lock_follow_from_bot: botからのフォローを承認制にする setting_show_quote_in_home: ホーム・リスト・アンテナなどで引用を表示する setting_show_quote_in_public: 公開タイムライン(ローカル・連合)で引用を表示する diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 5d6fccd3b3..d2828cd375 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -397,13 +397,9 @@ RSpec.describe Account do describe '#public_settings_for_local' do subject { account.public_settings_for_local } - let(:account) { Fabricate(:user, settings: { link_preview: false, allow_quote: true, hide_statuses_count: true, emoji_reaction_policy: :followers_only }).account } + let(:account) { Fabricate(:user, settings: { allow_quote: true, hide_statuses_count: true, emoji_reaction_policy: :followers_only }).account } shared_examples 'some settings' do |permitted, emoji_reaction_policy| - it 'link_preview is disallowed' do - expect(subject['link_preview']).to be permitted.include?(:link_preview) - end - it 'allow_quote is allowed' do expect(subject['allow_quote']).to be permitted.include?(:allow_quote) end @@ -423,8 +419,14 @@ RSpec.describe Account do it_behaves_like 'some settings', %i(allow_quote hide_statuses_count), 'followers_only' + context 'when default true setting is set false' do + let(:account) { Fabricate(:user, settings: { allow_quote: false, hide_statuses_count: true, emoji_reaction_policy: :followers_only }).account } + + it_behaves_like 'some settings', %i(hide_statuses_count), 'followers_only' + end + context 'when remote user' do - let(:account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor', settings: { 'link_preview' => false, 'allow_quote' => true, 'hide_statuses_count' => true, 'emoji_reaction_policy' => 'followers_only' }) } + let(:account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor', settings: { 'allow_quote' => true, 'hide_statuses_count' => true, 'emoji_reaction_policy' => 'followers_only' }) } it_behaves_like 'some settings', %i(allow_quote hide_statuses_count), 'followers_only' end @@ -432,7 +434,7 @@ RSpec.describe Account do context 'when remote user by server other_settings is not supported' do let(:account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor') } - it_behaves_like 'some settings', %i(link_preview allow_quote), 'allow' + it_behaves_like 'some settings', %i(allow_quote), 'allow' end end diff --git a/spec/services/fetch_link_card_service_spec.rb b/spec/services/fetch_link_card_service_spec.rb index df44c03e10..3273351b9a 100644 --- a/spec/services/fetch_link_card_service_spec.rb +++ b/spec/services/fetch_link_card_service_spec.rb @@ -253,15 +253,6 @@ RSpec.describe FetchLinkCardService, type: :service do expect(status.preview_card.title).to eq 'Hello world' end end - - context 'with URL but author is not allow preview card' do - let(:account) { Fabricate(:user, settings: { link_preview: false }).account } - let(:status) { Fabricate(:status, text: 'http://example.com/html', account: account) } - - it 'not create preview card' do - expect(status.preview_card).to be_nil - end - end end context 'with a remote status' do @@ -282,14 +273,6 @@ RSpec.describe FetchLinkCardService, type: :service do it 'ignores URLs to hashtags' do expect(a_request(:get, 'https://quitter.se/tag/wannacry')).to_not have_been_made end - - context 'with URL but author is not allow preview card' do - let(:account) { Fabricate(:account, domain: 'example.com', settings: { link_preview: false }) } - - it 'not create link preview' do - expect(status.preview_card).to be_nil - end - end end context 'with a remote status of reference' do From cc408a5e7daf534f3a1354eda208fde7a32faa39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Mon, 15 Jan 2024 12:27:38 +0900 Subject: [PATCH 03/23] =?UTF-8?q?Fix:=20=E3=83=96=E3=83=BC=E3=82=B9?= =?UTF-8?q?=E3=83=88=E6=99=82=E3=81=AB=E9=81=B8=E6=8A=9E=E3=81=A7=E3=81=8D?= =?UTF-8?q?=E3=82=8B=E5=85=AC=E9=96=8B=E7=AF=84=E5=9B=B2=E3=81=AB=E9=99=90?= =?UTF-8?q?=E5=AE=9A=E6=8A=95=E7=A8=BF=E3=81=8C=E5=90=AB=E3=81=BE=E3=82=8C?= =?UTF-8?q?=E3=82=8B=E5=95=8F=E9=A1=8C=20(#460)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/compose/components/privacy_dropdown.jsx | 5 +++++ .../mastodon/features/ui/components/boost_modal.jsx | 1 + 2 files changed, 6 insertions(+) diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx index db4dcd5f51..2f3114f23e 100644 --- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx +++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx @@ -169,6 +169,7 @@ class PrivacyDropdown extends PureComponent { value: PropTypes.string.isRequired, onChange: PropTypes.func.isRequired, noDirect: PropTypes.bool, + noLimited: PropTypes.bool, replyToLimited: PropTypes.bool, container: PropTypes.func, disabled: PropTypes.bool, @@ -260,6 +261,10 @@ class PrivacyDropdown extends PureComponent { ); } + if (this.props.noLimited) { + this.options = this.options.filter((opt) => !['mutual', 'circle'].includes(opt.value)); + } + this.selectableOptions = [...this.options]; if (!enableLoginPrivacy) { diff --git a/app/javascript/mastodon/features/ui/components/boost_modal.jsx b/app/javascript/mastodon/features/ui/components/boost_modal.jsx index 150cc51357..1beb81c3f2 100644 --- a/app/javascript/mastodon/features/ui/components/boost_modal.jsx +++ b/app/javascript/mastodon/features/ui/components/boost_modal.jsx @@ -110,6 +110,7 @@ class BoostModal extends ImmutablePureComponent { {status.get('visibility') !== 'private' && !status.get('reblogged') && ( Date: Mon, 15 Jan 2024 18:32:35 +0900 Subject: [PATCH 04/23] =?UTF-8?q?Fix:=20=E3=83=95=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=83=89=E3=82=B5=E3=83=BC=E3=83=90=E3=83=BC=E3=81=AB=E3=83=AD?= =?UTF-8?q?=E3=82=B0=E3=82=A4=E3=83=B3=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC?= =?UTF-8?q?=E3=81=AE=E3=81=BF=E6=8A=95=E7=A8=BF=E3=81=8C=E9=85=8D=E9=80=81?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C=20(#463)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/status.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/status.rb b/app/models/status.rb index 60c0839d18..6fdda2a28f 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -618,7 +618,7 @@ class Status < ApplicationRecord end def distributable_friend? - public_visibility? || public_unlisted_visibility? || (unlisted_visibility? && (public_searchability? || public_unlisted_searchability?)) + public_visibility? || public_unlisted_visibility? || login_visibility? || (unlisted_visibility? && (public_searchability? || public_unlisted_searchability?)) end private From ef3eb48932782a65d53e559a2ee82c90e4c54b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Thu, 18 Jan 2024 10:13:32 +0900 Subject: [PATCH 05/23] =?UTF-8?q?Fix:=20#303=20=E9=99=90=E5=AE=9A=E6=8A=95?= =?UTF-8?q?=E7=A8=BF=E3=81=AE=E3=82=B9=E3=82=BF=E3=83=B3=E3=83=97=E3=81=8C?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=83=AA=E3=83=BC=E3=83=9F=E3=83=B3=E3=82=B0?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=81=A6=E3=81=84=E3=81=AA=E3=81=84=20(#481)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/concerns/account_scope.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/services/concerns/account_scope.rb b/app/services/concerns/account_scope.rb index 1d617fd731..f670d17f38 100644 --- a/app/services/concerns/account_scope.rb +++ b/app/services/concerns/account_scope.rb @@ -7,6 +7,8 @@ module AccountScope scope_local when :private scope_account_local_followers(status.account) + when :limited + scope_status_all_mentioned(status) else scope_status_mentioned(status) end @@ -24,6 +26,10 @@ module AccountScope Account.local.where(id: status.active_mentions.select(:account_id)).reorder(nil) end + def scope_status_all_mentioned(status) + Account.local.where(id: status.mentions.select(:account_id)).reorder(nil) + end + # TODO: not work def scope_list_following_account(account) account.lists_for_local_distribution.select(:id).reorder(nil) From 65cc1273aafe78c0009a4f78f5d9d0d275ca6fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Thu, 18 Jan 2024 13:09:20 +0900 Subject: [PATCH 06/23] =?UTF-8?q?Fix:=20=E6=8A=95=E7=A8=BF=E3=81=A7?= =?UTF-8?q?=E3=81=AF=E3=81=AA=E3=81=84=E3=83=AA=E3=83=B3=E3=82=AF=E3=82=92?= =?UTF-8?q?=E5=8F=82=E7=85=A7=E3=81=97=E3=81=9F=E3=81=A8=E3=81=8D=E3=81=AB?= =?UTF-8?q?=E3=83=AA=E3=83=B3=E3=82=AF=E3=83=97=E3=83=AC=E3=83=93=E3=83=A5?= =?UTF-8?q?=E3=83=BC=E3=81=8C=E7=94=9F=E6=88=90=E3=81=95=E3=82=8C=E3=81=AA?= =?UTF-8?q?=E3=81=84=E5=95=8F=E9=A1=8C=20(#482)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/fetch_link_card_service.rb | 4 ++ spec/services/fetch_link_card_service_spec.rb | 49 +++++++++++++++++-- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index fa445faf2c..6c84f6d3b4 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -88,6 +88,10 @@ class FetchLinkCardService < BaseService end def referenced_urls + referenced_urls_raw.filter { |uri| ActivityPub::TagManager.instance.uri_to_resource(uri, Status, url: true).present? } + end + + def referenced_urls_raw unless @status.local? document = Nokogiri::HTML(@status.text) document.search('a[href^="http://"]', 'a[href^="https://"]').each do |link| diff --git a/spec/services/fetch_link_card_service_spec.rb b/spec/services/fetch_link_card_service_spec.rb index 3273351b9a..654da1e0d4 100644 --- a/spec/services/fetch_link_card_service_spec.rb +++ b/spec/services/fetch_link_card_service_spec.rb @@ -7,6 +7,7 @@ RSpec.describe FetchLinkCardService, type: :service do let(:html) { 'Hello world' } let(:oembed_cache) { nil } + let(:custom_before) { false } before do stub_request(:get, 'http://example.com/html').to_return(headers: { 'Content-Type' => 'text/html' }, body: html) @@ -30,7 +31,7 @@ RSpec.describe FetchLinkCardService, type: :service do Rails.cache.write('oembed_endpoint:example.com', oembed_cache) if oembed_cache - subject.call(status) + subject.call(status) unless custom_before end context 'with a local status' do @@ -236,16 +237,46 @@ RSpec.describe FetchLinkCardService, type: :service do end end - context 'with URL of reference' do - let(:status) { Fabricate(:status, text: 'RT http://example.com/html') } + context 'with URI of reference and normal page' do + let(:status) { Fabricate(:status, text: 'RT http://example.com/text http://example.com/html') } + let(:custom_before) { true } + + before { Fabricate(:status, uri: 'http://example.com/text') } it 'creates preview card' do + subject.call(status) + expect(status.preview_card).to_not be_nil + expect(status.preview_card.url).to eq 'http://example.com/html' + expect(status.preview_card.title).to eq 'Hello world' + end + end + + context 'with URI of reference' do + let(:status) { Fabricate(:status, text: 'RT http://example.com/text') } + let(:custom_before) { true } + + before { Fabricate(:status, uri: 'http://example.com/text') } + + it 'does not create preview card' do + subject.call(status) expect(status.preview_card).to be_nil end end - context 'with URL of reference and normal page' do - let(:status) { Fabricate(:status, text: 'RT http://example.com/text http://example.com/html') } + context 'with URL of reference' do + let(:status) { Fabricate(:status, text: 'RT http://example.com/text') } + let(:custom_before) { true } + + before { Fabricate(:status, uri: 'http://example.com/text/activity', url: 'http://example.com/text') } + + it 'does not create preview card' do + subject.call(status) + expect(status.preview_card).to be_nil + end + end + + context 'with reference normal URL' do + let(:status) { Fabricate(:status, text: 'RT http://example.com/html') } it 'creates preview card' do expect(status.preview_card).to_not be_nil @@ -281,8 +312,12 @@ RSpec.describe FetchLinkCardService, type: :service do RT Hello  TEXT end + let(:custom_before) { true } + + before { Fabricate(:status, uri: 'http://example.com/html') } it 'creates preview card' do + subject.call(status) expect(status.preview_card).to be_nil end end @@ -294,8 +329,12 @@ RSpec.describe FetchLinkCardService, type: :service do Hello  TEXT end + let(:custom_before) { true } + + before { Fabricate(:status, uri: 'http://example.com/html') } it 'creates preview card' do + subject.call(status) expect(status.preview_card).to_not be_nil expect(status.preview_card.url).to eq 'http://example.com/html_sub' expect(status.preview_card.title).to eq 'Hello world' From 201fd37bc3078f092f11e0431206a04d7bb1e794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Mon, 22 Jan 2024 08:50:44 +0900 Subject: [PATCH 07/23] =?UTF-8?q?Fix:=20=E3=83=89=E3=83=A1=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E3=83=96=E3=83=AD=E3=83=83=E3=82=AF=E3=81=8COutbox?= =?UTF-8?q?=E3=81=AB=E3=81=8A=E3=81=84=E3=81=A6=E5=8B=95=E4=BD=9C=E3=81=97?= =?UTF-8?q?=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C=20(#491)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/account_statuses_filter.rb | 7 ++- spec/lib/account_statuses_filter_spec.rb | 74 ++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/app/lib/account_statuses_filter.rb b/app/lib/account_statuses_filter.rb index d32f6d7463..719181b8b2 100644 --- a/app/lib/account_statuses_filter.rb +++ b/app/lib/account_statuses_filter.rb @@ -33,7 +33,8 @@ class AccountStatusesFilter available_visibilities -= [:unlisted] if (domain_block&.detect_invalid_subscription || misskey_software?) && @account.user&.setting_reject_unlisted_subscription available_visibilities -= [:login] if current_account.nil? - scope.merge!(scope.where(spoiler_text: ['', nil])) if domain_block&.reject_send_sensitive + scope.merge!(scope.where(sensitive: false)) if domain_block&.reject_send_sensitive + scope.merge!(scope.where(searchability: available_searchabilities)) scope.merge!(scope.where(visibility: available_visibilities)) @@ -153,9 +154,9 @@ class AccountStatusesFilter end def domain_block - return nil if @account.nil? || @account.local? + return nil if @current_account.nil? || @current_account.local? - @domain_block = DomainBlock.find_by(domain: @account.domain) + @domain_block = DomainBlock.find_by(domain: @current_account.domain) end def misskey_software? diff --git a/spec/lib/account_statuses_filter_spec.rb b/spec/lib/account_statuses_filter_spec.rb index f8380ca322..fd5357c1bb 100644 --- a/spec/lib/account_statuses_filter_spec.rb +++ b/spec/lib/account_statuses_filter_spec.rb @@ -267,6 +267,80 @@ RSpec.describe AccountStatusesFilter do it_behaves_like 'filter params' end + context 'when accessed by a remote account' do + let(:current_account) { Fabricate(:account, uri: 'https://example.com/', domain: 'example.com') } + let!(:sensitive_status_with_cw) { Fabricate(:status, account: account, visibility: :public, spoiler_text: 'CW', sensitive: true) } + let!(:sensitive_status_with_media) do + Fabricate(:status, account: account, visibility: :public, sensitive: true).tap do |status| + Fabricate(:media_attachment, account: account, status: status) + end + end + + shared_examples 'as_like_public_visibility' do + it 'returns private statuses, replies, and reblogs' do + expect(results_unique_visibilities).to match_array %w(login unlisted public_unlisted public) + + expect(results_in_reply_to_ids).to_not be_empty + + expect(results_reblog_of_ids).to_not be_empty + end + + context 'when there is a direct status mentioning the non-follower' do + let!(:direct_status) { status_with_mention!(:direct, current_account) } + + it 'returns the direct status' do + expect(results_ids).to include(direct_status.id) + end + end + + context 'when there is a direct status mentioning other user' do + let!(:direct_status) { status_with_mention!(:direct) } + + it 'not returns the direct status' do + expect(results_ids).to_not include(direct_status.id) + end + end + + context 'when there is a limited status mentioning the non-follower' do + let!(:limited_status) { status_with_mention!(:limited, current_account) } + + it 'returns the limited status' do + expect(results_ids).to include(limited_status.id) + end + end + + context 'when there is a limited status mentioning other user' do + let!(:limited_status) { status_with_mention!(:limited) } + + it 'not returns the limited status' do + expect(results_ids).to_not include(limited_status.id) + end + end + end + + it_behaves_like 'as_like_public_visibility' + it_behaves_like 'filter params' + + it 'returns the sensitive status' do + expect(results_ids).to include(sensitive_status_with_cw.id) + expect(results_ids).to include(sensitive_status_with_media.id) + end + + context 'when domain-blocked reject_media' do + before do + Fabricate(:domain_block, domain: 'example.com', severity: :noop, reject_send_sensitive: true) + end + + it_behaves_like 'as_like_public_visibility' + it_behaves_like 'filter params' + + it 'does not return the sensitive status' do + expect(results_ids).to_not include(sensitive_status_with_cw.id) + expect(results_ids).to_not include(sensitive_status_with_media.id) + end + end + end + private def results_unique_visibilities From d87a11bc7de1c6191e8a68163d21f1dd0eebccc0 Mon Sep 17 00:00:00 2001 From: KMY Date: Wed, 24 Jan 2024 20:37:27 +0900 Subject: [PATCH 08/23] =?UTF-8?q?Add:=20Misskey=E3=81=AB=E7=9B=B8=E4=BA=92?= =?UTF-8?q?=E9=99=90=E5=AE=9A=E6=8A=95=E7=A8=BF=E3=82=92=E9=85=8D=E9=80=81?= =?UTF-8?q?=E3=81=97=E3=81=AA=E3=81=84=E3=82=AA=E3=83=97=E3=82=B7=E3=83=A7?= =?UTF-8?q?=E3=83=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/concerns/user/has_settings.rb | 4 ++ app/models/user_settings.rb | 1 + app/services/process_mentions_service.rb | 5 +- .../settings/privacy_extra/show.html.haml | 3 ++ config/locales/simple_form.en.yml | 1 + config/locales/simple_form.ja.yml | 2 + spec/services/post_status_service_spec.rb | 53 ++++++++++++++----- 7 files changed, 55 insertions(+), 14 deletions(-) diff --git a/app/models/concerns/user/has_settings.rb b/app/models/concerns/user/has_settings.rb index 79072a7f30..0cd99a2809 100644 --- a/app/models/concerns/user/has_settings.rb +++ b/app/models/concerns/user/has_settings.rb @@ -127,6 +127,10 @@ module User::HasSettings settings['allow_quote'] end + def setting_reject_send_limited_to_suspects + settings['reject_send_limited_to_suspects'] + end + def setting_noindex settings['noindex'] end diff --git a/app/models/user_settings.rb b/app/models/user_settings.rb index ba5883d03f..9d441c6508 100644 --- a/app/models/user_settings.rb +++ b/app/models/user_settings.rb @@ -41,6 +41,7 @@ class UserSettings setting :dtl_force_subscribable, default: false setting :lock_follow_from_bot, default: false setting :allow_quote, default: true + setting :reject_send_limited_to_suspects, default: false setting_inverse_alias :indexable, :noindex diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index ece2e1aa1e..ebd5d260f0 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -105,7 +105,10 @@ class ProcessMentionsService < BaseService def process_mutual! mentioned_account_ids = @current_mentions.map(&:account_id) - @status.account.mutuals.reorder(nil).find_each do |target_account| + mutuals = @status.account.mutuals + mutuals = mutuals.where.not(domain: InstanceInfo.where(software: 'misskey').select(:domain)).or(mutuals.where(domain: nil)) if @status.account.user&.setting_reject_send_limited_to_suspects + + mutuals.reorder(nil).find_each do |target_account| @current_mentions << @status.mentions.new(silent: true, account: target_account) unless mentioned_account_ids.include?(target_account.id) end end diff --git a/app/views/settings/privacy_extra/show.html.haml b/app/views/settings/privacy_extra/show.html.haml index 9c63542b26..14ad50e261 100644 --- a/app/views/settings/privacy_extra/show.html.haml +++ b/app/views/settings/privacy_extra/show.html.haml @@ -45,5 +45,8 @@ .fields-group = ff.input :reject_unlisted_subscription, kmyblue: true, as: :boolean, wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_reject_unlisted_subscription'), hint: I18n.t('simple_form.hints.defaults.setting_reject_unlisted_subscription') + .fields-group + = ff.input :reject_send_limited_to_suspects, kmyblue: true, as: :boolean, wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_reject_send_limited_to_suspects'), hint: I18n.t('simple_form.hints.defaults.setting_reject_send_limited_to_suspects') + .actions = f.button :button, t('generic.save_changes'), type: :submit diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index c0dc68c385..75d1dd0244 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -282,6 +282,7 @@ en: setting_public_post_to_unlisted: Convert public post to public unlisted if not using Web app setting_reduce_motion: Reduce motion in animations setting_reject_public_unlisted_subscription: Reject sending public unlisted visibility/non-public searchability posts to Misskey, Calckey + setting_reject_send_limited_to_suspects: Reject sending mutual posts to Misskey setting_reject_unlisted_subscription: Reject sending unlisted visibility/non-public searchability posts to Misskey, Calckey setting_send_without_domain_blocks: Send your post to all server with administrator set as rejecting-post-server for protect you [DEPRECATED] setting_show_application: Disclose application used to send posts diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index ffefa6b347..840e0ca4c8 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -80,6 +80,7 @@ ja: setting_enable_emoji_reaction: この機能を無効にしても、他の人はあなたの投稿にスタンプをつけられます setting_hide_network: フォローとフォロワーの情報がプロフィールページで見られないようにします setting_public_post_to_unlisted: 未対応のサードパーティアプリからもローカル公開で投稿できますが、公開投稿はWeb以外できなくなります + setting_reject_send_limited_to_suspects: これは「相互のみ」投稿に適用されます。サークル投稿は例外なく配送されます。一部のMisskeyサーバーが独自に限定投稿へ対応しましたが、相互のみ投稿を行うたびに相手に通知されるなど複数の問題があるため、気になる人向けの設定です setting_reject_unlisted_subscription: Misskeyやそのフォークは、フォローしていないアカウントの「非収載」投稿を **購読・検索** することができます。これはkmyblueの挙動と異なります。そのようなサーバーに、指定した公開範囲の投稿を「フォロワーのみ」として配送します。ただし構造上、完璧な対応は困難でたまに非収載として配信されること、ご理解ください setting_show_application: 投稿するのに使用したアプリが投稿の詳細ビューに表示されるようになります setting_single_ref_to_quote: 当サーバーがまだ対象投稿を取り込んでいない場合、引用が相手に正常に認識されない場合があります @@ -293,6 +294,7 @@ ja: setting_public_post_to_unlisted: サードパーティから公開範囲「公開」で投稿した場合、「ローカル公開」に変更する setting_reduce_motion: アニメーションの動きを減らす setting_reject_public_unlisted_subscription: Misskey系サーバーに「ローカル公開」かつ検索許可「誰でも以外」の投稿を「フォロワーのみ」に変換して配送する + setting_reject_send_limited_to_suspects: Misskey系サーバーに「相互のみ」投稿を配送しない setting_reject_unlisted_subscription: Misskey系サーバーに「非収載」かつ検索許可「誰でも以外」の投稿を「フォロワーのみ」に変換して配送する setting_send_without_domain_blocks: 管理人の設定した配送停止設定を拒否する (非推奨) setting_show_application: 送信したアプリを開示する diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb index 455dac4e7e..238878bb72 100644 --- a/spec/services/post_status_service_spec.rb +++ b/spec/services/post_status_service_spec.rb @@ -192,21 +192,48 @@ RSpec.describe PostStatusService, type: :service do expect(mention_service).to have_received(:call).with(status, limited_type: '', circle: nil, save_records: false) end - it 'mutual visibility' do - account = Fabricate(:account) - mutual_account = Fabricate(:account) - other_account = Fabricate(:account) - text = 'This is an English text.' + context 'with mutual visibility' do + let(:sender) { Fabricate(:user).account } + let(:io_account) { Fabricate(:account, domain: 'misskey.io', uri: 'https://misskey.io/actor') } + let(:local_account) { Fabricate(:account) } + let(:remote_account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor') } + let(:follower) { Fabricate(:account) } + let(:followee) { Fabricate(:account) } - mutual_account.follow!(account) - account.follow!(mutual_account) - other_account.follow!(account) - status = subject.call(account, text: text, visibility: 'mutual') + before do + Fabricate(:instance_info, domain: 'misskey.io', software: 'misskey') + io_account.follow!(sender) + local_account.follow!(sender) + remote_account.follow!(sender) + follower.follow!(sender) + sender.follow!(io_account) + sender.follow!(local_account) + sender.follow!(remote_account) + sender.follow!(followee) + end - expect(status.visibility).to eq 'limited' - expect(status.limited_scope).to eq 'mutual' - expect(status.mentioned_accounts.count).to eq 1 - expect(status.mentioned_accounts.first.id).to eq mutual_account.id + it 'visibility is set' do + status = subject.call(sender, text: 'text', visibility: 'mutual') + + expect(status.visibility).to eq 'limited' + expect(status.limited_scope).to eq 'mutual' + end + + it 'sent to mutuals' do + status = subject.call(sender, text: 'text', visibility: 'mutual') + + expect(status.mentioned_accounts.count).to eq 3 + expect(status.mentioned_accounts.pluck(:id)).to contain_exactly(io_account.id, local_account.id, remote_account.id) + end + + it 'sent to mutuals without misskey.io users' do + sender.user.update!(settings: { reject_send_limited_to_suspects: true }) + + status = subject.call(sender, text: 'text', visibility: 'mutual') + + expect(status.mentioned_accounts.count).to eq 2 + expect(status.mentioned_accounts.pluck(:id)).to contain_exactly(local_account.id, remote_account.id) + end end it 'limited visibility and direct searchability' do From 7d9d2e2e86f233ca57e59a8209a22d160b8a7560 Mon Sep 17 00:00:00 2001 From: KMY Date: Wed, 24 Jan 2024 21:41:30 +0900 Subject: [PATCH 09/23] Fix test --- spec/services/post_status_service_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb index 238878bb72..535bbd1311 100644 --- a/spec/services/post_status_service_spec.rb +++ b/spec/services/post_status_service_spec.rb @@ -194,13 +194,15 @@ RSpec.describe PostStatusService, type: :service do context 'with mutual visibility' do let(:sender) { Fabricate(:user).account } - let(:io_account) { Fabricate(:account, domain: 'misskey.io', uri: 'https://misskey.io/actor') } + let(:io_account) { Fabricate(:account, domain: 'misskey.io', uri: 'https://misskey.io/actor', inbox_url: 'https://misskey.io/inbox') } let(:local_account) { Fabricate(:account) } - let(:remote_account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor') } + let(:remote_account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor', inbox_url: 'https://example.com/inbox') } let(:follower) { Fabricate(:account) } let(:followee) { Fabricate(:account) } before do + stub_request(:post, 'https://misskey.io/inbox').to_return(status: 200) + stub_request(:post, 'https://example.com/inbox').to_return(status: 200) Fabricate(:instance_info, domain: 'misskey.io', software: 'misskey') io_account.follow!(sender) local_account.follow!(sender) From e83c4c56047233f6632f4cfc0b61721652184986 Mon Sep 17 00:00:00 2001 From: KMY Date: Fri, 19 Jan 2024 07:58:06 +0900 Subject: [PATCH 10/23] Bump version to 10.1 --- lib/mastodon/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 007c768cdd..b575459465 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -9,7 +9,7 @@ module Mastodon end def kmyblue_minor - 0 + 1 end def kmyblue_flag From f40e951d291e6ad6695d830373e44a8779df7477 Mon Sep 17 00:00:00 2001 From: MitarashiDango Date: Sat, 13 Jan 2024 00:58:28 +0900 Subject: [PATCH 11/23] Fix Undo Announce activity is not sent, when not followed by the reblogged post author (#18482) Co-authored-by: Claire --- app/lib/status_reach_finder.rb | 62 +++++++++------------ app/services/reblog_service.rb | 6 +- spec/lib/activitypub/tag_manager_spec.rb | 8 +++ spec/services/reblog_service_spec.rb | 4 -- spec/services/remove_status_service_spec.rb | 18 ++++++ 5 files changed, 54 insertions(+), 44 deletions(-) diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb index 0307e98c7b..f6570ebbd8 100644 --- a/app/lib/status_reach_finder.rb +++ b/app/lib/status_reach_finder.rb @@ -38,47 +38,39 @@ class StatusReachFinder private def reached_account_inboxes + Account.where(id: reached_account_ids).where.not(domain: banned_domains).inboxes + end + + def reached_account_inboxes_for_misskey + Account.where(id: reached_account_ids, domain: banned_domains_for_misskey - friend_domains).inboxes + end + + def reached_account_inboxes_for_friend + Account.where(id: reached_account_ids, domain: friend_domains).inboxes + end + + def reached_account_ids # When the status is a reblog, there are no interactions with it # directly, we assume all interactions are with the original one if @status.reblog? - [] + [reblog_of_account_id] elsif @status.limited_visibility? - Account.where(id: mentioned_account_ids).where.not(domain: banned_domains).inboxes + [mentioned_account_ids] else - Account.where(id: reached_account_ids).where.not(domain: banned_domains + friend_domains).inboxes - end - end - - def reached_account_inboxes_for_misskey - if @status.reblog? || @status.limited_visibility? - [] - else - Account.where(id: reached_account_ids, domain: banned_domains_for_misskey - friend_domains).inboxes - end - end - - def reached_account_inboxes_for_friend - if @status.reblog? || @status.limited_visibility? - [] - else - Account.where(id: reached_account_ids, domain: friend_domains).inboxes - end - end - - def reached_account_ids - [ - replied_to_account_id, - reblog_of_account_id, - mentioned_account_ids, - reblogs_account_ids, - favourites_account_ids, - replies_account_ids, - quoted_account_id, - ].tap do |arr| - arr.flatten! - arr.compact! - arr.uniq! + [ + replied_to_account_id, + reblog_of_account_id, + mentioned_account_ids, + reblogs_account_ids, + favourites_account_ids, + replies_account_ids, + quoted_account_id, + ].tap do |arr| + arr.flatten! + arr.compact! + arr.uniq! + end end end diff --git a/app/services/reblog_service.rb b/app/services/reblog_service.rb index a36eda4673..76aaf83c04 100644 --- a/app/services/reblog_service.rb +++ b/app/services/reblog_service.rb @@ -44,11 +44,7 @@ class ReblogService < BaseService def create_notification(reblog) reblogged_status = reblog.reblog - if reblogged_status.account.local? - LocalNotificationWorker.perform_async(reblogged_status.account_id, reblog.id, reblog.class.name, 'reblog') - elsif reblogged_status.account.activitypub? && !reblogged_status.account.following?(reblog.account) - ActivityPub::DeliveryWorker.perform_async(build_json(reblog), reblog.account_id, reblogged_status.account.inbox_url) - end + LocalNotificationWorker.perform_async(reblogged_status.account_id, reblog.id, reblog.class.name, 'reblog') if reblogged_status.account.local? end def increment_statistics diff --git a/spec/lib/activitypub/tag_manager_spec.rb b/spec/lib/activitypub/tag_manager_spec.rb index 9878952f05..caa940d169 100644 --- a/spec/lib/activitypub/tag_manager_spec.rb +++ b/spec/lib/activitypub/tag_manager_spec.rb @@ -139,6 +139,14 @@ RSpec.describe ActivityPub::TagManager do expect(subject.cc(status)).to include(subject.uri_for(foo)) expect(subject.cc(status)).to_not include(subject.uri_for(alice)) end + + it 'returns poster of reblogged post, if reblog' do + bob = Fabricate(:account, username: 'bob', domain: 'example.com', inbox_url: 'http://example.com/bob') + alice = Fabricate(:account, username: 'alice') + status = Fabricate(:status, visibility: :public, account: bob) + reblog = Fabricate(:status, visibility: :public, account: alice, reblog: status) + expect(subject.cc(reblog)).to include(subject.uri_for(bob)) + end end describe '#cc_for_misskey' do diff --git a/spec/services/reblog_service_spec.rb b/spec/services/reblog_service_spec.rb index 7b85e37ed8..357b315af0 100644 --- a/spec/services/reblog_service_spec.rb +++ b/spec/services/reblog_service_spec.rb @@ -86,9 +86,5 @@ RSpec.describe ReblogService, type: :service do it 'distributes to followers' do expect(ActivityPub::DistributionWorker).to have_received(:perform_async) end - - it 'sends an announce activity to the author' do - expect(a_request(:post, bob.inbox_url)).to have_been_made.once - end end end diff --git a/spec/services/remove_status_service_spec.rb b/spec/services/remove_status_service_spec.rb index 4e6bc39aaa..e9e247edab 100644 --- a/spec/services/remove_status_service_spec.rb +++ b/spec/services/remove_status_service_spec.rb @@ -160,4 +160,22 @@ RSpec.describe RemoveStatusService, type: :service do )).to have_been_made.once end end + + context 'when removed status is a reblog of a non-follower' do + let!(:original_status) { Fabricate(:status, account: bill, text: 'Hello ThisIsASecret', visibility: :public) } + let!(:status) { ReblogService.new.call(alice, original_status) } + + it 'sends Undo activity to followers' do + subject.call(status) + expect(a_request(:post, bill.shared_inbox_url).with( + body: hash_including({ + 'type' => 'Undo', + 'object' => hash_including({ + 'type' => 'Announce', + 'object' => ActivityPub::TagManager.instance.uri_for(original_status), + }), + }) + )).to have_been_made.once + end + end end From 2338fc4aecfdfe6d05a1d29fd61182a4cabcc960 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 10 Jan 2024 16:05:46 +0100 Subject: [PATCH 12/23] Fix potential redirection loop of streaming endpoint (#28665) --- app/controllers/api/v1/streaming_controller.rb | 7 ++++++- spec/controllers/api/v1/streaming_controller_spec.rb | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/v1/streaming_controller.rb b/app/controllers/api/v1/streaming_controller.rb index 0cb6e856f2..adb14676e1 100644 --- a/app/controllers/api/v1/streaming_controller.rb +++ b/app/controllers/api/v1/streaming_controller.rb @@ -2,7 +2,7 @@ class Api::V1::StreamingController < Api::BaseController def index - if Rails.configuration.x.streaming_api_base_url == request.host + if same_host? not_found else redirect_to streaming_api_url, status: 301, allow_other_host: true @@ -11,6 +11,11 @@ class Api::V1::StreamingController < Api::BaseController private + def same_host? + base_url = Addressable::URI.parse(Rails.configuration.x.streaming_api_base_url) + request.host == base_url.host && request.port == (base_url.port || 80) + end + def streaming_api_url Addressable::URI.parse(request.url).tap do |uri| base_url = Addressable::URI.parse(Rails.configuration.x.streaming_api_base_url) diff --git a/spec/controllers/api/v1/streaming_controller_spec.rb b/spec/controllers/api/v1/streaming_controller_spec.rb index c3e7153ce8..099f68a74e 100644 --- a/spec/controllers/api/v1/streaming_controller_spec.rb +++ b/spec/controllers/api/v1/streaming_controller_spec.rb @@ -5,7 +5,7 @@ require 'rails_helper' describe Api::V1::StreamingController do around do |example| before = Rails.configuration.x.streaming_api_base_url - Rails.configuration.x.streaming_api_base_url = Rails.configuration.x.web_domain + Rails.configuration.x.streaming_api_base_url = "wss://#{Rails.configuration.x.web_domain}" example.run Rails.configuration.x.streaming_api_base_url = before end From 6bc4219f598ec6dfe0ae0e133058e967aa27c396 Mon Sep 17 00:00:00 2001 From: Jeong Arm Date: Tue, 16 Jan 2024 17:35:54 +0900 Subject: [PATCH 13/23] Ignore RecordNotUnique errors in LinkCrawlWorker (#28748) --- app/workers/link_crawl_worker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/link_crawl_worker.rb b/app/workers/link_crawl_worker.rb index b3d8aa2646..c63af1e43a 100644 --- a/app/workers/link_crawl_worker.rb +++ b/app/workers/link_crawl_worker.rb @@ -7,7 +7,7 @@ class LinkCrawlWorker def perform(status_id) FetchLinkCardService.new.call(Status.find(status_id)) - rescue ActiveRecord::RecordNotFound + rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordNotUnique true end end From eec533e8cd8db4f814dd08925660bd41a87164fb Mon Sep 17 00:00:00 2001 From: Jonathan de Jong Date: Fri, 19 Jan 2024 10:18:21 +0100 Subject: [PATCH 14/23] Retry 401 errors on replies fetching (#28788) Co-authored-by: Claire --- app/helpers/jsonld_helper.rb | 12 ++++++------ app/services/activitypub/fetch_replies_service.rb | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/app/helpers/jsonld_helper.rb b/app/helpers/jsonld_helper.rb index 46cef6b087..4c00c72393 100644 --- a/app/helpers/jsonld_helper.rb +++ b/app/helpers/jsonld_helper.rb @@ -163,7 +163,7 @@ module JsonLdHelper end end - def fetch_resource(uri, id, on_behalf_of = nil) + def fetch_resource(uri, id, on_behalf_of = nil, request_options: {}) unless id json = fetch_resource_without_id_validation(uri, on_behalf_of) @@ -172,14 +172,14 @@ module JsonLdHelper uri = json['id'] end - json = fetch_resource_without_id_validation(uri, on_behalf_of) + json = fetch_resource_without_id_validation(uri, on_behalf_of, request_options: request_options) json.present? && json['id'] == uri ? json : nil end - def fetch_resource_without_id_validation(uri, on_behalf_of = nil, raise_on_temporary_error = false) + def fetch_resource_without_id_validation(uri, on_behalf_of = nil, raise_on_temporary_error = false, request_options: {}) on_behalf_of ||= Account.representative - build_request(uri, on_behalf_of).perform do |response| + build_request(uri, on_behalf_of, options: request_options).perform do |response| raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error body_to_json(response.body_with_limit) if response.code == 200 @@ -212,8 +212,8 @@ module JsonLdHelper response.code == 501 || ((400...500).cover?(response.code) && ![401, 408, 429].include?(response.code)) end - def build_request(uri, on_behalf_of = nil) - Request.new(:get, uri).tap do |request| + def build_request(uri, on_behalf_of = nil, options: {}) + Request.new(:get, uri, **options).tap do |request| request.on_behalf_of(on_behalf_of) if on_behalf_of request.add_headers('Accept' => 'application/activity+json, application/ld+json') end diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb index b5c7759ec5..a9dd327e96 100644 --- a/app/services/activitypub/fetch_replies_service.rb +++ b/app/services/activitypub/fetch_replies_service.rb @@ -37,7 +37,20 @@ class ActivityPub::FetchRepliesService < BaseService return unless @allow_synchronous_requests return if non_matching_uri_hosts?(@account.uri, collection_or_uri) - fetch_resource_without_id_validation(collection_or_uri, nil, true) + # NOTE: For backward compatibility reasons, Mastodon signs outgoing + # queries incorrectly by default. + # + # While this is relevant for all URLs with query strings, this is + # the only code path where this happens in practice. + # + # Therefore, retry with correct signatures if this fails. + begin + fetch_resource_without_id_validation(collection_or_uri, nil, true) + rescue Mastodon::UnexpectedResponseError => e + raise unless e.response && e.response.code == 401 && Addressable::URI.parse(collection_or_uri).query.present? + + fetch_resource_without_id_validation(collection_or_uri, nil, true, request_options: { with_query_string: true }) + end end def filtered_replies From 8c23a8aa2b1a13d276958bc15953e83f38268b2c Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Jan 2024 13:19:49 +0100 Subject: [PATCH 15/23] Add rate-limit of TOTP authentication attempts at controller level (#28801) --- app/controllers/auth/sessions_controller.rb | 22 +++++++++++++++++++ .../auth/two_factor_authentication_concern.rb | 5 +++++ config/locales/en.yml | 1 + .../auth/sessions_controller_spec.rb | 20 +++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index 148ad53755..6bc48a7804 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true class Auth::SessionsController < Devise::SessionsController + include Redisable + + MAX_2FA_ATTEMPTS_PER_HOUR = 10 + layout 'auth' skip_before_action :check_self_destruct! @@ -130,9 +134,23 @@ class Auth::SessionsController < Devise::SessionsController session.delete(:attempt_user_updated_at) end + def clear_2fa_attempt_from_user(user) + redis.del(second_factor_attempts_key(user)) + end + + def check_second_factor_rate_limits(user) + attempts, = redis.multi do |multi| + multi.incr(second_factor_attempts_key(user)) + multi.expire(second_factor_attempts_key(user), 1.hour) + end + + attempts >= MAX_2FA_ATTEMPTS_PER_HOUR + end + def on_authentication_success(user, security_measure) @on_authentication_success_called = true + clear_2fa_attempt_from_user(user) clear_attempt_from_session user.update_sign_in!(new_sign_in: true) @@ -164,4 +182,8 @@ class Auth::SessionsController < Devise::SessionsController user_agent: request.user_agent ) end + + def second_factor_attempts_key(user) + "2fa_auth_attempts:#{user.id}:#{Time.now.utc.hour}" + end end diff --git a/app/controllers/concerns/auth/two_factor_authentication_concern.rb b/app/controllers/concerns/auth/two_factor_authentication_concern.rb index effdb8d21c..404164751a 100644 --- a/app/controllers/concerns/auth/two_factor_authentication_concern.rb +++ b/app/controllers/concerns/auth/two_factor_authentication_concern.rb @@ -66,6 +66,11 @@ module Auth::TwoFactorAuthenticationConcern end def authenticate_with_two_factor_via_otp(user) + if check_second_factor_rate_limits(user) + flash.now[:alert] = I18n.t('users.rate_limited') + return prompt_for_two_factor(user) + end + if valid_otp_attempt?(user) on_authentication_success(user, :otp) else diff --git a/config/locales/en.yml b/config/locales/en.yml index 970c1fe005..ba5d1e4c29 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2075,6 +2075,7 @@ en: go_to_sso_account_settings: Go to your identity provider's account settings invalid_otp_token: Invalid two-factor code otp_lost_help_html: If you lost access to both, you may get in touch with %{email} + rate_limited: Too many authentication attempts, try again later. seamless_external_login: You are logged in via an external service, so password and e-mail settings are not available. signed_in_as: 'Signed in as:' verification: diff --git a/spec/controllers/auth/sessions_controller_spec.rb b/spec/controllers/auth/sessions_controller_spec.rb index 212cc4d5e5..7b18f021f5 100644 --- a/spec/controllers/auth/sessions_controller_spec.rb +++ b/spec/controllers/auth/sessions_controller_spec.rb @@ -262,6 +262,26 @@ RSpec.describe Auth::SessionsController do end end + context 'when repeatedly using an invalid TOTP code before using a valid code' do + before do + stub_const('Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR', 2) + end + + it 'does not log the user in' do + # Travel to the beginning of an hour to avoid crossing rate-limit buckets + travel_to '2023-12-20T10:00:00Z' + + Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR.times do + post :create, params: { user: { otp_attempt: '1234' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } + expect(controller.current_user).to be_nil + end + + post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } + expect(controller.current_user).to be_nil + expect(flash[:alert]).to match I18n.t('users.rate_limited') + end + end + context 'when using a valid OTP' do before do post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } From 1225c22810f52c77c5642a613b6bc51d01a85679 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Jan 2024 13:43:10 +0100 Subject: [PATCH 16/23] Fix processing of compacted single-item JSON-LD collections (#28816) --- .../fetch_featured_collection_service.rb | 4 +-- .../activitypub/fetch_replies_service.rb | 4 +-- .../synchronize_followers_service.rb | 4 +-- app/services/keys/query_service.rb | 2 +- .../fetch_featured_collection_service_spec.rb | 34 +++++++++++++++++-- .../activitypub/fetch_replies_service_spec.rb | 12 +++++++ 6 files changed, 51 insertions(+), 9 deletions(-) diff --git a/app/services/activitypub/fetch_featured_collection_service.rb b/app/services/activitypub/fetch_featured_collection_service.rb index d2bae08a0e..89c3a1b6c0 100644 --- a/app/services/activitypub/fetch_featured_collection_service.rb +++ b/app/services/activitypub/fetch_featured_collection_service.rb @@ -23,9 +23,9 @@ class ActivityPub::FetchFeaturedCollectionService < BaseService case collection['type'] when 'Collection', 'CollectionPage' - collection['items'] + as_array(collection['items']) when 'OrderedCollection', 'OrderedCollectionPage' - collection['orderedItems'] + as_array(collection['orderedItems']) end end diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb index a9dd327e96..e2ecdef165 100644 --- a/app/services/activitypub/fetch_replies_service.rb +++ b/app/services/activitypub/fetch_replies_service.rb @@ -26,9 +26,9 @@ class ActivityPub::FetchRepliesService < BaseService case collection['type'] when 'Collection', 'CollectionPage' - collection['items'] + as_array(collection['items']) when 'OrderedCollection', 'OrderedCollectionPage' - collection['orderedItems'] + as_array(collection['orderedItems']) end end diff --git a/app/services/activitypub/synchronize_followers_service.rb b/app/services/activitypub/synchronize_followers_service.rb index 7ccc917309..f51d671a00 100644 --- a/app/services/activitypub/synchronize_followers_service.rb +++ b/app/services/activitypub/synchronize_followers_service.rb @@ -59,9 +59,9 @@ class ActivityPub::SynchronizeFollowersService < BaseService case collection['type'] when 'Collection', 'CollectionPage' - collection['items'] + as_array(collection['items']) when 'OrderedCollection', 'OrderedCollectionPage' - collection['orderedItems'] + as_array(collection['orderedItems']) end end diff --git a/app/services/keys/query_service.rb b/app/services/keys/query_service.rb index 14c9d9205b..33e13293f3 100644 --- a/app/services/keys/query_service.rb +++ b/app/services/keys/query_service.rb @@ -69,7 +69,7 @@ class Keys::QueryService < BaseService return if json['items'].blank? - @devices = json['items'].map do |device| + @devices = as_array(json['items']).map do |device| Device.new(device_id: device['id'], name: device['name'], identity_key: device.dig('identityKey', 'publicKeyBase64'), fingerprint_key: device.dig('fingerprintKey', 'publicKeyBase64'), claim_url: device['claim']) end rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error => e diff --git a/spec/services/activitypub/fetch_featured_collection_service_spec.rb b/spec/services/activitypub/fetch_featured_collection_service_spec.rb index a98108cea3..b9e95b825f 100644 --- a/spec/services/activitypub/fetch_featured_collection_service_spec.rb +++ b/spec/services/activitypub/fetch_featured_collection_service_spec.rb @@ -31,7 +31,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do } end - let(:status_json_pinned_unknown_unreachable) do + let(:status_json_pinned_unknown_reachable) do { '@context': 'https://www.w3.org/ns/activitystreams', type: 'Note', @@ -75,7 +75,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: Oj.dump(status_json_pinned_known)) stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_inlined)) stub_request(:get, 'https://example.com/account/pinned/unknown-unreachable').to_return(status: 404) - stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_unreachable)) + stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: Oj.dump(featured_with_null)) subject.call(actor, note: true, hashtag: false) @@ -115,6 +115,21 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do end it_behaves_like 'sets pinned posts' + + context 'when there is a single item, with the array compacted away' do + let(:items) { 'https://example.com/account/pinned/unknown-reachable' } + + before do + stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) + subject.call(actor, note: true, hashtag: false) + end + + it 'sets expected posts as pinned posts' do + expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly( + 'https://example.com/account/pinned/unknown-reachable' + ) + end + end end context 'when the endpoint is a paginated Collection' do @@ -136,6 +151,21 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do end it_behaves_like 'sets pinned posts' + + context 'when there is a single item, with the array compacted away' do + let(:items) { 'https://example.com/account/pinned/unknown-reachable' } + + before do + stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) + subject.call(actor, note: true, hashtag: false) + end + + it 'sets expected posts as pinned posts' do + expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly( + 'https://example.com/account/pinned/unknown-reachable' + ) + end + end end end end diff --git a/spec/services/activitypub/fetch_replies_service_spec.rb b/spec/services/activitypub/fetch_replies_service_spec.rb index d7716dd4ef..a76b996c20 100644 --- a/spec/services/activitypub/fetch_replies_service_spec.rb +++ b/spec/services/activitypub/fetch_replies_service_spec.rb @@ -34,6 +34,18 @@ RSpec.describe ActivityPub::FetchRepliesService, type: :service do describe '#call' do context 'when the payload is a Collection with inlined replies' do + context 'when there is a single reply, with the array compacted away' do + let(:items) { 'http://example.com/self-reply-1' } + + it 'queues the expected worker' do + allow(FetchReplyWorker).to receive(:push_bulk) + + subject.call(status, payload) + + expect(FetchReplyWorker).to have_received(:push_bulk).with(['http://example.com/self-reply-1']) + end + end + context 'when passing the collection itself' do it 'spawns workers for up to 5 replies on the same server' do allow(FetchReplyWorker).to receive(:push_bulk) From 58267dcfe928ccc56c2773f5ced5fe025670a05c Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Jan 2024 19:52:59 +0100 Subject: [PATCH 17/23] Fix error when processing remote files with unusually long names (#28823) --- lib/paperclip/response_with_limit_adapter.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/paperclip/response_with_limit_adapter.rb b/lib/paperclip/response_with_limit_adapter.rb index deb89717a4..ff7a938abb 100644 --- a/lib/paperclip/response_with_limit_adapter.rb +++ b/lib/paperclip/response_with_limit_adapter.rb @@ -16,7 +16,7 @@ module Paperclip private def cache_current_values - @original_filename = filename_from_content_disposition.presence || filename_from_path.presence || 'data' + @original_filename = truncated_filename @tempfile = copy_to_tempfile(@target) @content_type = ContentTypeDetector.new(@tempfile.path).detect @size = File.size(@tempfile) @@ -43,6 +43,13 @@ module Paperclip source.response.connection.close end + def truncated_filename + filename = filename_from_content_disposition.presence || filename_from_path.presence || 'data' + extension = File.extname(filename) + basename = File.basename(filename, extension) + [basename[...20], extension[..4]].compact_blank.join + end + def filename_from_content_disposition disposition = @target.response.headers['content-disposition'] disposition&.match(/filename="([^"]*)"/)&.captures&.first From 1ac58c385825128e3c190671bd66939b2820eeb7 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 23 Jan 2024 15:02:19 +0100 Subject: [PATCH 18/23] Update dependency puma to v6.4.2 --- Gemfile.lock | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 06d4d5b8eb..bd25965cab 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -481,7 +481,8 @@ GEM timeout net-smtp (0.4.0) net-protocol - nio4r (2.5.9) + net-ssh (7.1.0) + nio4r (2.7.0) nokogiri (1.16.0) mini_portile2 (~> 2.8.2) racc (~> 1.4) @@ -544,7 +545,7 @@ GEM psych (5.1.2) stringio public_suffix (5.0.4) - puma (6.4.1) + puma (6.4.2) nio4r (~> 2.0) pundit (2.3.1) activesupport (>= 3.0.0) From fcb0ebdb5b1532814ab79cdd61b3fb94bf980cbc Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 23 Jan 2024 15:03:45 +0100 Subject: [PATCH 19/23] Bump ruby version to 3.2.3 --- .ruby-version | 2 +- Dockerfile | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.ruby-version b/.ruby-version index be94e6f53d..b347b11eac 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.2 +3.2.3 diff --git a/Dockerfile b/Dockerfile index 96f8b5cd27..1cafd3b552 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,7 @@ # syntax=docker/dockerfile:1.4 -# Please see https://docs.docker.com/engine/reference/builder for information about -# the extended buildx capabilities used in this file. -# Make sure multiarch TARGETPLATFORM is available for interpolation -# See: https://docs.docker.com/build/building/multi-platform/ -ARG TARGETPLATFORM=${TARGETPLATFORM} -ARG BUILDPLATFORM=${BUILDPLATFORM} +FROM ghcr.io/moritzheiber/ruby-jemalloc:3.2.3-slim as ruby +FROM node:${NODE_VERSION} as build # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.2.2"] ARG RUBY_VERSION="3.2.2" From 72367f684822287d5b60f5ae637d0590f2f431f7 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 15 Jan 2024 11:45:48 +0100 Subject: [PATCH 20/23] Ignore the devise-two-factor advisory as we have rate limits in place (#28733) --- .bundler-audit.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .bundler-audit.yml diff --git a/.bundler-audit.yml b/.bundler-audit.yml new file mode 100644 index 0000000000..0671df390f --- /dev/null +++ b/.bundler-audit.yml @@ -0,0 +1,6 @@ +--- +ignore: + # devise-two-factor advisory about brute-forcing TOTP + # We have rate-limits on authentication endpoints in place (including second + # factor verification) since Mastodon v3.2.0 + - CVE-2024-0227 From 48f860945daad5f5c3e6f9f9b9df1f5666aff6a4 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 24 Jan 2024 14:59:09 +0100 Subject: [PATCH 21/23] Change PostgreSQL version check to check for PostgreSQL 10+ --- lib/tasks/db.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake index e8a64b8fb2..f51a2459c5 100644 --- a/lib/tasks/db.rake +++ b/lib/tasks/db.rake @@ -17,7 +17,7 @@ namespace :db do task :pre_migration_check do version = ActiveRecord::Base.connection.select_one("SELECT current_setting('server_version_num') AS v")['v'].to_i - abort 'This version of Mastodon requires PostgreSQL 9.5 or newer. Please update PostgreSQL before updating Mastodon' if version < 90_500 + abort 'This version of Mastodon requires PostgreSQL 10.0 or newer. Please update PostgreSQL before updating Mastodon' if version < 100_000 end Rake::Task['db:migrate'].enhance(['db:pre_migration_check']) From 018eb174e8e590bbb966a9db08ac391312eb55d7 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 23 Jan 2024 14:58:27 +0100 Subject: [PATCH 22/23] Bump version to v4.2.4 --- CHANGELOG.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 6 ++--- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f775fcfa8..11cd633870 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,65 @@ All notable changes to this project will be documented in this file. +## [4.2.4] - 2024-01-24 + +### Fixed + +- Fix error when processing remote files with unusually long names ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28823)) +- Fix processing of compacted single-item JSON-LD collections ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28816)) +- Retry 401 errors on replies fetching ([ShadowJonathan](https://github.com/mastodon/mastodon/pull/28788)) +- Fix `RecordNotUnique` errors in LinkCrawlWorker ([tribela](https://github.com/mastodon/mastodon/pull/28748)) +- Fix Mastodon not correctly processing HTTP Signatures with query strings ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28443), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/28476)) +- Fix potential redirection loop of streaming endpoint ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28665)) +- Fix streaming API redirection ignoring the port of `streaming_api_base_url` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28558)) +- Fix error when processing link preview with an array as `inLanguage` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28252)) +- Fix unsupported time zone or locale preventing sign-up ([Gargron](https://github.com/mastodon/mastodon/pull/28035)) +- Fix "Hide these posts from home" list setting not refreshing when switching lists ([brianholley](https://github.com/mastodon/mastodon/pull/27763)) +- Fix missing background behind dismissable banner in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/27479)) +- Fix line wrapping of language selection button with long locale codes ([gunchleoc](https://github.com/mastodon/mastodon/pull/27100), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27127)) +- Fix `Undo Announce` activity not being sent to non-follower authors ([MitarashiDango](https://github.com/mastodon/mastodon/pull/18482)) +- Fix N+1s because of association preloaders not actually getting called ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28339)) +- Fix empty column explainer getting cropped under certain conditions ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28337)) +- Fix `LinkCrawlWorker` error when encountering empty OEmbed response ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28268)) +- Fix call to inefficient `delete_matched` cache method in domain blocks ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28367)) + +### Security + +- Add rate-limit of TOTP authentication attempts at controller level ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28801)) + +## [4.2.3] - 2023-12-05 + +### Fixed + +- Fix dependency on `json-canonicalization` version that has been made unavailable since last release + +## [4.2.2] - 2023-12-04 + +### Changed + +- Change dismissed banners to be stored server-side ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27055)) +- Change GIF max matrix size error to explicitly mention GIF files ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27927)) +- Change `Follow` activities delivery to bypass availability check ([ShadowJonathan](https://github.com/mastodon/mastodon/pull/27586)) +- Change single-column navigation notice to be displayed outside of the logo container ([renchap](https://github.com/mastodon/mastodon/pull/27462), [renchap](https://github.com/mastodon/mastodon/pull/27476)) +- Change Content-Security-Policy to be tighter on media paths ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26889)) +- Change post language code to include country code when relevant ([gunchleoc](https://github.com/mastodon/mastodon/pull/27099), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27207)) + +### Fixed + +- Fix upper border radius of onboarding columns ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27890)) +- Fix incoming status creation date not being restricted to standard ISO8601 ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27655), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/28081)) +- Fix some posts from threads received out-of-order sometimes not being inserted into timelines ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27653)) +- Fix posts from force-sensitized accounts being able to trend ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27620)) +- Fix error when trying to delete already-deleted file with OpenStack Swift ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27569)) +- Fix batch attachment deletion when using OpenStack Swift ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27554)) +- Fix processing LDSigned activities from actors with unknown public keys ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27474)) +- Fix error and incorrect URLs in `/api/v1/accounts/:id/featured_tags` for remote accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27459)) +- Fix report processing notice not mentioning the report number when performing a custom action ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27442)) +- Fix handling of `inLanguage` attribute in preview card processing ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27423)) +- Fix own posts being removed from home timeline when unfollowing a used hashtag ([kmycode](https://github.com/mastodon/mastodon/pull/27391)) +- Fix some link anchors being recognized as hashtags ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27271), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27584)) +- Fix format-dependent redirects being cached regardless of requested format ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27634)) + ## [4.2.1] - 2023-10-10 ### Added diff --git a/docker-compose.yml b/docker-compose.yml index d52ca44100..b77e63b837 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -56,7 +56,7 @@ services: web: build: . - image: ghcr.io/mastodon/mastodon:v4.2.1 + image: ghcr.io/mastodon/mastodon:v4.2.4 restart: always env_file: .env.production command: bundle exec puma -C config/puma.rb @@ -77,7 +77,7 @@ services: streaming: build: . - image: ghcr.io/mastodon/mastodon:v4.2.1 + image: ghcr.io/mastodon/mastodon:v4.2.4 restart: always env_file: .env.production command: node ./streaming @@ -95,7 +95,7 @@ services: sidekiq: build: . - image: ghcr.io/mastodon/mastodon:v4.2.1 + image: ghcr.io/mastodon/mastodon:v4.2.4 restart: always env_file: .env.production command: bundle exec sidekiq From 48d091dd18c7bf29abfb34cdee2841ae84c82e58 Mon Sep 17 00:00:00 2001 From: KMY Date: Thu, 25 Jan 2024 09:58:26 +0900 Subject: [PATCH 23/23] Set ruby version --- install/5.0/setup4.sh | 4 ++-- install/9.0/setup4.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/install/5.0/setup4.sh b/install/5.0/setup4.sh index 60014adb11..4c946d9a41 100644 --- a/install/5.0/setup4.sh +++ b/install/5.0/setup4.sh @@ -6,8 +6,8 @@ Install Ruby EOF git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build -RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.2.2 -rbenv global 3.2.2 +RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.2.3 +rbenv global 3.2.3 cat << EOF diff --git a/install/9.0/setup4.sh b/install/9.0/setup4.sh index 4e61f44071..a278c21fed 100644 --- a/install/9.0/setup4.sh +++ b/install/9.0/setup4.sh @@ -6,8 +6,8 @@ Install Ruby EOF git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build -RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.2.2 -rbenv global 3.2.2 +RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.2.3 +rbenv global 3.2.3 cat << EOF