From e2103c9175b67bc310a6c36aa239520d7dcbed7c Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 3 Mar 2023 20:25:15 +0100 Subject: [PATCH 01/39] =?UTF-8?q?Fix=20=E2=80=9CRemove=20all=20followers?= =?UTF-8?q?=20from=20the=20selected=20domains=E2=80=9D=20being=20more=20de?= =?UTF-8?q?structive=20than=20it=20claims=20(#23805)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/relationships_controller.rb | 4 ++-- app/models/form/account_batch.rb | 10 ++++---- .../remove_domains_from_followers_service.rb | 23 +++++++++++++++++++ app/views/relationships/show.html.haml | 2 +- .../relationships_controller_spec.rb | 11 ++++++++- 5 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 app/services/remove_domains_from_followers_service.rb diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb index 96cce55e9..baa34da22 100644 --- a/app/controllers/relationships_controller.rb +++ b/app/controllers/relationships_controller.rb @@ -60,8 +60,8 @@ class RelationshipsController < ApplicationController 'unfollow' elsif params[:remove_from_followers] 'remove_from_followers' - elsif params[:block_domains] - 'block_domains' + elsif params[:block_domains] || params[:remove_domains_from_followers] + 'remove_domains_from_followers' end end diff --git a/app/models/form/account_batch.rb b/app/models/form/account_batch.rb index 5cfcf7205..6fc9ac591 100644 --- a/app/models/form/account_batch.rb +++ b/app/models/form/account_batch.rb @@ -17,8 +17,8 @@ class Form::AccountBatch unfollow! when 'remove_from_followers' remove_from_followers! - when 'block_domains' - block_domains! + when 'remove_domains_from_followers' + remove_domains_from_followers! when 'approve' approve! when 'reject' @@ -50,10 +50,8 @@ class Form::AccountBatch RemoveFromFollowersService.new.call(current_account, account_ids) end - def block_domains! - AfterAccountDomainBlockWorker.push_bulk(account_domains) do |domain| - [current_account.id, domain] - end + def remove_domains_from_followers! + RemoveDomainsFromFollowersService.new.call(current_account, account_domains) end def account_domains diff --git a/app/services/remove_domains_from_followers_service.rb b/app/services/remove_domains_from_followers_service.rb new file mode 100644 index 000000000..d76763409 --- /dev/null +++ b/app/services/remove_domains_from_followers_service.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class RemoveDomainsFromFollowersService < BaseService + include Payloadable + + def call(source_account, target_domains) + source_account.passive_relationships.where(account_id: Account.where(domain: target_domains)).find_each do |follow| + follow.destroy + + create_notification(follow) if source_account.local? && !follow.account.local? && follow.account.activitypub? + end + end + + private + + def create_notification(follow) + ActivityPub::DeliveryWorker.perform_async(build_json(follow), follow.target_account_id, follow.account.inbox_url) + end + + def build_json(follow) + Oj.dump(serialize_payload(follow, ActivityPub::RejectFollowSerializer)) + end +end diff --git a/app/views/relationships/show.html.haml b/app/views/relationships/show.html.haml index c82e639e0..cd5152b40 100644 --- a/app/views/relationships/show.html.haml +++ b/app/views/relationships/show.html.haml @@ -48,7 +48,7 @@ = f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_followers')]), name: :remove_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } unless following_relationship? - = f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_domains')]), name: :block_domains, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } if followed_by_relationship? + = f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_domains')]), name: :remove_domains_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } if followed_by_relationship? .batch-table__body - if @accounts.empty? = nothing_here 'nothing-here--under-tabs' diff --git a/spec/controllers/relationships_controller_spec.rb b/spec/controllers/relationships_controller_spec.rb index 2056a2ac2..bcdcfa905 100644 --- a/spec/controllers/relationships_controller_spec.rb +++ b/spec/controllers/relationships_controller_spec.rb @@ -55,7 +55,7 @@ describe RelationshipsController do end context 'when select parameter is provided' do - subject { patch :update, params: { form_account_batch: { account_ids: [poopfeast.id] }, block_domains: '' } } + subject { patch :update, params: { form_account_batch: { account_ids: [poopfeast.id] }, remove_domains_from_followers: '' } } it 'soft-blocks followers from selected domains' do poopfeast.follow!(user.account) @@ -66,6 +66,15 @@ describe RelationshipsController do expect(poopfeast.following?(user.account)).to be false end + it 'does not unfollow users from selected domains' do + user.account.follow!(poopfeast) + + sign_in user, scope: :user + subject + + expect(user.account.following?(poopfeast)).to be true + end + include_examples 'authenticate user' include_examples 'redirects back to followers page' end From cc80f4ed9bc9ab616cfd5a6ffe4c1ed9e3f0061b Mon Sep 17 00:00:00 2001 From: Dean Bassett Date: Mon, 13 Feb 2023 05:54:08 -0800 Subject: [PATCH 02/39] Fix case-sensitive check for previously used hashtags (#23526) --- app/javascript/mastodon/reducers/compose.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js index 8cc7bf520..ed1028e08 100644 --- a/app/javascript/mastodon/reducers/compose.js +++ b/app/javascript/mastodon/reducers/compose.js @@ -186,11 +186,12 @@ const ignoreSuggestion = (state, position, token, completion, path) => { }; const sortHashtagsByUse = (state, tags) => { - const personalHistory = state.get('tagHistory'); + const personalHistory = state.get('tagHistory').map(tag => tag.toLowerCase()); - return tags.sort((a, b) => { - const usedA = personalHistory.includes(a.name); - const usedB = personalHistory.includes(b.name); + const tagsWithLowercase = tags.map(t => ({ ...t, lowerName: t.name.toLowerCase() })); + const sorted = tagsWithLowercase.sort((a, b) => { + const usedA = personalHistory.includes(a.lowerName); + const usedB = personalHistory.includes(b.lowerName); if (usedA === usedB) { return 0; @@ -200,6 +201,8 @@ const sortHashtagsByUse = (state, tags) => { return 1; } }); + sorted.forEach(tag => delete tag.lowerName); + return sorted; }; const insertEmoji = (state, position, emojiData, needsSpace) => { From 0e3f06da99b6d8a49dd6020aca133a741ae676a9 Mon Sep 17 00:00:00 2001 From: Botao Wang Date: Tue, 21 Feb 2023 18:06:13 +0900 Subject: [PATCH 03/39] Fix sidebar cut-off on small screens in admin UI (#23764) --- app/javascript/styles/mastodon/admin.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index 7a50a89bb..b1163c212 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -386,7 +386,7 @@ $content-width: 840px; position: fixed; z-index: 10; width: 100%; - height: calc(100vh - 56px); + height: calc(100% - 56px); left: 0; bottom: 0; overflow-y: auto; From 348599a54370e2428059a05b8f898c4f1de6e54a Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 22 Feb 2023 11:53:13 +0100 Subject: [PATCH 04/39] Fix inefficiency when searching accounts per username in admin interface (#23801) --- app/models/account.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/account.rb b/app/models/account.rb index fc7359cfc..bfe932c9f 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -107,7 +107,7 @@ class Account < ApplicationRecord scope :bots, -> { where(actor_type: %w(Application Service)) } scope :groups, -> { where(actor_type: 'Group') } scope :alphabetic, -> { order(domain: :asc, username: :asc) } - scope :matches_username, ->(value) { where(arel_table[:username].matches("#{value}%")) } + scope :matches_username, ->(value) { where('lower((username)::text) LIKE lower(?)', "#{value}%") } scope :matches_display_name, ->(value) { where(arel_table[:display_name].matches("#{value}%")) } scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) } scope :without_unapproved, -> { left_outer_joins(:user).remote.or(left_outer_joins(:user).merge(User.approved.confirmed)) } From c22c4247d9cb8df3807ca76b144135d11466efd4 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 3 Mar 2023 20:36:18 +0100 Subject: [PATCH 05/39] Fix server error when failing to follow back followers from `/relationships` (#23787) --- app/controllers/relationships_controller.rb | 2 ++ app/models/form/account_batch.rb | 6 ++++++ config/locales/en.yml | 1 + 3 files changed, 9 insertions(+) diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb index baa34da22..de5dc5879 100644 --- a/app/controllers/relationships_controller.rb +++ b/app/controllers/relationships_controller.rb @@ -19,6 +19,8 @@ class RelationshipsController < ApplicationController @form.save rescue ActionController::ParameterMissing # Do nothing + rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound + flash[:alert] = I18n.t('relationships.follow_failure') if action_from_button == 'follow' ensure redirect_to relationships_path(filter_params) end diff --git a/app/models/form/account_batch.rb b/app/models/form/account_batch.rb index 6fc9ac591..d0cb727ca 100644 --- a/app/models/form/account_batch.rb +++ b/app/models/form/account_batch.rb @@ -35,9 +35,15 @@ class Form::AccountBatch private def follow! + error = nil + accounts.each do |target_account| FollowService.new.call(current_account, target_account) + rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound => e + error ||= e end + + raise error if error.present? end def unfollow! diff --git a/config/locales/en.yml b/config/locales/en.yml index 679e356b4..6332f0f01 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1341,6 +1341,7 @@ en: relationships: activity: Account activity dormant: Dormant + follow_failure: Could not follow some of the selected accounts. follow_selected_followers: Follow selected followers followers: Followers following: Following From 76c96cdd728b4eb33857d459c43da0f4b43c2e05 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 3 Mar 2023 20:44:02 +0100 Subject: [PATCH 06/39] Fix error when displaying post history of a trendable post in the admin interface (#23574) --- app/views/admin/statuses/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/statuses/show.html.haml b/app/views/admin/statuses/show.html.haml index 62b49de8c..4631e97f1 100644 --- a/app/views/admin/statuses/show.html.haml +++ b/app/views/admin/statuses/show.html.haml @@ -34,7 +34,7 @@ %td - if @status.trend.allowed? %abbr{ title: t('admin.trends.tags.current_score', score: @status.trend.score) }= t('admin.trends.tags.trending_rank', rank: @status.trend.rank) - - elsif @status.trend.requires_review? + - elsif @status.requires_review? = t('admin.trends.pending_review') - else = t('admin.trends.not_allowed_to_trend') From 11f04e3b972f6efc161d32b06b7d98d51e7550be Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 6 Mar 2023 16:00:08 +0100 Subject: [PATCH 07/39] Fix unconfirmed accounts being registered as active users (#23803) --- app/models/user.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/models/user.rb b/app/models/user.rb index 6d566b1c2..5790be6e9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -480,10 +480,13 @@ class User < ApplicationRecord def prepare_new_user! BootstrapTimelineWorker.perform_async(account_id) ActivityTracker.increment('activity:accounts:local') + ActivityTracker.record('activity:logins', id) UserMailer.welcome(self).deliver_later end def prepare_returning_user! + return unless confirmed? + ActivityTracker.record('activity:logins', id) regenerate_feed! if needs_feed_update? end From 290d02e936abeb047e3436edb81952f707da6fb2 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 3 Mar 2023 21:13:55 +0100 Subject: [PATCH 08/39] Fix original account being unfollowed on migration before the follow request could be sent (#21957) --- app/services/follow_migration_service.rb | 40 +++++++++++++++++++ .../migrated_follow_delivery_worker.rb | 17 ++++++++ app/workers/unfollow_follow_worker.rb | 8 +--- 3 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 app/services/follow_migration_service.rb create mode 100644 app/workers/activitypub/migrated_follow_delivery_worker.rb diff --git a/app/services/follow_migration_service.rb b/app/services/follow_migration_service.rb new file mode 100644 index 000000000..cfe9093cb --- /dev/null +++ b/app/services/follow_migration_service.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +class FollowMigrationService < FollowService + # Follow an account with the same settings as another account, and unfollow the old account once the request is sent + # @param [Account] source_account From which to follow + # @param [Account] target_account Account to follow + # @param [Account] old_target_account Account to unfollow once the follow request has been sent to the new one + # @option [Boolean] bypass_locked Whether to immediately follow the new account even if it is locked + def call(source_account, target_account, old_target_account, bypass_locked: false) + @old_target_account = old_target_account + + follow = source_account.active_relationships.find_by(target_account: old_target_account) + reblogs = follow&.show_reblogs? + notify = follow&.notify? + languages = follow&.languages + + super(source_account, target_account, reblogs: reblogs, notify: notify, languages: languages, bypass_locked: bypass_locked, bypass_limit: true) + end + + private + + def request_follow! + follow_request = @source_account.request_follow!(@target_account, **follow_options.merge(rate_limit: @options[:with_rate_limit], bypass_limit: @options[:bypass_limit])) + + if @target_account.local? + LocalNotificationWorker.perform_async(@target_account.id, follow_request.id, follow_request.class.name, 'follow_request') + UnfollowService.new.call(@source_account, @old_target_account, skip_unmerge: true) + elsif @target_account.activitypub? + ActivityPub::MigratedFollowDeliveryWorker.perform_async(build_json(follow_request), @source_account.id, @target_account.inbox_url, @old_target_account.id) + end + + follow_request + end + + def direct_follow! + follow = super + UnfollowService.new.call(@source_account, @old_target_account, skip_unmerge: true) + follow + end +end diff --git a/app/workers/activitypub/migrated_follow_delivery_worker.rb b/app/workers/activitypub/migrated_follow_delivery_worker.rb new file mode 100644 index 000000000..17a9e515e --- /dev/null +++ b/app/workers/activitypub/migrated_follow_delivery_worker.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class ActivityPub::MigratedFollowDeliveryWorker < ActivityPub::DeliveryWorker + def perform(json, source_account_id, inbox_url, old_target_account_id, options = {}) + super(json, source_account_id, inbox_url, options) + unfollow_old_account!(old_target_account_id) + end + + private + + def unfollow_old_account!(old_target_account_id) + old_target_account = Account.find(old_target_account_id) + UnfollowService.new.call(@source_account, old_target_account, skip_unmerge: true) + rescue StandardError + true + end +end diff --git a/app/workers/unfollow_follow_worker.rb b/app/workers/unfollow_follow_worker.rb index 7203b4888..a4d57839d 100644 --- a/app/workers/unfollow_follow_worker.rb +++ b/app/workers/unfollow_follow_worker.rb @@ -10,13 +10,7 @@ class UnfollowFollowWorker old_target_account = Account.find(old_target_account_id) new_target_account = Account.find(new_target_account_id) - follow = follower_account.active_relationships.find_by(target_account: old_target_account) - reblogs = follow&.show_reblogs? - notify = follow&.notify? - languages = follow&.languages - - FollowService.new.call(follower_account, new_target_account, reblogs: reblogs, notify: notify, languages: languages, bypass_locked: bypass_locked, bypass_limit: true) - UnfollowService.new.call(follower_account, old_target_account, skip_unmerge: true) + FollowMigrationService.new.call(follower_account, new_target_account, old_target_account, bypass_locked: bypass_locked) rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError true end From 0f2e8476e094f94532e6d7de4b0584f9824ae943 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 5 Mar 2023 01:52:42 +0100 Subject: [PATCH 09/39] Fix pgBouncer resetting application name on every transaction (#23958) --- config/database.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/database.yml b/config/database.yml index 127a78abf..6bfde618b 100644 --- a/config/database.yml +++ b/config/database.yml @@ -4,6 +4,7 @@ default: &default timeout: 5000 encoding: unicode sslmode: <%= ENV['DB_SSLMODE'] || "prefer" %> + application_name: '' development: <<: *default From ad77e8a2fbdbad3fdfb1a24f766a5a5c23b77af9 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 6 Mar 2023 17:44:55 +0100 Subject: [PATCH 10/39] Fix `/api/v1/streaming` sub-paths not being redirected (#23988) --- config/routes.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 98aa5a033..d71a9bbbe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -447,7 +447,9 @@ Rails.application.routes.draw do resources :list, only: :show end - resources :streaming, only: [:index] + get '/streaming', to: 'streaming#index' + get '/streaming/(*any)', to: 'streaming#index' + resources :custom_emojis, only: [:index] resources :suggestions, only: [:index, :destroy] resources :scheduled_statuses, only: [:index, :show, :update, :destroy] From c2d38ef0f1715a36cc24a1c09e306bc75f78fdf6 Mon Sep 17 00:00:00 2001 From: Rodion Borisov Date: Thu, 9 Mar 2023 16:35:44 +0300 Subject: [PATCH 11/39] Center the text itself in upload area (#24029) --- app/javascript/styles/mastodon/components.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 119bbe8e6..825671f34 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -4407,6 +4407,7 @@ a.status-card.compact:hover { display: flex; align-items: center; justify-content: center; + text-align: center; color: $secondary-text-color; font-size: 18px; font-weight: 500; From d6f1bd2e088f594d0ad86ed1eaac096cb841e9e0 Mon Sep 17 00:00:00 2001 From: Claire Date: Sun, 12 Mar 2023 23:47:55 +0100 Subject: [PATCH 12/39] Fix sidekiq jobs not triggering Elasticsearch index updates (#24046) --- bin/tootctl | 4 +++- config/initializers/chewy.rb | 1 - lib/mastodon/sidekiq_middleware.rb | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bin/tootctl b/bin/tootctl index a9ebb22c6..9c7ae8b87 100755 --- a/bin/tootctl +++ b/bin/tootctl @@ -5,7 +5,9 @@ require_relative '../config/boot' require_relative '../lib/cli' begin - Mastodon::CLI.start(ARGV) + Chewy.strategy(:mastodon) do + Mastodon::CLI.start(ARGV) + end rescue Interrupt exit(130) end diff --git a/config/initializers/chewy.rb b/config/initializers/chewy.rb index 752fc3c6d..2a91efefc 100644 --- a/config/initializers/chewy.rb +++ b/config/initializers/chewy.rb @@ -19,7 +19,6 @@ Chewy.settings = { # cycle, which takes care of checking if Elasticsearch is enabled # or not. However, mind that for the Rails console, the :urgent # strategy is set automatically with no way to override it. -Chewy.root_strategy = :mastodon Chewy.request_strategy = :mastodon Chewy.use_after_commit_callbacks = false diff --git a/lib/mastodon/sidekiq_middleware.rb b/lib/mastodon/sidekiq_middleware.rb index c75e8401f..9832e1a27 100644 --- a/lib/mastodon/sidekiq_middleware.rb +++ b/lib/mastodon/sidekiq_middleware.rb @@ -3,8 +3,8 @@ class Mastodon::SidekiqMiddleware BACKTRACE_LIMIT = 3 - def call(*) - yield + def call(*, &block) + Chewy.strategy(:mastodon, &block) rescue Mastodon::HostValidationError # Do not retry rescue => e From 419bd9281d97c6de572093db4ed9bc489f96db72 Mon Sep 17 00:00:00 2001 From: Christian Schmidt Date: Mon, 6 Mar 2023 15:37:19 +0100 Subject: [PATCH 13/39] Do not strip tags from `Setting.site_short_description` (#23975) --- app/views/application/_sidebar.html.haml | 2 +- app/views/shared/_og.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/application/_sidebar.html.haml b/app/views/application/_sidebar.html.haml index 6d18668b0..9d0efa7e1 100644 --- a/app/views/application/_sidebar.html.haml +++ b/app/views/application/_sidebar.html.haml @@ -3,7 +3,7 @@ = image_tag @instance_presenter.thumbnail&.file&.url(:'@1x') || asset_pack_path('media/images/preview.png'), alt: @instance_presenter.title .hero-widget__text - %p= @instance_presenter.description.html_safe.presence || t('about.about_mastodon_html') + %p= @instance_presenter.description.presence || t('about.about_mastodon_html') - if Setting.trends && !(user_signed_in? && !current_user.setting_trends) - trends = Trends.tags.query.allowed.limit(3) diff --git a/app/views/shared/_og.html.haml b/app/views/shared/_og.html.haml index 2941b566e..a5d99ae33 100644 --- a/app/views/shared/_og.html.haml +++ b/app/views/shared/_og.html.haml @@ -1,5 +1,5 @@ - thumbnail = @instance_presenter.thumbnail -- description ||= strip_tags(@instance_presenter.description.presence || t('about.about_mastodon_html')) +- description ||= @instance_presenter.description.presence || strip_tags(t('about.about_mastodon_html')) %meta{ name: 'description', content: description }/ From 4ea4c3f49c24e7cbd82058a7e802602f5d7e85ac Mon Sep 17 00:00:00 2001 From: Christian Schmidt Date: Wed, 8 Mar 2023 19:56:41 +0100 Subject: [PATCH 14/39] Unescape HTML entities (#24019) --- app/lib/plain_text_formatter.rb | 6 ++- spec/lib/plain_text_formatter_spec.rb | 61 ++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/app/lib/plain_text_formatter.rb b/app/lib/plain_text_formatter.rb index 08aa29696..6fa2bc5d2 100644 --- a/app/lib/plain_text_formatter.rb +++ b/app/lib/plain_text_formatter.rb @@ -18,7 +18,7 @@ class PlainTextFormatter if local? text else - strip_tags(insert_newlines).chomp + html_entities.decode(strip_tags(insert_newlines)).chomp end end @@ -27,4 +27,8 @@ class PlainTextFormatter def insert_newlines text.gsub(NEWLINE_TAGS_RE) { |match| "#{match}\n" } end + + def html_entities + HTMLEntities.new + end end diff --git a/spec/lib/plain_text_formatter_spec.rb b/spec/lib/plain_text_formatter_spec.rb index c3d0ee630..81e4ae286 100644 --- a/spec/lib/plain_text_formatter_spec.rb +++ b/spec/lib/plain_text_formatter_spec.rb @@ -4,7 +4,7 @@ RSpec.describe PlainTextFormatter do describe '#to_s' do subject { described_class.new(status.text, status.local?).to_s } - context 'given a post with local status' do + context 'when status is local' do let(:status) { Fabricate(:status, text: '

a text by a nerd who uses an HTML tag in text

', uri: nil) } it 'returns the raw text' do @@ -12,12 +12,63 @@ RSpec.describe PlainTextFormatter do end end - context 'given a post with remote status' do + context 'when status is remote' do let(:remote_account) { Fabricate(:account, domain: 'remote.test', username: 'bob', url: 'https://remote.test/') } - let(:status) { Fabricate(:status, account: remote_account, text: '

Hello

') } - it 'returns tag-stripped text' do - is_expected.to eq 'Hello' + context 'when text contains inline HTML tags' do + let(:status) { Fabricate(:status, account: remote_account, text: 'Lorem ipsum') } + + it 'strips the tags' do + expect(subject).to eq 'Lorem ipsum' + end + end + + context 'when text contains

tags' do + let(:status) { Fabricate(:status, account: remote_account, text: '

Lorem

ipsum

') } + + it 'inserts a newline' do + expect(subject).to eq "Lorem\nipsum" + end + end + + context 'when text contains a single
tag' do + let(:status) { Fabricate(:status, account: remote_account, text: 'Lorem
ipsum') } + + it 'inserts a newline' do + expect(subject).to eq "Lorem\nipsum" + end + end + + context 'when text contains consecutive
tag' do + let(:status) { Fabricate(:status, account: remote_account, text: 'Lorem


ipsum') } + + it 'inserts a single newline' do + expect(subject).to eq "Lorem\nipsum" + end + end + + context 'when text contains HTML entity' do + let(:status) { Fabricate(:status, account: remote_account, text: 'Lorem & ipsum ❤') } + + it 'unescapes the entity' do + expect(subject).to eq 'Lorem & ipsum ❤' + end + end + + context 'when text contains ipsum') } + + it 'strips the tag and its contents' do + expect(subject).to eq 'Lorem ipsum' + end + end + + context 'when text contains an HTML comment tags' do + let(:status) { Fabricate(:status, account: remote_account, text: 'Lorem ipsum') } + + it 'strips the comment' do + expect(subject).to eq 'Lorem ipsum' + end end end end From c44ddbdb3ec0daf11a362629e7caaecd958eea3a Mon Sep 17 00:00:00 2001 From: Thijs Kinkhorst Date: Tue, 14 Feb 2023 19:05:57 +0100 Subject: [PATCH 15/39] Fix paths with url-encoded @ to redirect to the correct path (#23593) --- config/routes.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/routes.rb b/config/routes.rb index d71a9bbbe..fc27e0cb6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -109,6 +109,8 @@ Rails.application.routes.draw do resource :inbox, only: [:create], module: :activitypub + get '/:encoded_at(*path)', to: redirect("/@%{path}"), constraints: { encoded_at: /%40/ } + constraints(username: /[^@\/.]+/) do get '/@:username', to: 'accounts#show', as: :short_account get '/@:username/with_replies', to: 'accounts#show', as: :short_account_with_replies From bd43f7d4cc40140306023acd8f205e3a3a42cbee Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 21 Feb 2023 09:23:39 +0100 Subject: [PATCH 16/39] Add `lang` tag to native language names in language picker (#23749) --- .../mastodon/features/compose/components/language_dropdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/compose/components/language_dropdown.js b/app/javascript/mastodon/features/compose/components/language_dropdown.js index bf56fd0fa..bac6c1c77 100644 --- a/app/javascript/mastodon/features/compose/components/language_dropdown.js +++ b/app/javascript/mastodon/features/compose/components/language_dropdown.js @@ -216,7 +216,7 @@ class LanguageDropdownMenu extends React.PureComponent { return (
- {lang[2]} ({lang[1]}) + {lang[2]} ({lang[1]})
); } From 97e19e8802f16581c49dfa2350b6d0a626d085c8 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 3 Mar 2023 20:44:46 +0100 Subject: [PATCH 17/39] Add mail headers to avoid auto-replies (#23597) --- app/mailers/application_mailer.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index a37682eca..4edcb75f3 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -7,6 +7,8 @@ class ApplicationMailer < ActionMailer::Base helper :instance helper :formatting + after_action :set_autoreply_headers! + protected def locale_for_account(account) @@ -14,4 +16,10 @@ class ApplicationMailer < ActionMailer::Base yield end end + + def set_autoreply_headers! + headers['Precedence'] = 'list' + headers['X-Auto-Response-Suppress'] = 'All' + headers['Auto-Submitted'] = 'auto-generated' + end end From 1da72b41c70e8ead726a446fdd4f96dc8e70dee5 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 14 Mar 2023 10:05:48 +0100 Subject: [PATCH 18/39] Update changelog --- CHANGELOG.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1ad9e5fd..63d617f4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,31 @@ Changelog All notable changes to this project will be documented in this file. +# [4.0.3] - UNRELEASED + +### Added + +- Add redirection from paths with url-encoded `@` to their decoded form ([thijskh](https://github.com/mastodon/mastodon/pull/23593)) +- Add `lang` attribute to native language names in language picker in Web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23749)) +- Add headers to outgoing mails to avoid auto-replies ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23597)) + +### Fixed + +- Fix “Remove all followers from the selected domains” being more destructive than it claims ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23805)) +- Fix case-sensitive check for previously used hashtags in hashtag autocompletion ([deanveloper](https://github.com/mastodon/mastodon/pull/23526)) +- Fix sidebar behavior in settings/admin UI on mobile ([wxt2005](https://github.com/mastodon/mastodon/pull/23764)) +- Fix inefficiency when searching accounts per username in admin interface ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23801)) +- Fix server error when failing to follow back followers from `/relationships` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23787)) +- Fix server error when attempting to display the edit history of a trendable post in the admin interface ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23574)) +- Fix original account being unfollowed on migration before the follow request to the new account could be sent ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/21957)) +- Fix pgBouncer resetting application name on every transaction ([Gargron](https://github.com/mastodon/mastodon/pull/23958)) +- Fix unconfirmed accounts being counted as active users ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23803)) +- Fix `/api/v1/streaming` sub-paths not being redirected ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23988)) +- Fix drag'n'drop upload area text that spans multiple lines not being centered ([vintprox](https://github.com/mastodon/mastodon/pull/24029)) +- Fix sidekiq jobs not triggering Elasticsearch index updates ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24046)) +- Fix tags being stripped from plain-text short site description ([c960657](https://github.com/mastodon/mastodon/pull/23975)) +- Fix HTML entities not being un-escaped in extracted plain-text from remote posts ([c960657](https://github.com/mastodon/mastodon/pull/24019)) + ## [4.0.2] - 2022-11-15 ### Fixed From f834fdaf6a7ae1c16527532cbfc5a384d0449c75 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 15 Mar 2023 04:01:49 +0100 Subject: [PATCH 19/39] Fix dashboard crash on ElasticSearch server error (#23751) --- app/lib/admin/system_check/elasticsearch_check.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/admin/system_check/elasticsearch_check.rb b/app/lib/admin/system_check/elasticsearch_check.rb index 8aee18267..e04ec085d 100644 --- a/app/lib/admin/system_check/elasticsearch_check.rb +++ b/app/lib/admin/system_check/elasticsearch_check.rb @@ -24,7 +24,7 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck def running_version @running_version ||= begin Chewy.client.info['version']['number'] - rescue Faraday::ConnectionFailed + rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error nil end end From 86924c344d17235847f4b83105beddfff0412154 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 15 Mar 2023 04:14:47 +0100 Subject: [PATCH 20/39] Fix incorrect post links in strikes when the account is remote (#23611) --- app/views/disputes/strikes/show.html.haml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/views/disputes/strikes/show.html.haml b/app/views/disputes/strikes/show.html.haml index 4a3005f72..edf7463e5 100644 --- a/app/views/disputes/strikes/show.html.haml +++ b/app/views/disputes/strikes/show.html.haml @@ -50,15 +50,15 @@ .strike-card__statuses-list__item - if (status = status_map[status_id.to_i]) .one-liner - = link_to short_account_status_url(@strike.target_account, status_id), class: 'emojify' do - = one_line_preview(status) + .emojify= one_line_preview(status) - - status.ordered_media_attachments.each do |media_attachment| - %abbr{ title: media_attachment.description } - = fa_icon 'link' - = media_attachment.file_file_name + - status.ordered_media_attachments.each do |media_attachment| + %abbr{ title: media_attachment.description } + = fa_icon 'link' + = media_attachment.file_file_name .strike-card__statuses-list__item__meta - %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) + = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank' do + %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) - unless status.application.nil? · = status.application.name From 2c3cb903ad9fa31745a25737e355306ce77aa263 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 15 Mar 2023 04:15:20 +0100 Subject: [PATCH 21/39] Fix misleading error code when receiving invalid WebAuthn credentials (#23568) --- .../webauthn_credentials_controller.rb | 2 +- .../webauthn_credentials_controller_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb b/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb index a50d30f06..8435155dd 100644 --- a/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb +++ b/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb @@ -52,7 +52,7 @@ module Settings end else flash[:error] = I18n.t('webauthn_credentials.create.error') - status = :internal_server_error + status = :unprocessable_entity end else flash[:error] = t('webauthn_credentials.create.error') diff --git a/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb index fe53b4dfc..269c4d685 100644 --- a/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb @@ -248,7 +248,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do post :create, params: { credential: new_webauthn_credential, nickname: 'USB Key' } - expect(response).to have_http_status(500) + expect(response).to have_http_status(422) expect(flash[:error]).to be_present end end @@ -268,7 +268,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do post :create, params: { credential: new_webauthn_credential, nickname: nickname } - expect(response).to have_http_status(500) + expect(response).to have_http_status(422) expect(flash[:error]).to be_present end end From 98c59c1d580c344655805ed14ab83df1a29a7d1c Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Tue, 14 Mar 2023 20:27:43 +0100 Subject: [PATCH 22/39] Push Docker images to Github Container Registry as well (#24101) --- .github/workflows/build-image.yml | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 39fe1bd0b..846a5e755 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -12,6 +12,7 @@ on: - Dockerfile permissions: contents: read + packages: write jobs: build-image: @@ -20,15 +21,28 @@ jobs: - uses: actions/checkout@v3 - uses: docker/setup-qemu-action@v2 - uses: docker/setup-buildx-action@v2 - - uses: docker/login-action@v2 + + - name: Log in to Docker Hub + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} if: github.event_name != 'pull_request' + + - name: Log in to the Github Container registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + if: github.event_name != 'pull_request' + - uses: docker/metadata-action@v4 id: meta with: - images: tootsuite/mastodon + images: | + tootsuite/mastodon + ghcr.io/mastodon/mastodon flavor: | latest=auto tags: | @@ -36,11 +50,13 @@ jobs: type=pep440,pattern={{raw}} type=pep440,pattern=v{{major}}.{{minor}} type=ref,event=pr - - uses: docker/build-push-action@v3 + + - uses: docker/build-push-action@v4 with: context: . platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} - cache-from: type=registry,ref=tootsuite/mastodon:edge - cache-to: type=inline + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max From 0941230e227734af8b9d00c5773fe2a7ee636ffa Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Tue, 14 Mar 2023 22:43:49 -0400 Subject: [PATCH 23/39] Skip Docker CI Login/Push on forks (#23564) --- .github/workflows/build-image.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 846a5e755..247028206 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -27,7 +27,7 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - if: github.event_name != 'pull_request' + if: github.repository == 'mastodon/mastodon' && github.event_name != 'pull_request' - name: Log in to the Github Container registry uses: docker/login-action@v2 @@ -35,7 +35,7 @@ jobs: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - if: github.event_name != 'pull_request' + if: github.repository == 'mastodon/mastodon' && github.event_name != 'pull_request' - uses: docker/metadata-action@v4 id: meta From 520377a609ab2fbffee116ff8336082c28619c56 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Wed, 15 Mar 2023 16:41:13 +0100 Subject: [PATCH 24/39] Use Github Container Registry as the official container image source (#24113) --- README.md | 3 +-- docker-compose.yml | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5019bd097..33ae3867e 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,11 @@ [![Build Status](https://img.shields.io/circleci/project/github/mastodon/mastodon.svg)][circleci] [![Code Climate](https://img.shields.io/codeclimate/maintainability/mastodon/mastodon.svg)][code_climate] [![Crowdin](https://d322cqt584bo4o.cloudfront.net/mastodon/localized.svg)][crowdin] -[![Docker Pulls](https://img.shields.io/docker/pulls/tootsuite/mastodon.svg)][docker] [releases]: https://github.com/mastodon/mastodon/releases [circleci]: https://circleci.com/gh/mastodon/mastodon [code_climate]: https://codeclimate.com/github/mastodon/mastodon [crowdin]: https://crowdin.com/project/mastodon -[docker]: https://hub.docker.com/r/tootsuite/mastodon/ Mastodon is a **free, open-source social network server** based on ActivityPub where users can follow friends and discover new ones. On Mastodon, users can publish anything they want: links, pictures, text, video. All Mastodon servers are interoperable as a federated network (users on one server can seamlessly communicate with users from another one, including non-Mastodon software that implements ActivityPub)! @@ -31,6 +29,7 @@ Click below to **learn more** in a video: - [View sponsors](https://joinmastodon.org/sponsors) - [Blog](https://blog.joinmastodon.org) - [Documentation](https://docs.joinmastodon.org) +- [Official Docker image](https://github.com/mastodon/mastodon/pkgs/container/mastodon) - [Browse Mastodon servers](https://joinmastodon.org/communities) - [Browse Mastodon apps](https://joinmastodon.org/apps) diff --git a/docker-compose.yml b/docker-compose.yml index c534286c7..f603c2f7e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -56,7 +56,7 @@ services: web: build: . - image: tootsuite/mastodon + image: ghcr.io/mastodon/mastodon restart: always env_file: .env.production command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000" @@ -77,7 +77,7 @@ services: streaming: build: . - image: tootsuite/mastodon + image: ghcr.io/mastodon/mastodon restart: always env_file: .env.production command: node ./streaming @@ -95,7 +95,7 @@ services: sidekiq: build: . - image: tootsuite/mastodon + image: ghcr.io/mastodon/mastodon restart: always env_file: .env.production command: bundle exec sidekiq From 43a16e43baa0ce62367f238721ee8ce939e75a20 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Wed, 15 Mar 2023 11:43:44 -0400 Subject: [PATCH 25/39] Skip pushing containers on forks (#24106) --- .github/workflows/build-image.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 247028206..9500c5e22 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -55,7 +55,9 @@ jobs: with: context: . platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} + provenance: false + builder: ${{ steps.buildx.outputs.name }} + push: ${{ github.repository == 'mastodon/mastodon' && github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha From 8236c3affc98fd36f317c83da9b38ce40c062417 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 16 Mar 2023 12:04:15 +0100 Subject: [PATCH 26/39] Update changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63d617f4b..35d555d93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ All notable changes to this project will be documented in this file. - Add `lang` attribute to native language names in language picker in Web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23749)) - Add headers to outgoing mails to avoid auto-replies ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23597)) +## Changed + +- Change Docker images to be pushed to Github Container Registry ([renchap](https://github.com/mastodon/mastodon/pull/24101), [nschonni](https://github.com/mastodon/mastodon/pull/23564), [renchap](https://github.com/mastodon/mastodon/pull/24113), [nschonni](https://github.com/mastodon/mastodon/pull/24106)) + ### Fixed - Fix “Remove all followers from the selected domains” being more destructive than it claims ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23805)) @@ -27,6 +31,9 @@ All notable changes to this project will be documented in this file. - Fix sidekiq jobs not triggering Elasticsearch index updates ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24046)) - Fix tags being stripped from plain-text short site description ([c960657](https://github.com/mastodon/mastodon/pull/23975)) - Fix HTML entities not being un-escaped in extracted plain-text from remote posts ([c960657](https://github.com/mastodon/mastodon/pull/24019)) +- Fix dashboard crash on ElasticSearch server error ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23751)) +- Fix incorrect post links in strikes when the account is remote ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23611)) +- Fix misleading error code when receiving invalid WebAuthn credentials ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23568)) ## [4.0.2] - 2022-11-15 ### Fixed From 3e9978071b51048b79d76e0f46248ac9381463da Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 16 Mar 2023 22:05:00 +0100 Subject: [PATCH 27/39] Update changelog --- CHANGELOG.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35d555d93..f85c96d2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,6 @@ All notable changes to this project will be documented in this file. - Add `lang` attribute to native language names in language picker in Web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23749)) - Add headers to outgoing mails to avoid auto-replies ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23597)) -## Changed - -- Change Docker images to be pushed to Github Container Registry ([renchap](https://github.com/mastodon/mastodon/pull/24101), [nschonni](https://github.com/mastodon/mastodon/pull/23564), [renchap](https://github.com/mastodon/mastodon/pull/24113), [nschonni](https://github.com/mastodon/mastodon/pull/24106)) - ### Fixed - Fix “Remove all followers from the selected domains” being more destructive than it claims ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23805)) @@ -29,7 +25,7 @@ All notable changes to this project will be documented in this file. - Fix `/api/v1/streaming` sub-paths not being redirected ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23988)) - Fix drag'n'drop upload area text that spans multiple lines not being centered ([vintprox](https://github.com/mastodon/mastodon/pull/24029)) - Fix sidekiq jobs not triggering Elasticsearch index updates ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24046)) -- Fix tags being stripped from plain-text short site description ([c960657](https://github.com/mastodon/mastodon/pull/23975)) +- Fix tags being unnecessarily stripped from plain-text short site description ([c960657](https://github.com/mastodon/mastodon/pull/23975)) - Fix HTML entities not being un-escaped in extracted plain-text from remote posts ([c960657](https://github.com/mastodon/mastodon/pull/24019)) - Fix dashboard crash on ElasticSearch server error ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23751)) - Fix incorrect post links in strikes when the account is remote ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23611)) From a6217bd035093a0e568ba10ed2d2f9f3c3946c19 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 16 Mar 2023 22:46:52 +0100 Subject: [PATCH 28/39] Change user backups to use expiring URLs for download when possible (#24136) --- app/controllers/backups_controller.rb | 27 ++++++++++++++++++++ app/models/backup.rb | 2 +- app/views/settings/exports/show.html.haml | 2 +- app/views/user_mailer/backup_ready.html.haml | 2 +- app/views/user_mailer/backup_ready.text.erb | 2 +- config/routes.rb | 1 + 6 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 app/controllers/backups_controller.rb diff --git a/app/controllers/backups_controller.rb b/app/controllers/backups_controller.rb new file mode 100644 index 000000000..2f4b400b8 --- /dev/null +++ b/app/controllers/backups_controller.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +class BackupsController < ApplicationController + include RoutingHelper + + skip_before_action :require_functional! + + before_action :authenticate_user! + before_action :set_backup + + def download + case Paperclip::Attachment.default_options[:storage] + when :s3 + redirect_to @backup.dump.expiring_url(10) + when :fog + redirect_to @backup.dump.expiring_url(Time.now.utc + 10) + when :filesystem + redirect_to full_asset_url(@backup.dump.url) + end + end + + private + + def set_backup + @backup = current_user.backups.find(params[:id]) + end +end diff --git a/app/models/backup.rb b/app/models/backup.rb index d242fd62c..20e6e8aa8 100644 --- a/app/models/backup.rb +++ b/app/models/backup.rb @@ -17,6 +17,6 @@ class Backup < ApplicationRecord belongs_to :user, inverse_of: :backups - has_attached_file :dump + has_attached_file :dump, s3_permissions: 'private' do_not_validate_attachment_file_type :dump end diff --git a/app/views/settings/exports/show.html.haml b/app/views/settings/exports/show.html.haml index c49613fdc..d7b59af27 100644 --- a/app/views/settings/exports/show.html.haml +++ b/app/views/settings/exports/show.html.haml @@ -64,6 +64,6 @@ %td= l backup.created_at - if backup.processed? %td= number_to_human_size backup.dump_file_size - %td= table_link_to 'download', t('exports.archive_takeout.download'), backup.dump.url + %td= table_link_to 'download', t('exports.archive_takeout.download'), download_backup_url(backup) - else %td{ colspan: 2 }= t('exports.archive_takeout.in_progress') diff --git a/app/views/user_mailer/backup_ready.html.haml b/app/views/user_mailer/backup_ready.html.haml index 85140b08b..465ead2c8 100644 --- a/app/views/user_mailer/backup_ready.html.haml +++ b/app/views/user_mailer/backup_ready.html.haml @@ -55,5 +55,5 @@ %tbody %tr %td.button-primary - = link_to full_asset_url(@backup.dump.url) do + = link_to download_backup_url(@backup) do %span= t 'exports.archive_takeout.download' diff --git a/app/views/user_mailer/backup_ready.text.erb b/app/views/user_mailer/backup_ready.text.erb index eb89e7d74..8ebbaae85 100644 --- a/app/views/user_mailer/backup_ready.text.erb +++ b/app/views/user_mailer/backup_ready.text.erb @@ -4,4 +4,4 @@ <%= t 'user_mailer.backup_ready.explanation' %> -=> <%= full_asset_url(@backup.dump.url) %> +=> <%= download_backup_url(@backup) %> diff --git a/config/routes.rb b/config/routes.rb index fc27e0cb6..c11b78ba2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -219,6 +219,7 @@ Rails.application.routes.draw do resource :statuses_cleanup, controller: :statuses_cleanup, only: [:show, :update] get '/media_proxy/:id/(*any)', to: 'media_proxy#show', as: :media_proxy, format: false + get '/backups/:id/download', to: 'backups#download', as: :download_backup, format: false resource :authorize_interaction, only: [:show, :create] resource :share, only: [:show, :create] From 9715a211c7d606ee180da19aff98eb18641ee96b Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 16 Mar 2023 22:47:01 +0100 Subject: [PATCH 29/39] Add warning for object storage misconfiguration (#24137) --- app/lib/admin/system_check.rb | 1 + .../admin/system_check/media_privacy_check.rb | 105 ++++++++++++++++++ app/lib/admin/system_check/message.rb | 11 +- app/views/admin/dashboard/index.html.haml | 2 +- config/locales/en.yml | 6 + 5 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 app/lib/admin/system_check/media_privacy_check.rb diff --git a/app/lib/admin/system_check.rb b/app/lib/admin/system_check.rb index f512635ab..89dfcef9f 100644 --- a/app/lib/admin/system_check.rb +++ b/app/lib/admin/system_check.rb @@ -2,6 +2,7 @@ class Admin::SystemCheck ACTIVE_CHECKS = [ + Admin::SystemCheck::MediaPrivacyCheck, Admin::SystemCheck::DatabaseSchemaCheck, Admin::SystemCheck::SidekiqProcessCheck, Admin::SystemCheck::RulesCheck, diff --git a/app/lib/admin/system_check/media_privacy_check.rb b/app/lib/admin/system_check/media_privacy_check.rb new file mode 100644 index 000000000..1df05b120 --- /dev/null +++ b/app/lib/admin/system_check/media_privacy_check.rb @@ -0,0 +1,105 @@ +# frozen_string_literal: true + +class Admin::SystemCheck::MediaPrivacyCheck < Admin::SystemCheck::BaseCheck + include RoutingHelper + + def skip? + !current_user.can?(:view_devops) + end + + def pass? + check_media_uploads! + @failure_message.nil? + end + + def message + Admin::SystemCheck::Message.new(@failure_message, @failure_value, @failure_action, true) + end + + private + + def check_media_uploads! + if Rails.configuration.x.use_s3 + check_media_listing_inaccessible_s3! + else + check_media_listing_inaccessible! + end + end + + def check_media_listing_inaccessible! + full_url = full_asset_url(media_attachment.file.url(:original, false)) + + # Check if we can list the uploaded file. If true, that's an error + directory_url = Addressable::URI.parse(full_url) + directory_url.query = nil + filename = directory_url.path.gsub(%r{.*/}, '') + directory_url.path = directory_url.path.gsub(%r{/[^/]+\Z}, '/') + Request.new(:get, directory_url, allow_local: true).perform do |res| + if res.truncated_body&.include?(filename) + @failure_message = use_storage? ? :upload_check_privacy_error_object_storage : :upload_check_privacy_error + @failure_action = 'https://docs.joinmastodon.org/admin/optional/object-storage/#FS' + end + end + rescue + nil + end + + def check_media_listing_inaccessible_s3! + urls_to_check = [] + paperclip_options = Paperclip::Attachment.default_options + s3_protocol = paperclip_options[:s3_protocol] + s3_host_alias = paperclip_options[:s3_host_alias] + s3_host_name = paperclip_options[:s3_host_name] + bucket_name = paperclip_options.dig(:s3_credentials, :bucket) + + urls_to_check << "#{s3_protocol}://#{s3_host_alias}/" if s3_host_alias.present? + urls_to_check << "#{s3_protocol}://#{s3_host_name}/#{bucket_name}/" + urls_to_check.uniq.each do |full_url| + check_s3_listing!(full_url) + break if @failure_message.present? + end + rescue + nil + end + + def check_s3_listing!(full_url) + bucket_url = Addressable::URI.parse(full_url) + bucket_url.path = bucket_url.path.delete_suffix(media_attachment.file.path(:original)) + bucket_url.query = "max-keys=1&x-random=#{SecureRandom.hex(10)}" + Request.new(:get, bucket_url, allow_local: true).perform do |res| + if res.truncated_body&.include?('ListBucketResult') + @failure_message = :upload_check_privacy_error_object_storage + @failure_action = 'https://docs.joinmastodon.org/admin/optional/object-storage/#S3' + end + end + end + + def media_attachment + @media_attachment ||= begin + attachment = Account.representative.media_attachments.first + if attachment.present? + attachment.touch # rubocop:disable Rails/SkipsModelValidations + attachment + else + create_test_attachment! + end + end + end + + def create_test_attachment! + Tempfile.create(%w(test-upload .jpg), binmode: true) do |tmp_file| + tmp_file.write( + Base64.decode64( + '/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAA' \ + 'AAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA' \ + 'QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE' \ + 'BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/x' \ + 'ABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAA' \ + 'AAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==' + ) + ) + tmp_file.flush + Account.representative.media_attachments.create!(file: tmp_file) + end + end +end diff --git a/app/lib/admin/system_check/message.rb b/app/lib/admin/system_check/message.rb index bfcad3bf3..ad8d4b607 100644 --- a/app/lib/admin/system_check/message.rb +++ b/app/lib/admin/system_check/message.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true class Admin::SystemCheck::Message - attr_reader :key, :value, :action + attr_reader :key, :value, :action, :critical - def initialize(key, value = nil, action = nil) - @key = key - @value = value - @action = action + def initialize(key, value = nil, action = nil, critical = false) + @key = key + @value = value + @action = action + @critical = critical end end diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index 8354f0b9f..425472abd 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -12,7 +12,7 @@ - unless @system_checks.empty? .flash-message-stack - @system_checks.each do |message| - .flash-message.warning + .flash-message{ class: message.critical ? 'alert' : 'warning' } = t("admin.system_checks.#{message.key}.message_html", value: message.value ? content_tag(:strong, message.value) : nil) - if message.action = link_to t("admin.system_checks.#{message.key}.action"), message.action diff --git a/config/locales/en.yml b/config/locales/en.yml index 6332f0f01..6f246f5fd 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -756,6 +756,12 @@ en: message_html: You haven't defined any server rules. sidekiq_process_check: message_html: No Sidekiq process running for the %{value} queue(s). Please review your Sidekiq configuration + upload_check_privacy_error: + action: Check here for more information + message_html: "Your web server is misconfigured. The privacy of your users is at risk." + upload_check_privacy_error_object_storage: + action: Check here for more information + message_html: "Your object storage is misconfigured. The privacy of your users is at risk." tags: review: Review status updated_msg: Hashtag settings updated successfully From 2125dbf6109fc7376d4cdf22520672b39ee31988 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 16 Mar 2023 22:36:28 +0100 Subject: [PATCH 30/39] Bump version to v4.0.3 --- CHANGELOG.md | 7 ++++++- lib/mastodon/version.rb | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f85c96d2e..08589391d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ Changelog All notable changes to this project will be documented in this file. -# [4.0.3] - UNRELEASED +# [4.0.3] - 2023-03-16 ### Added @@ -31,6 +31,11 @@ All notable changes to this project will be documented in this file. - Fix incorrect post links in strikes when the account is remote ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23611)) - Fix misleading error code when receiving invalid WebAuthn credentials ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23568)) +### Security + +- Change user backups to use expiring URLs for download when possible ([Gargron](https://github.com/mastodon/mastodon/pull/24136)) +- Add warning for object storage misconfiguration ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24137)) + ## [4.0.2] - 2022-11-15 ### Fixed diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index dc3cbab66..ed4d1defa 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -13,7 +13,7 @@ module Mastodon end def patch - 2 + 3 end def flags From f75fba0531a0f2cfd0797f9f94023090b401f05b Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 20 Mar 2023 20:02:58 +0100 Subject: [PATCH 31/39] Fix crash in `tootctl` commands making use of parallelization when Elasticsearch is enabled (#24182) --- lib/mastodon/cli_helper.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/mastodon/cli_helper.rb b/lib/mastodon/cli_helper.rb index a78a28e27..4e304c903 100644 --- a/lib/mastodon/cli_helper.rb +++ b/lib/mastodon/cli_helper.rb @@ -53,14 +53,16 @@ module Mastodon progress.log("Processing #{item.id}") if options[:verbose] - result = ActiveRecord::Base.connection_pool.with_connection do - yield(item) - ensure - RedisConfiguration.pool.checkin if Thread.current[:redis] - Thread.current[:redis] = nil - end + Chewy.strategy(:mastodon) do + result = ActiveRecord::Base.connection_pool.with_connection do + yield(item) + ensure + RedisConfiguration.pool.checkin if Thread.current[:redis] + Thread.current[:redis] = nil + end - aggregate.increment(result) if result.is_a?(Integer) + aggregate.increment(result) if result.is_a?(Integer) + end rescue => e progress.log pastel.red("Error processing #{item.id}: #{e}") ensure From aa37eeadf35aa01ea5b84650cb75037f79c87c32 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 27 Mar 2023 17:07:37 +0200 Subject: [PATCH 32/39] Fix user archive takeout when using OpenStack Swift or S3 providers with no ACL support (#24200) --- app/controllers/backups_controller.rb | 6 +++++- app/models/backup.rb | 2 +- config/initializers/paperclip.rb | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/controllers/backups_controller.rb b/app/controllers/backups_controller.rb index 2f4b400b8..0687b62c5 100644 --- a/app/controllers/backups_controller.rb +++ b/app/controllers/backups_controller.rb @@ -13,7 +13,11 @@ class BackupsController < ApplicationController when :s3 redirect_to @backup.dump.expiring_url(10) when :fog - redirect_to @backup.dump.expiring_url(Time.now.utc + 10) + if Paperclip::Attachment.default_options.dig(:storage, :fog_credentials, :openstack_temp_url_key).present? + redirect_to @backup.dump.expiring_url(Time.now.utc + 10) + else + redirect_to full_asset_url(@backup.dump.url) + end when :filesystem redirect_to full_asset_url(@backup.dump.url) end diff --git a/app/models/backup.rb b/app/models/backup.rb index 20e6e8aa8..8823e7cae 100644 --- a/app/models/backup.rb +++ b/app/models/backup.rb @@ -17,6 +17,6 @@ class Backup < ApplicationRecord belongs_to :user, inverse_of: :backups - has_attached_file :dump, s3_permissions: 'private' + has_attached_file :dump, s3_permissions: ->(*) { ENV['S3_PERMISSION'] == '' ? nil : 'private' } do_not_validate_attachment_file_type :dump end diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb index a2285427c..63f0d9240 100644 --- a/config/initializers/paperclip.rb +++ b/config/initializers/paperclip.rb @@ -124,6 +124,7 @@ elsif ENV['SWIFT_ENABLED'] == 'true' openstack_domain_name: ENV.fetch('SWIFT_DOMAIN_NAME') { 'default' }, openstack_region: ENV['SWIFT_REGION'], openstack_cache_ttl: ENV.fetch('SWIFT_CACHE_TTL') { 60 }, + openstack_temp_url_key: ENV['SWIFT_TEMP_URL_KEY'], }, fog_file: { 'Cache-Control' => 'public, max-age=315576000, immutable' }, From 971e8b8f5f58b9dc4cef817f154b26076fc77a1a Mon Sep 17 00:00:00 2001 From: Robert R George Date: Wed, 29 Mar 2023 00:58:27 -0700 Subject: [PATCH 33/39] Wrap db:setup with Chewy.strategy(:mastodon) (#24302) --- db/seeds.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index 1ca300de7..c01e83f1d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true -Dir[Rails.root.join('db', 'seeds', '*.rb')].sort.each do |seed| - load seed +Chewy.strategy(:mastodon) do + Dir[Rails.root.join('db', 'seeds', '*.rb')].sort.each do |seed| + load seed + end end From acc277a1529d7b4875633fab04750daef59abdfd Mon Sep 17 00:00:00 2001 From: mhkhung Date: Wed, 30 Nov 2022 03:56:27 -0500 Subject: [PATCH 34/39] 3.0.5 version of cimg/ruby:3.0-node upgraded to node 18 (#21873) Node 18 caused build to fail --- .circleci/config.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2a60ae684..bddfd2d27 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -68,7 +68,9 @@ jobs: cache-version: v1 pkg-manager: yarn - run: - command: ./bin/rails assets:precompile + command: | + export NODE_OPTIONS=--openssl-legacy-provider + ./bin/rails assets:precompile name: Precompile assets - persist_to_workspace: paths: From 46b91cd817977d2e986dedb411e6fdc291fafd0b Mon Sep 17 00:00:00 2001 From: Sai Date: Fri, 31 Mar 2023 15:54:42 +0100 Subject: [PATCH 35/39] Update Ruby to 3.0.6 (#24333) --- .ruby-version | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ruby-version b/.ruby-version index b0f2dcb32..818bd47ab 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.0.4 +3.0.6 diff --git a/Dockerfile b/Dockerfile index cf311fef2..d560f1888 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN ARCH= && \ mv node-v$NODE_VER-linux-$ARCH /opt/node # Install Ruby 3.0 -ENV RUBY_VER="3.0.4" +ENV RUBY_VER="3.0.6" RUN apt-get update && \ apt-get install -y --no-install-recommends build-essential \ bison libyaml-dev libgdbm-dev libreadline-dev libjemalloc-dev \ From 274bb193b22c80b79f4a83f0e9449d58fcb22572 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 31 Mar 2023 21:42:28 +0200 Subject: [PATCH 36/39] Fix invalid/expired invites being processed on sign-up (#24337) --- app/controllers/auth/registrations_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 14e0d9a36..c4de20231 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -48,7 +48,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController super(hash) resource.locale = I18n.locale - resource.invite_code = params[:invite_code] if resource.invite_code.blank? + resource.invite_code = @invite&.code if resource.invite_code.blank? resource.registration_form_time = session[:registration_form_time] resource.sign_up_ip = request.remote_ip From 448986438ebbe3fa8062487cccbfe57a469ba7d9 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 3 Apr 2023 15:05:39 +0200 Subject: [PATCH 37/39] Change root Chewy strategy to emit a warning instead of erroring out in production mode (#24327) --- config/application.rb | 1 + config/initializers/chewy.rb | 1 + lib/chewy/strategy/bypass_with_warning.rb | 12 ++++++++++++ 3 files changed, 14 insertions(+) create mode 100644 lib/chewy/strategy/bypass_with_warning.rb diff --git a/config/application.rb b/config/application.rb index 4d6c7ebf1..720ea51ec 100644 --- a/config/application.rb +++ b/config/application.rb @@ -39,6 +39,7 @@ require_relative '../lib/mastodon/rack_middleware' require_relative '../lib/devise/two_factor_ldap_authenticatable' require_relative '../lib/devise/two_factor_pam_authenticatable' require_relative '../lib/chewy/strategy/mastodon' +require_relative '../lib/chewy/strategy/bypass_with_warning' require_relative '../lib/webpacker/manifest_extensions' require_relative '../lib/webpacker/helper_extensions' require_relative '../lib/rails/engine_extensions' diff --git a/config/initializers/chewy.rb b/config/initializers/chewy.rb index 2a91efefc..daf4a5f32 100644 --- a/config/initializers/chewy.rb +++ b/config/initializers/chewy.rb @@ -19,6 +19,7 @@ Chewy.settings = { # cycle, which takes care of checking if Elasticsearch is enabled # or not. However, mind that for the Rails console, the :urgent # strategy is set automatically with no way to override it. +Chewy.root_strategy = :bypass_with_warning if Rails.env.production? Chewy.request_strategy = :mastodon Chewy.use_after_commit_callbacks = false diff --git a/lib/chewy/strategy/bypass_with_warning.rb b/lib/chewy/strategy/bypass_with_warning.rb new file mode 100644 index 000000000..eb6fbaab1 --- /dev/null +++ b/lib/chewy/strategy/bypass_with_warning.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Chewy + class Strategy + class BypassWithWarning < Base + def update(...) + Rails.logger.warn 'Chewy update without a root strategy' unless @warning_issued + @warning_issued = true + end + end + end +end From 05c45e9eebf97ec5412f39d7b9e2a8a7c49d2d41 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 3 Apr 2023 15:47:04 +0200 Subject: [PATCH 38/39] Fix unescaped user input in LDAP query (#24379) Fix CVE-2023-28853 --- app/models/concerns/ldap_authenticable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/concerns/ldap_authenticable.rb b/app/models/concerns/ldap_authenticable.rb index dc5abcd5a..775df0817 100644 --- a/app/models/concerns/ldap_authenticable.rb +++ b/app/models/concerns/ldap_authenticable.rb @@ -6,7 +6,7 @@ module LdapAuthenticable class_methods do def authenticate_with_ldap(params = {}) ldap = Net::LDAP.new(ldap_options) - filter = format(Devise.ldap_search_filter, uid: Devise.ldap_uid, mail: Devise.ldap_mail, email: params[:email]) + filter = format(Devise.ldap_search_filter, uid: Devise.ldap_uid, mail: Devise.ldap_mail, email: Net::LDAP::Filter.escape(params[:email])) if (user_info = ldap.bind_as(base: Devise.ldap_base, filter: filter, password: params[:password])) ldap_get_user(user_info.first) From 214c3670959361230c5199e668df4de3da513b22 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 27 Mar 2023 17:47:26 +0200 Subject: [PATCH 39/39] Bump version to v4.0.4 --- CHANGELOG.md | 14 ++++++++++++++ lib/mastodon/version.rb | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08589391d..1ac230ff1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,20 @@ Changelog All notable changes to this project will be documented in this file. +## [4.0.4] - 2023-04-04 + +### Fixed + +- Fix crash in `tootctl` commands making use of parallelization when Elasticsearch is enabled ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24182), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24377)) +- Fix crash in `db:setup` when Elasticsearch is enabled ([rrgeorge](https://github.com/mastodon/mastodon/pull/24302)) +- Fix user archive takeout when using OpenStack Swift or S3 providers with no ACL support ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24200)) +- Fix invalid/expired invites being processed on sign-up ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24337)) + +### Security + +- Update Ruby to 3.0.6 due to ReDoS vulnerabilities ([saizai](https://github.com/mastodon/mastodon/pull/24333)) +- Fix unescaped user input in LDAP query ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24379)) + # [4.0.3] - 2023-03-16 ### Added diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index ed4d1defa..49fe7d8d5 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -13,7 +13,7 @@ module Mastodon end def patch - 3 + 4 end def flags