From 603b245cc62acba0d8f71ad4c31d2f1676e90190 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Wed, 29 Nov 2023 09:34:36 +0100 Subject: [PATCH 01/41] Add VAPID public key to instance serializer (#28006) Co-authored-by: Renaud Chaput --- app/serializers/rest/application_serializer.rb | 5 ++++- app/serializers/rest/instance_serializer.rb | 4 ++++ spec/serializers/rest/instance_serializer_spec.rb | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/serializers/rest/application_serializer.rb b/app/serializers/rest/application_serializer.rb index e4806a3c9fc5b4..635508a17cbe64 100644 --- a/app/serializers/rest/application_serializer.rb +++ b/app/serializers/rest/application_serializer.rb @@ -2,7 +2,10 @@ class REST::ApplicationSerializer < ActiveModel::Serializer attributes :id, :name, :website, :scopes, :redirect_uri, - :client_id, :client_secret, :vapid_key + :client_id, :client_secret + + # NOTE: Deprecated in 4.3.0, needs to be removed in 5.0.0 + attribute :vapid_key def id object.id.to_s diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb index 14aeda9462dbb3..d7ed381e16b36c 100644 --- a/app/serializers/rest/instance_serializer.rb +++ b/app/serializers/rest/instance_serializer.rb @@ -48,6 +48,10 @@ def configuration status: object.status_page_url, }, + vapid: { + public_key: Rails.configuration.x.vapid_public_key, + }, + accounts: { max_featured_tags: FeaturedTag::LIMIT, }, diff --git a/spec/serializers/rest/instance_serializer_spec.rb b/spec/serializers/rest/instance_serializer_spec.rb index 8ac32f2247f79d..d8f2536d200867 100644 --- a/spec/serializers/rest/instance_serializer_spec.rb +++ b/spec/serializers/rest/instance_serializer_spec.rb @@ -10,5 +10,11 @@ it 'returns recent usage data' do expect(serialization['usage']).to eq({ 'users' => { 'active_month' => 0 } }) end + + it 'returns the VAPID public key' do + expect(serialization['configuration']['vapid']).to eq({ + 'public_key' => Rails.configuration.x.vapid_public_key, + }) + end end end From 3e1e41054ba40294ecf70c1216759fc378f46ee0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 Nov 2023 10:00:07 +0100 Subject: [PATCH 02/41] chore(deps): update dependency pghero to v3.4.0 (#28117) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7440f1b327e79a..40f85c7d484b14 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -522,7 +522,7 @@ GEM pastel (0.8.0) tty-color (~> 0.5) pg (1.5.4) - pghero (3.3.4) + pghero (3.4.0) activerecord (>= 6) posix-spawn (0.3.15) premailer (1.21.0) From 186895fc887d8729185fc51f994dca93a30592b1 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:00:52 -0500 Subject: [PATCH 03/41] Refactor, lint fix, and bug fix on admin/roles/form partial (#27558) --- app/helpers/admin/roles_helper.rb | 24 ++++++++++++++++++++++++ app/models/user_role.rb | 6 +++--- app/views/admin/roles/_form.html.haml | 2 +- 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 app/helpers/admin/roles_helper.rb diff --git a/app/helpers/admin/roles_helper.rb b/app/helpers/admin/roles_helper.rb new file mode 100644 index 00000000000000..7b4702e268fe54 --- /dev/null +++ b/app/helpers/admin/roles_helper.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Admin + module RolesHelper + def privilege_label(privilege) + safe_join( + [ + t("admin.roles.privileges.#{privilege}"), + content_tag(:span, t("admin.roles.privileges.#{privilege}_description"), class: 'hint'), + ] + ) + end + + def disable_permissions?(permissions) + permissions.filter { |privilege| role_flag_value(privilege).zero? } + end + + private + + def role_flag_value(privilege) + UserRole::FLAGS[privilege] & current_user.role.computed_permissions + end + end +end diff --git a/app/models/user_role.rb b/app/models/user_role.rb index 5472646c600a0f..89354da5423bb3 100644 --- a/app/models/user_role.rb +++ b/app/models/user_role.rb @@ -49,7 +49,7 @@ module Flags invite_users ).freeze, - moderation: %w( + moderation: %i( view_dashboard view_audit_log manage_users @@ -63,7 +63,7 @@ module Flags manage_invites ).freeze, - administration: %w( + administration: %i( manage_settings manage_rules manage_roles @@ -72,7 +72,7 @@ module Flags manage_announcements ).freeze, - devops: %w( + devops: %i( view_devops ).freeze, diff --git a/app/views/admin/roles/_form.html.haml b/app/views/admin/roles/_form.html.haml index 2400332145be1f..46a1c537a75a0f 100644 --- a/app/views/admin/roles/_form.html.haml +++ b/app/views/admin/roles/_form.html.haml @@ -31,6 +31,6 @@ - (form.object.everyone? ? UserRole::Flags::CATEGORIES.slice(:invites) : UserRole::Flags::CATEGORIES).each do |category, permissions| %h4= t(category, scope: 'admin.roles.categories') - = form.input :permissions_as_keys, collection: permissions, wrapper: :with_block_label, include_blank: false, label_method: ->(privilege) { safe_join([t("admin.roles.privileges.#{privilege}"), content_tag(:span, t("admin.roles.privileges.#{privilege}_description"), class: 'hint')]) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', label: false, hint: false, disabled: permissions.filter { |privilege| UserRole::FLAGS[privilege] & current_user.role.computed_permissions == 0 } + = form.input :permissions_as_keys, collection: permissions, wrapper: :with_block_label, include_blank: false, label_method: ->(privilege) { privilege_label(privilege) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', label: false, hint: false, disabled: disable_permissions?(permissions) %hr.spacer/ From 9b47c5d53c24cd5bd9ee84169f4f05bb81f3ed88 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:02:59 -0500 Subject: [PATCH 04/41] Extract helper methods for labels from filters/_filter_fields (#27574) --- app/helpers/filters_helper.rb | 12 ++++++++++++ app/views/filters/_filter_fields.html.haml | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 app/helpers/filters_helper.rb diff --git a/app/helpers/filters_helper.rb b/app/helpers/filters_helper.rb new file mode 100644 index 00000000000000..22a1c172de2c86 --- /dev/null +++ b/app/helpers/filters_helper.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module FiltersHelper + def filter_action_label(action) + safe_join( + [ + t("simple_form.labels.filters.actions.#{action}"), + content_tag(:span, t("simple_form.hints.filters.actions.#{action}"), class: 'hint'), + ] + ) + end +end diff --git a/app/views/filters/_filter_fields.html.haml b/app/views/filters/_filter_fields.html.haml index 0690e8dd597cc7..a3260816ed9c0c 100644 --- a/app/views/filters/_filter_fields.html.haml +++ b/app/views/filters/_filter_fields.html.haml @@ -10,7 +10,7 @@ %hr.spacer/ .fields-group - = f.input :filter_action, as: :radio_buttons, collection: %i(warn hide), include_blank: false, wrapper: :with_block_label, label_method: ->(action) { safe_join([t("simple_form.labels.filters.actions.#{action}"), content_tag(:span, t("simple_form.hints.filters.actions.#{action}"), class: 'hint')]) }, hint: t('simple_form.hints.filters.action'), required: true + = f.input :filter_action, as: :radio_buttons, collection: %i(warn hide), include_blank: false, wrapper: :with_block_label, label_method: ->(action) { filter_action_label(action) }, hint: t('simple_form.hints.filters.action'), required: true %hr.spacer/ From 72b7cd349ccffb557d2c55f4ba76b525ff47ef9e Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:06:19 -0500 Subject: [PATCH 05/41] Extract helper methods for form label in admin/ area views (#27575) --- app/helpers/admin/account_actions_helper.rb | 12 ++++++++++++ app/helpers/admin/accounts_helper.rb | 19 +++++++++++++++++++ app/helpers/admin/ip_blocks_helper.rb | 12 ++++++++++++ .../admin/settings/discovery_helper.rb | 15 +++++++++++++++ app/views/admin/account_actions/new.html.haml | 2 +- app/views/admin/accounts/index.html.haml | 2 +- app/views/admin/ip_blocks/new.html.haml | 2 +- .../admin/settings/discovery/show.html.haml | 2 +- 8 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 app/helpers/admin/account_actions_helper.rb create mode 100644 app/helpers/admin/accounts_helper.rb create mode 100644 app/helpers/admin/ip_blocks_helper.rb create mode 100644 app/helpers/admin/settings/discovery_helper.rb diff --git a/app/helpers/admin/account_actions_helper.rb b/app/helpers/admin/account_actions_helper.rb new file mode 100644 index 00000000000000..e132680a688a53 --- /dev/null +++ b/app/helpers/admin/account_actions_helper.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Admin::AccountActionsHelper + def account_action_type_label(type) + safe_join( + [ + I18n.t("simple_form.labels.admin_account_action.types.#{type}"), + content_tag(:span, I18n.t("simple_form.hints.admin_account_action.types.#{type}"), class: 'hint'), + ] + ) + end +end diff --git a/app/helpers/admin/accounts_helper.rb b/app/helpers/admin/accounts_helper.rb new file mode 100644 index 00000000000000..a936797e888074 --- /dev/null +++ b/app/helpers/admin/accounts_helper.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Admin::AccountsHelper + def admin_accounts_moderation_options + [ + [t('admin.accounts.moderation.active'), 'active'], + [t('admin.accounts.moderation.silenced'), 'silenced'], + [t('admin.accounts.moderation.disabled'), 'disabled'], + [t('admin.accounts.moderation.suspended'), 'suspended'], + [safe_join([t('admin.accounts.moderation.pending'), "(#{pending_user_count_label})"], ' '), 'pending'], + ] + end + + private + + def pending_user_count_label + number_with_delimiter User.pending.count + end +end diff --git a/app/helpers/admin/ip_blocks_helper.rb b/app/helpers/admin/ip_blocks_helper.rb new file mode 100644 index 00000000000000..4aae3aae7abe51 --- /dev/null +++ b/app/helpers/admin/ip_blocks_helper.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Admin::IpBlocksHelper + def ip_blocks_severity_label(severity) + safe_join( + [ + I18n.t("simple_form.labels.ip_block.severities.#{severity}"), + content_tag(:span, I18n.t("simple_form.hints.ip_block.severities.#{severity}"), class: 'hint'), + ] + ) + end +end diff --git a/app/helpers/admin/settings/discovery_helper.rb b/app/helpers/admin/settings/discovery_helper.rb new file mode 100644 index 00000000000000..0aa4d4368f30bf --- /dev/null +++ b/app/helpers/admin/settings/discovery_helper.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Admin::Settings::DiscoveryHelper + def discovery_warning_hint_text + authorized_fetch_overridden? ? t('admin.settings.security.authorized_fetch_overridden_hint') : nil + end + + def discovery_hint_text + t('admin.settings.security.authorized_fetch_hint') + end + + def discovery_recommended_value + authorized_fetch_overridden? ? :overridden : nil + end +end diff --git a/app/views/admin/account_actions/new.html.haml b/app/views/admin/account_actions/new.html.haml index 2a0cae15a0338e..4cb4401c70542d 100644 --- a/app/views/admin/account_actions/new.html.haml +++ b/app/views/admin/account_actions/new.html.haml @@ -5,7 +5,7 @@ = f.input :report_id, as: :hidden .fields-group - = f.input :type, as: :radio_buttons, collection: Admin::AccountAction.types_for_account(@account), include_blank: false, wrapper: :with_block_label, label_method: ->(type) { safe_join([I18n.t("simple_form.labels.admin_account_action.types.#{type}"), content_tag(:span, I18n.t("simple_form.hints.admin_account_action.types.#{type}"), class: 'hint')]) }, hint: t('simple_form.hints.admin_account_action.type_html', acct: @account.pretty_acct) + = f.input :type, as: :radio_buttons, collection: Admin::AccountAction.types_for_account(@account), include_blank: false, wrapper: :with_block_label, label_method: ->(type) { account_action_type_label(type) }, hint: t('simple_form.hints.admin_account_action.type_html', acct: @account.pretty_acct) - if @account.local? %hr.spacer/ diff --git a/app/views/admin/accounts/index.html.haml b/app/views/admin/accounts/index.html.haml index 9cec8d6325c87a..8354441895deb8 100644 --- a/app/views/admin/accounts/index.html.haml +++ b/app/views/admin/accounts/index.html.haml @@ -10,7 +10,7 @@ .filter-subset.filter-subset--with-select %strong= t('admin.accounts.moderation.title') .input.select.optional - = select_tag :status, options_for_select([[t('admin.accounts.moderation.active'), 'active'], [t('admin.accounts.moderation.silenced'), 'silenced'], [t('admin.accounts.moderation.disabled'), 'disabled'], [t('admin.accounts.moderation.suspended'), 'suspended'], [safe_join([t('admin.accounts.moderation.pending'), "(#{number_with_delimiter(User.pending.count)})"], ' '), 'pending']], params[:status]), prompt: I18n.t('generic.all') + = select_tag :status, options_for_select(admin_accounts_moderation_options, params[:status]), prompt: I18n.t('generic.all') .filter-subset.filter-subset--with-select %strong= t('admin.accounts.role') .input.select.optional diff --git a/app/views/admin/ip_blocks/new.html.haml b/app/views/admin/ip_blocks/new.html.haml index 405c73c90e72a6..ecaf04315bc674 100644 --- a/app/views/admin/ip_blocks/new.html.haml +++ b/app/views/admin/ip_blocks/new.html.haml @@ -11,7 +11,7 @@ = f.input :expires_in, wrapper: :with_block_label, collection: [1.day, 2.weeks, 1.month, 6.months, 1.year, 3.years].map(&:to_i), label_method: ->(i) { I18n.t("admin.ip_blocks.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt') .fields-group - = f.input :severity, as: :radio_buttons, collection: IpBlock.severities.keys, include_blank: false, wrapper: :with_block_label, label_method: ->(severity) { safe_join([I18n.t("simple_form.labels.ip_block.severities.#{severity}"), content_tag(:span, I18n.t("simple_form.hints.ip_block.severities.#{severity}"), class: 'hint')]) } + = f.input :severity, as: :radio_buttons, collection: IpBlock.severities.keys, include_blank: false, wrapper: :with_block_label, label_method: ->(severity) { ip_blocks_severity_label(severity) } .fields-group = f.input :comment, as: :string, wrapper: :with_block_label diff --git a/app/views/admin/settings/discovery/show.html.haml b/app/views/admin/settings/discovery/show.html.haml index 62011d5c567110..59fc3226ac0713 100644 --- a/app/views/admin/settings/discovery/show.html.haml +++ b/app/views/admin/settings/discovery/show.html.haml @@ -42,7 +42,7 @@ %h4= t('admin.settings.security.federation_authentication') .fields-group - = f.input :authorized_fetch, as: :boolean, wrapper: :with_label, label: t('admin.settings.security.authorized_fetch'), warning_hint: authorized_fetch_overridden? ? t('admin.settings.security.authorized_fetch_overridden_hint') : nil, hint: t('admin.settings.security.authorized_fetch_hint'), disabled: authorized_fetch_overridden?, recommended: authorized_fetch_overridden? ? :overridden : nil + = f.input :authorized_fetch, as: :boolean, wrapper: :with_label, label: t('admin.settings.security.authorized_fetch'), warning_hint: discovery_warning_hint_text, hint: discovery_hint_text, disabled: authorized_fetch_overridden?, recommended: discovery_recommended_value %h4= t('admin.settings.discovery.follow_recommendations') From 31bef99b9edf8ad52182f9dcc5012d3c799b9fe4 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:08:55 -0500 Subject: [PATCH 06/41] Move lib/mastodon/premailer_webpack_strategy to lib/ (#27636) --- .rubocop_todo.yml | 2 +- config/initializers/premailer_rails.rb | 2 +- lib/{mastodon => }/premailer_webpack_strategy.rb | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename lib/{mastodon => }/premailer_webpack_strategy.rb (100%) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 1672046048708b..a79f88f971a54a 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -307,7 +307,7 @@ Style/FetchEnvVar: - 'config/initializers/devise.rb' - 'config/initializers/paperclip.rb' - 'config/initializers/vapid.rb' - - 'lib/mastodon/premailer_webpack_strategy.rb' + - 'lib/premailer_webpack_strategy.rb' - 'lib/mastodon/redis_config.rb' - 'lib/tasks/repo.rake' - 'spec/features/profile_spec.rb' diff --git a/config/initializers/premailer_rails.rb b/config/initializers/premailer_rails.rb index 98b2082719cf91..52576ef883264b 100644 --- a/config/initializers/premailer_rails.rb +++ b/config/initializers/premailer_rails.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative '../../lib/mastodon/premailer_webpack_strategy' +require_relative '../../lib/premailer_webpack_strategy' Premailer::Rails.config.merge!(remove_ids: true, adapter: :nokogiri, diff --git a/lib/mastodon/premailer_webpack_strategy.rb b/lib/premailer_webpack_strategy.rb similarity index 100% rename from lib/mastodon/premailer_webpack_strategy.rb rename to lib/premailer_webpack_strategy.rb From a1636fce7f2eb630b6c8d0a4524b1687b61e3496 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:10:21 -0500 Subject: [PATCH 07/41] Move lib/devise/* to lib/devise/strategies/* (#27638) --- .rubocop_todo.yml | 8 ++++---- config/application.rb | 4 ++-- .../{ => strategies}/two_factor_ldap_authenticatable.rb | 0 .../{ => strategies}/two_factor_pam_authenticatable.rb | 0 4 files changed, 6 insertions(+), 6 deletions(-) rename lib/devise/{ => strategies}/two_factor_ldap_authenticatable.rb (100%) rename lib/devise/{ => strategies}/two_factor_pam_authenticatable.rb (100%) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index a79f88f971a54a..43af4f670aeac8 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -357,8 +357,8 @@ Style/GuardClause: - 'config/initializers/devise.rb' - 'db/migrate/20170901141119_truncate_preview_cards.rb' - 'db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb' - - 'lib/devise/two_factor_ldap_authenticatable.rb' - - 'lib/devise/two_factor_pam_authenticatable.rb' + - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb' + - 'lib/devise/strategies/two_factor_pam_authenticatable.rb' - 'lib/mastodon/cli/accounts.rb' - 'lib/mastodon/cli/maintenance.rb' - 'lib/mastodon/cli/media.rb' @@ -493,8 +493,8 @@ Style/SafeNavigation: # SupportedStyles: only_raise, only_fail, semantic Style/SignalException: Exclude: - - 'lib/devise/two_factor_ldap_authenticatable.rb' - - 'lib/devise/two_factor_pam_authenticatable.rb' + - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb' + - 'lib/devise/strategies/two_factor_pam_authenticatable.rb' # This cop supports unsafe autocorrection (--autocorrect-all). Style/SingleArgumentDig: diff --git a/config/application.rb b/config/application.rb index 387827784a5a6c..99ee4ffd76a06a 100644 --- a/config/application.rb +++ b/config/application.rb @@ -39,8 +39,8 @@ require_relative '../lib/mastodon/version' require_relative '../lib/mastodon/rack_middleware' require_relative '../lib/public_file_server_middleware' -require_relative '../lib/devise/two_factor_ldap_authenticatable' -require_relative '../lib/devise/two_factor_pam_authenticatable' +require_relative '../lib/devise/strategies/two_factor_ldap_authenticatable' +require_relative '../lib/devise/strategies/two_factor_pam_authenticatable' require_relative '../lib/chewy/settings_extensions' require_relative '../lib/chewy/index_extensions' require_relative '../lib/chewy/strategy/mastodon' diff --git a/lib/devise/two_factor_ldap_authenticatable.rb b/lib/devise/strategies/two_factor_ldap_authenticatable.rb similarity index 100% rename from lib/devise/two_factor_ldap_authenticatable.rb rename to lib/devise/strategies/two_factor_ldap_authenticatable.rb diff --git a/lib/devise/two_factor_pam_authenticatable.rb b/lib/devise/strategies/two_factor_pam_authenticatable.rb similarity index 100% rename from lib/devise/two_factor_pam_authenticatable.rb rename to lib/devise/strategies/two_factor_pam_authenticatable.rb From 291dc04e67f963313958a23de7ba935fa7130996 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:38:05 -0500 Subject: [PATCH 08/41] Remove un-needed `action` and `template` options to `render` in controllers (#28022) --- .../admin/account_moderation_notes_controller.rb | 2 +- app/controllers/admin/relays_controller.rb | 2 +- app/controllers/admin/report_notes_controller.rb | 2 +- app/controllers/concerns/challengable_concern.rb | 2 +- app/controllers/disputes/appeals_controller.rb | 2 +- app/controllers/filters_controller.rb | 4 ++-- app/controllers/statuses_cleanup_controller.rb | 2 +- spec/controllers/concerns/challengable_concern_spec.rb | 6 +++--- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/controllers/admin/account_moderation_notes_controller.rb b/app/controllers/admin/account_moderation_notes_controller.rb index 4f36f33f47e0fe..8b6c1a4454ebd0 100644 --- a/app/controllers/admin/account_moderation_notes_controller.rb +++ b/app/controllers/admin/account_moderation_notes_controller.rb @@ -16,7 +16,7 @@ def create @moderation_notes = @account.targeted_moderation_notes.latest @warnings = @account.strikes.custom.latest - render template: 'admin/accounts/show' + render 'admin/accounts/show' end end diff --git a/app/controllers/admin/relays_controller.rb b/app/controllers/admin/relays_controller.rb index c1297c8b991bb1..c893802159b753 100644 --- a/app/controllers/admin/relays_controller.rb +++ b/app/controllers/admin/relays_controller.rb @@ -24,7 +24,7 @@ def create @relay.enable! redirect_to admin_relays_path else - render action: :new + render :new end end diff --git a/app/controllers/admin/report_notes_controller.rb b/app/controllers/admin/report_notes_controller.rb index 3fd815b60a0b58..b5f04a1caa0998 100644 --- a/app/controllers/admin/report_notes_controller.rb +++ b/app/controllers/admin/report_notes_controller.rb @@ -26,7 +26,7 @@ def create @form = Admin::StatusBatchAction.new @statuses = @report.statuses.with_includes - render template: 'admin/reports/show' + render 'admin/reports/show' end end diff --git a/app/controllers/concerns/challengable_concern.rb b/app/controllers/concerns/challengable_concern.rb index 2995a25e096296..09874fb4054435 100644 --- a/app/controllers/concerns/challengable_concern.rb +++ b/app/controllers/concerns/challengable_concern.rb @@ -43,7 +43,7 @@ def require_challenge! def render_challenge @body_classes = 'lighter' - render template: 'auth/challenges/new', layout: 'auth' + render 'auth/challenges/new', layout: 'auth' end def challenge_passed? diff --git a/app/controllers/disputes/appeals_controller.rb b/app/controllers/disputes/appeals_controller.rb index eefd92b5a83c70..98b58d2117449d 100644 --- a/app/controllers/disputes/appeals_controller.rb +++ b/app/controllers/disputes/appeals_controller.rb @@ -11,7 +11,7 @@ def create redirect_to disputes_strike_path(@strike), notice: I18n.t('disputes.strikes.appealed_msg') rescue ActiveRecord::RecordInvalid => e @appeal = e.record - render template: 'disputes/strikes/show' + render 'disputes/strikes/show' end private diff --git a/app/controllers/filters_controller.rb b/app/controllers/filters_controller.rb index bbe177ead18962..bd9964426b8064 100644 --- a/app/controllers/filters_controller.rb +++ b/app/controllers/filters_controller.rb @@ -25,7 +25,7 @@ def create if @filter.save redirect_to filters_path else - render action: :new + render :new end end @@ -33,7 +33,7 @@ def update if @filter.update(resource_params) redirect_to filters_path else - render action: :edit + render :edit end end diff --git a/app/controllers/statuses_cleanup_controller.rb b/app/controllers/statuses_cleanup_controller.rb index 19ae971ce482f5..4a3fc10ca4fbd5 100644 --- a/app/controllers/statuses_cleanup_controller.rb +++ b/app/controllers/statuses_cleanup_controller.rb @@ -14,7 +14,7 @@ def update if @policy.update(resource_params) redirect_to statuses_cleanup_path, notice: I18n.t('generic.changes_saved_msg') else - render action: :show + render :show end rescue ActionController::ParameterMissing # Do nothing diff --git a/spec/controllers/concerns/challengable_concern_spec.rb b/spec/controllers/concerns/challengable_concern_spec.rb index 3324bdd24fcd07..169e2122f8e253 100644 --- a/spec/controllers/concerns/challengable_concern_spec.rb +++ b/spec/controllers/concerns/challengable_concern_spec.rb @@ -85,7 +85,7 @@ def bar before { get :foo } it 'renders challenge' do - expect(response).to render_template('auth/challenges/new') + expect(response).to render_template('auth/challenges/new', layout: :auth) end # See Auth::ChallengesControllerSpec @@ -95,7 +95,7 @@ def bar before { post :bar } it 'renders challenge' do - expect(response).to render_template('auth/challenges/new') + expect(response).to render_template('auth/challenges/new', layout: :auth) end it 'accepts correct password' do @@ -106,7 +106,7 @@ def bar it 'rejects wrong password' do post :bar, params: { form_challenge: { current_password: 'dddfff888123' } } - expect(response.body).to render_template('auth/challenges/new') + expect(response.body).to render_template('auth/challenges/new', layout: :auth) expect(session[:challenge_passed_at]).to be_nil end end From e48ecd29294ec2790fd38fd1a35b8490d1350c4e Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:39:59 -0500 Subject: [PATCH 09/41] Remove `default_scope` from `Admin::ActionLog` (#28026) --- app/controllers/admin/action_logs_controller.rb | 2 +- app/models/admin/action_log.rb | 4 ++-- app/models/admin/action_log_filter.rb | 12 ++++++++---- app/models/report.rb | 10 +++++----- ...on_log_fabricator.rb => action_log_fabricator.rb} | 2 +- spec/models/report_spec.rb | 6 +++--- 6 files changed, 20 insertions(+), 16 deletions(-) rename spec/fabricators/{admin_action_log_fabricator.rb => action_log_fabricator.rb} (68%) diff --git a/app/controllers/admin/action_logs_controller.rb b/app/controllers/admin/action_logs_controller.rb index 42edec15a39de5..37a00ad225a5f8 100644 --- a/app/controllers/admin/action_logs_controller.rb +++ b/app/controllers/admin/action_logs_controller.rb @@ -6,7 +6,7 @@ class ActionLogsController < BaseController def index authorize :audit_log, :index? - @auditable_accounts = Account.where(id: Admin::ActionLog.reorder(nil).select('distinct account_id')).select(:id, :username) + @auditable_accounts = Account.where(id: Admin::ActionLog.select('distinct account_id')).select(:id, :username) end private diff --git a/app/models/admin/action_log.rb b/app/models/admin/action_log.rb index f2c121d7580333..49ae679809fc63 100644 --- a/app/models/admin/action_log.rb +++ b/app/models/admin/action_log.rb @@ -24,12 +24,12 @@ class Admin::ActionLog < ApplicationRecord belongs_to :account belongs_to :target, polymorphic: true, optional: true - default_scope -> { order('id desc') } - before_validation :set_human_identifier before_validation :set_route_param before_validation :set_permalink + scope :latest, -> { order(id: :desc) } + def action super.to_sym end diff --git a/app/models/admin/action_log_filter.rb b/app/models/admin/action_log_filter.rb index 0117974628b7b7..d413cb386d4ed9 100644 --- a/app/models/admin/action_log_filter.rb +++ b/app/models/admin/action_log_filter.rb @@ -72,7 +72,7 @@ def initialize(params) end def results - scope = Admin::ActionLog.includes(:target) + scope = latest_action_logs.includes(:target) params.each do |key, value| next if key.to_s == 'page' @@ -88,14 +88,18 @@ def results def scope_for(key, value) case key when 'action_type' - Admin::ActionLog.where(ACTION_TYPE_MAP[value.to_sym]) + latest_action_logs.where(ACTION_TYPE_MAP[value.to_sym]) when 'account_id' - Admin::ActionLog.where(account_id: value) + latest_action_logs.where(account_id: value) when 'target_account_id' account = Account.find_or_initialize_by(id: value) - Admin::ActionLog.where(target: [account, account.user].compact) + latest_action_logs.where(target: [account, account.user].compact) else raise Mastodon::InvalidParameterError, "Unknown filter: #{key}" end end + + def latest_action_logs + Admin::ActionLog.latest + end end diff --git a/app/models/report.rb b/app/models/report.rb index 81ad721df12644..c565362cc64adf 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -131,25 +131,25 @@ def history Admin::ActionLog.where( target_type: 'Report', target_id: id - ).unscope(:order).arel, + ).arel, Admin::ActionLog.where( target_type: 'Account', target_id: target_account_id - ).unscope(:order).arel, + ).arel, Admin::ActionLog.where( target_type: 'Status', target_id: status_ids - ).unscope(:order).arel, + ).arel, Admin::ActionLog.where( target_type: 'AccountWarning', target_id: AccountWarning.where(report_id: id).select(:id) - ).unscope(:order).arel, + ).arel, ].reduce { |union, query| Arel::Nodes::UnionAll.new(union, query) } - Admin::ActionLog.from(Arel::Nodes::As.new(subquery, Admin::ActionLog.arel_table)) + Admin::ActionLog.latest.from(Arel::Nodes::As.new(subquery, Admin::ActionLog.arel_table)) end private diff --git a/spec/fabricators/admin_action_log_fabricator.rb b/spec/fabricators/action_log_fabricator.rb similarity index 68% rename from spec/fabricators/admin_action_log_fabricator.rb rename to spec/fabricators/action_log_fabricator.rb index 3acedbffd392f7..ce52cb73a0380b 100644 --- a/spec/fabricators/admin_action_log_fabricator.rb +++ b/spec/fabricators/action_log_fabricator.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -Fabricator('Admin::ActionLog') do +Fabricator(:action_log, from: Admin::ActionLog) do account { Fabricate.build(:account) } action 'MyString' target nil diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb index 0093dcd8de9496..c514c63b39226f 100644 --- a/spec/models/report_spec.rb +++ b/spec/models/report_spec.rb @@ -110,9 +110,9 @@ let(:status) { Fabricate(:status) } before do - Fabricate('Admin::ActionLog', target_type: 'Report', account_id: target_account.id, target_id: report.id, created_at: 2.days.ago) - Fabricate('Admin::ActionLog', target_type: 'Account', account_id: target_account.id, target_id: report.target_account_id, created_at: 2.days.ago) - Fabricate('Admin::ActionLog', target_type: 'Status', account_id: target_account.id, target_id: status.id, created_at: 2.days.ago) + Fabricate(:action_log, target_type: 'Report', account_id: target_account.id, target_id: report.id, created_at: 2.days.ago) + Fabricate(:action_log, target_type: 'Account', account_id: target_account.id, target_id: report.target_account_id, created_at: 2.days.ago) + Fabricate(:action_log, target_type: 'Status', account_id: target_account.id, target_id: status.id, created_at: 2.days.ago) end it 'returns right logs' do From 6e55ff964325694c9a06914e59733babfc4854c7 Mon Sep 17 00:00:00 2001 From: Filippo Giunchedi Date: Thu, 30 Nov 2023 11:46:06 +0100 Subject: [PATCH 10/41] Change Vagrant to install Node 20 (#28100) Co-authored-by: Filippo Giunchedi --- Vagrantfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index e2c66a476edc3a..6f0f5110952aed 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -10,7 +10,11 @@ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main' # Add repo for NodeJS -curl -sL https://deb.nodesource.com/setup_16.x | sudo bash - +sudo mkdir -p /etc/apt/keyrings +curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +NODE_MAJOR=20 +echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list +sudo apt-get update # Add firewall rule to redirect 80 to PORT and save sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]} From b696ca6b1a0fee1e56fcf70f4c561ff2661ad81d Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 05:48:46 -0500 Subject: [PATCH 11/41] Move self destruct CLI command definition code to module (#28131) --- lib/mastodon/cli/federation.rb | 74 ++++++++++++++++++++++++++++++++++ lib/mastodon/cli/main.rb | 62 +--------------------------- 2 files changed, 76 insertions(+), 60 deletions(-) create mode 100644 lib/mastodon/cli/federation.rb diff --git a/lib/mastodon/cli/federation.rb b/lib/mastodon/cli/federation.rb new file mode 100644 index 00000000000000..1b4cb467a571bb --- /dev/null +++ b/lib/mastodon/cli/federation.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'tty-prompt' + +module Mastodon::CLI + module Federation + extend ActiveSupport::Concern + + included do + desc 'self-destruct', 'Erase the server from the federation' + long_desc <<~LONG_DESC + Erase the server from the federation by broadcasting account delete + activities to all known other servers. This allows a "clean exit" from + running a Mastodon server, as it leaves next to no cache behind on + other servers. + + This command is always interactive and requires confirmation twice. + + No local data is actually deleted, because emptying the + database or removing files is much faster through other, external + means, such as e.g. deleting the entire VPS. However, because other + servers will delete data about local users, but no local data will be + updated (such as e.g. followers), there will be a state mismatch + that will lead to glitches and issues if you then continue to run and use + the server. + + So either you know exactly what you are doing, or you are starting + from a blank slate afterwards by manually clearing out all the local + data! + LONG_DESC + def self_destruct + if SelfDestructHelper.self_destruct? + prompt.ok('Self-destruct mode is already enabled for this Mastodon server') + + pending_accounts = Account.local.without_suspended.count + Account.local.suspended.joins(:deletion_request).count + sidekiq_stats = Sidekiq::Stats.new + + if pending_accounts.positive? + prompt.warn("#{pending_accounts} accounts are still pending deletion.") + elsif sidekiq_stats.enqueued.positive? + prompt.warn('Deletion notices are still being processed') + elsif sidekiq_stats.retry_size.positive? + prompt.warn('At least one delivery attempt for each deletion notice has been made, but some have failed and are scheduled for retry') + else + prompt.ok('Every deletion notice has been sent! You can safely delete all data and decomission your servers!') + end + + exit(0) + end + + exit(1) unless prompt.ask('Type in the domain of the server to confirm:', required: true) == Rails.configuration.x.local_domain + + prompt.warn('This operation WILL NOT be reversible.') + prompt.warn('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.') + prompt.warn('The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process).') + + exit(1) if prompt.no?('Are you sure you want to proceed?') + + self_destruct_value = Rails.application.message_verifier('self-destruct').generate(Rails.configuration.x.local_domain) + prompt.ok('To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes:') + prompt.ok(" SELF_DESTRUCT=#{self_destruct_value}") + prompt.ok("\nYou can re-run this command to see the state of the self-destruct process.") + rescue TTY::Reader::InputInterrupt + exit(1) + end + + private + + def prompt + @prompt ||= TTY::Prompt.new + end + end + end +end diff --git a/lib/mastodon/cli/main.rb b/lib/mastodon/cli/main.rb index 64f1646f491091..ef40b81f33959c 100644 --- a/lib/mastodon/cli/main.rb +++ b/lib/mastodon/cli/main.rb @@ -8,6 +8,7 @@ require_relative 'domains' require_relative 'email_domain_blocks' require_relative 'emoji' +require_relative 'federation' require_relative 'feeds' require_relative 'ip_blocks' require_relative 'maintenance' @@ -65,66 +66,7 @@ class Main < Base desc 'maintenance SUBCOMMAND ...ARGS', 'Various maintenance utilities' subcommand 'maintenance', Maintenance - desc 'self-destruct', 'Erase the server from the federation' - long_desc <<~LONG_DESC - Erase the server from the federation by broadcasting account delete - activities to all known other servers. This allows a "clean exit" from - running a Mastodon server, as it leaves next to no cache behind on - other servers. - - This command is always interactive and requires confirmation twice. - - No local data is actually deleted, because emptying the - database or removing files is much faster through other, external - means, such as e.g. deleting the entire VPS. However, because other - servers will delete data about local users, but no local data will be - updated (such as e.g. followers), there will be a state mismatch - that will lead to glitches and issues if you then continue to run and use - the server. - - So either you know exactly what you are doing, or you are starting - from a blank slate afterwards by manually clearing out all the local - data! - LONG_DESC - def self_destruct - require 'tty-prompt' - - prompt = TTY::Prompt.new - - if SelfDestructHelper.self_destruct? - prompt.ok('Self-destruct mode is already enabled for this Mastodon server') - - pending_accounts = Account.local.without_suspended.count + Account.local.suspended.joins(:deletion_request).count - sidekiq_stats = Sidekiq::Stats.new - - if pending_accounts.positive? - prompt.warn("#{pending_accounts} accounts are still pending deletion.") - elsif sidekiq_stats.enqueued.positive? - prompt.warn('Deletion notices are still being processed') - elsif sidekiq_stats.retry_size.positive? - prompt.warn('At least one delivery attempt for each deletion notice has been made, but some have failed and are scheduled for retry') - else - prompt.ok('Every deletion notice has been sent! You can safely delete all data and decomission your servers!') - end - - exit(0) - end - - exit(1) unless prompt.ask('Type in the domain of the server to confirm:', required: true) == Rails.configuration.x.local_domain - - prompt.warn('This operation WILL NOT be reversible.') - prompt.warn('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.') - prompt.warn('The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process).') - - exit(1) if prompt.no?('Are you sure you want to proceed?') - - self_destruct_value = Rails.application.message_verifier('self-destruct').generate(Rails.configuration.x.local_domain) - prompt.ok('To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes:') - prompt.ok(" SELF_DESTRUCT=#{self_destruct_value}") - prompt.ok("\nYou can re-run this command to see the state of the self-destruct process.") - rescue TTY::Reader::InputInterrupt - exit(1) - end + include Federation map %w(--version -v) => :version From c761cc4738c74519c65a99c5ab24874584605d2d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 11:53:49 +0100 Subject: [PATCH 12/41] fix(deps): update babel monorepo to v7.23.5 (#28122) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 260 +++++++++++++++++++++++++++--------------------------- 1 file changed, 130 insertions(+), 130 deletions(-) diff --git a/yarn.lock b/yarn.lock index 11c2724d59c911..69464dfa2f28cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -42,55 +42,55 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13": - version: 7.22.13 - resolution: "@babel/code-frame@npm:7.22.13" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/code-frame@npm:7.23.5" dependencies: - "@babel/highlight": "npm:^7.22.13" + "@babel/highlight": "npm:^7.23.4" chalk: "npm:^2.4.2" - checksum: f4cc8ae1000265677daf4845083b72f88d00d311adb1a93c94eb4b07bf0ed6828a81ae4ac43ee7d476775000b93a28a9cddec18fbdc5796212d8dcccd5de72bd + checksum: a10e843595ddd9f97faa99917414813c06214f4d9205294013e20c70fbdf4f943760da37dec1d998bf3e6fc20fa2918a47c0e987a7e458663feb7698063ad7c6 languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/compat-data@npm:7.23.3" - checksum: c6af331753c34ee8a5678bc94404320826cb56b1dda3efc1311ec8fb0774e78225132f3c1acc988440ace667f14a838e297a822692b95758aa63da406e1f97a1 +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/compat-data@npm:7.23.5" + checksum: 081278ed46131a890ad566a59c61600a5f9557bd8ee5e535890c8548192532ea92590742fd74bd9db83d74c669ef8a04a7e1c85cdea27f960233e3b83c3a957c languageName: node linkType: hard "@babel/core@npm:^7.10.4, @babel/core@npm:^7.11.1, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.22.1": - version: 7.23.3 - resolution: "@babel/core@npm:7.23.3" + version: 7.23.5 + resolution: "@babel/core@npm:7.23.5" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.3" + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.5" "@babel/helper-compilation-targets": "npm:^7.22.15" "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.23.2" - "@babel/parser": "npm:^7.23.3" + "@babel/helpers": "npm:^7.23.5" + "@babel/parser": "npm:^7.23.5" "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.3" - "@babel/types": "npm:^7.23.3" + "@babel/traverse": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 08d43b749e24052d12713a7fb1f0c0d1275d4fb056d00846faeb8da79ecf6d0ba91a11b6afec407b8b0f9388d00e2c2f485f282bef0ade4d6d0a17de191a4287 + checksum: 311a512a870ee330a3f9a7ea89e5df790b2b5af0b1bd98b10b4edc0de2ac440f0df4d69ea2c0ee38a4b89041b9a495802741d93603be7d4fd834ec8bb6970bd2 languageName: node linkType: hard -"@babel/generator@npm:^7.23.3, @babel/generator@npm:^7.7.2": - version: 7.23.3 - resolution: "@babel/generator@npm:7.23.3" +"@babel/generator@npm:^7.23.5, @babel/generator@npm:^7.7.2": + version: 7.23.5 + resolution: "@babel/generator@npm:7.23.5" dependencies: - "@babel/types": "npm:^7.23.3" + "@babel/types": "npm:^7.23.5" "@jridgewell/gen-mapping": "npm:^0.3.2" "@jridgewell/trace-mapping": "npm:^0.3.17" jsesc: "npm:^2.5.1" - checksum: d5fff1417eecfada040e01a7c77a4968e81c436aeb35815ce85b4e80cd01e731423613d61033044a6cb5563bb8449ee260e3379b63eb50b38ec0a9ea9c00abfd + checksum: 14c6e874f796c4368e919bed6003bb0adc3ce837760b08f9e646d20aeb5ae7d309723ce6e4f06bcb4a2b5753145446c8e4425851380f695e40e71e1760f49e7b languageName: node linkType: hard @@ -310,10 +310,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-string-parser@npm:7.22.5" - checksum: 6b0ff8af724377ec41e5587fffa7605198da74cb8e7d8d48a36826df0c0ba210eb9fedb3d9bef4d541156e0bd11040f021945a6cbb731ccec4aefb4affa17aa4 +"@babel/helper-string-parser@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/helper-string-parser@npm:7.23.4" + checksum: f348d5637ad70b6b54b026d6544bd9040f78d24e7ec245a0fc42293968181f6ae9879c22d89744730d246ce8ec53588f716f102addd4df8bbc79b73ea10004ac languageName: node linkType: hard @@ -324,10 +324,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-validator-option@npm:7.22.15" - checksum: e9661bf80ba18e2dd978217b350fb07298e57ac417f4f1ab9fa011505e20e4857f2c3b4b538473516a9dc03af5ce3a831e5ed973311c28326f4c330b6be981c2 +"@babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helper-validator-option@npm:7.23.5" + checksum: af45d5c0defb292ba6fd38979e8f13d7da63f9623d8ab9ededc394f67eb45857d2601278d151ae9affb6e03d5d608485806cd45af08b4468a0515cf506510e94 languageName: node linkType: hard @@ -342,34 +342,34 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.2": - version: 7.23.2 - resolution: "@babel/helpers@npm:7.23.2" +"@babel/helpers@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helpers@npm:7.23.5" dependencies: "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.2" - "@babel/types": "npm:^7.23.0" - checksum: 3a6a939c5277a27486e7c626812f0643b35d1c053ac2eb66911f5ae6c0a4e4bcdd40750eba36b766b0ee8a753484287f50ae56232a5f8f2947116723e44b9e35 + "@babel/traverse": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" + checksum: a37e2728eb4378a4888e5d614e28de7dd79b55ac8acbecd0e5c761273e2a02a8f33b34b1932d9069db55417ace2937cbf8ec37c42f1030ce6d228857d7ccaa4f languageName: node linkType: hard -"@babel/highlight@npm:^7.22.13": - version: 7.22.20 - resolution: "@babel/highlight@npm:7.22.20" +"@babel/highlight@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/highlight@npm:7.23.4" dependencies: "@babel/helper-validator-identifier": "npm:^7.22.20" chalk: "npm:^2.4.2" js-tokens: "npm:^4.0.0" - checksum: f3c3a193afad23434297d88e81d1d6c0c2cf02423de2139ada7ce0a7fc62d8559abf4cc996533c1a9beca7fc990010eb8d544097f75e818ac113bf39ed810aa2 + checksum: fbff9fcb2f5539289c3c097d130e852afd10d89a3a08ac0b5ebebbc055cc84a4bcc3dcfed463d488cde12dd0902ef1858279e31d7349b2e8cee43913744bda33 languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/parser@npm:7.23.3" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/parser@npm:7.23.5" bin: parser: ./bin/babel-parser.js - checksum: 0fe11eadd4146a9155305b5bfece0f8223a3b1b97357ffa163c0156940de92e76cd0e7a173de819b8692767147e62f33389b312d1537f84cede51092672df6ef + checksum: 3356aa90d7bafb4e2c7310e7c2c3d443c4be4db74913f088d3d577a1eb914ea4188e05fd50a47ce907a27b755c4400c4e3cbeee73dbeb37761f6ca85954f5a20 languageName: node linkType: hard @@ -661,9 +661,9 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.3" +"@babel/plugin-transform-async-generator-functions@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.4" dependencies: "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-plugin-utils": "npm:^7.22.5" @@ -671,7 +671,7 @@ __metadata: "@babel/plugin-syntax-async-generators": "npm:^7.8.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e846f282658e097fce4fccf3ee29289bf05f0654846a5994727a36f0cdc2e47abdffd4be4fa65787e94aa975824fae894c90afbfdc8caacd46c12c7f43e99d7f + checksum: f2eef4de609975a3f7da7832576b5ffc93e43c80f87e1a99e886b0f8591096cfc4c37e2d5f52fdeaa2a9c09a25a59f3e621159abaca75d3193922a5c0e4cbe0c languageName: node linkType: hard @@ -699,14 +699,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-block-scoping@npm:7.23.3" +"@babel/plugin-transform-block-scoping@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-block-scoping@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ccaeded7954c196811d22a35322579254cda52676e823682b6234885a3aaf88fe0d5152dacaec43db9031dcf35a050a5343e36028e5905b0ba9c02d36b30a57f + checksum: 83006804dddf980ab1bcd6d67bc381e24b58c776507c34f990468f820d0da71dba3697355ca4856532fa2eeb2a1e3e73c780f03760b5507a511cbedb0308e276 languageName: node linkType: hard @@ -722,22 +722,22 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-class-static-block@npm:7.23.3" +"@babel/plugin-transform-class-static-block@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-class-static-block@npm:7.23.4" dependencies: "@babel/helper-create-class-features-plugin": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.12.0 - checksum: 89cdb66d7bc834cd51659eb7286a6bee23add0bc114943d68c4b6c0c834178cf0d55183df0cf508fec9c55ed4155641360e6f55a91c16fe826ccaf1adf381922 + checksum: fdca96640ef29d8641a7f8de106f65f18871b38cc01c0f7b696d2b49c76b77816b30a812c08e759d06dd10b4d9b3af6b5e4ac22a2017a88c4077972224b77ab0 languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-classes@npm:7.23.3" +"@babel/plugin-transform-classes@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/plugin-transform-classes@npm:7.23.5" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" "@babel/helper-compilation-targets": "npm:^7.22.15" @@ -750,7 +750,7 @@ __metadata: globals: "npm:^11.1.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 88bfd332db0ba5cbfb8557a2ba5a7185151aebc9cfe3035b014aa6d795556acbe672bb8c78da3c9fd1d23f55a333d14b5daa127ef037f5ced5198b6d79a146d6 + checksum: 07988f52b4893151887d1ea6ff79e5fe834078c5731bd09babd5659edbbae21ea4e2de326a02443a63fd776b4c945da6177f07875b56fe66e0b7899e830a9e92 languageName: node linkType: hard @@ -800,15 +800,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-dynamic-import@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-dynamic-import@npm:7.23.3" +"@babel/plugin-transform-dynamic-import@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: df3fd130312dc53d068fa76333991dce5e86987b023af8c3b502bd7d36a8e67da6f718e61dc838576a9fbacd06628e29607ee22d9bae30705485c14130eab201 + checksum: 19ae4a4a2ca86d35224734c41c48b2aa6a13139f3cfa1cbd18c0e65e461de8b65687dec7e52b7a72bb49db04465394c776aa1b13a2af5dc975b2a0cde3dcab67 languageName: node linkType: hard @@ -824,15 +824,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-export-namespace-from@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-export-namespace-from@npm:7.23.3" +"@babel/plugin-transform-export-namespace-from@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-export-namespace-from": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 390c6626dcda99023629049d92090242b4575351a4a7b47f97febabd2381f2cd0f624de661d8de8d1f715fedd63753cfd1feddead19e5960c27b88e447465b81 + checksum: 38bf04f851e36240bbe83ace4169da626524f4107bfb91f05b4ad93a5fb6a36d5b3d30b8883c1ba575ccfc1bac7938e90ca2e3cb227f7b3f4a9424beec6fd4a7 languageName: node linkType: hard @@ -860,15 +860,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-json-strings@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-json-strings@npm:7.23.3" +"@babel/plugin-transform-json-strings@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-json-strings@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-json-strings": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e1cef6a485b9da32aba9449fb459dac062dfc401f3d6ad48e7fbdcb73bbe470c995cc15ce5c421b95efe1e9a90d5507eb606360fe10b6d8cb869dd5dae7a2562 + checksum: 39e82223992a9ad857722ae051291935403852ad24b0dd64c645ca1c10517b6bf9822377d88643fed8b3e61a4e3f7e5ae41cf90eb07c40a786505d47d5970e54 languageName: node linkType: hard @@ -883,15 +883,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-logical-assignment-operators@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.23.3" +"@babel/plugin-transform-logical-assignment-operators@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 23b7588b26d420c8b132bd08916d49871ca0c8db892f6b58637b10e2a0d918163d413c505db880a9157fc2e61d089040f139298a60d837ccbd0efca0474ac7ca + checksum: 87b034dd13143904e405887e6125d76c27902563486efc66b7d9a9d8f9406b76c6ac42d7b37224014af5783d7edb465db0cdecd659fa3227baad0b3a6a35deff languageName: node linkType: hard @@ -980,7 +980,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.3, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.23.3": +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.3, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.23.4": version: 7.23.4 resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.23.4" dependencies: @@ -992,21 +992,21 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-numeric-separator@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-numeric-separator@npm:7.23.3" +"@babel/plugin-transform-numeric-separator@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d3748cce20e8752e61dfda55e275c699459a3ff8d0bb46585da813136e04066b1ce70b71beef504fcdc8d4cca3c955112cea96d5e9fd5a42a5bc8956d05236c2 + checksum: e34902da4f5588dc4812c92cb1f6a5e3e3647baf7b4623e30942f551bf1297621abec4e322ebfa50b320c987c0f34d9eb4355b3d289961d9035e2126e3119c12 languageName: node linkType: hard -"@babel/plugin-transform-object-rest-spread@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.23.3" +"@babel/plugin-transform-object-rest-spread@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.23.4" dependencies: "@babel/compat-data": "npm:^7.23.3" "@babel/helper-compilation-targets": "npm:^7.22.15" @@ -1015,7 +1015,7 @@ __metadata: "@babel/plugin-transform-parameters": "npm:^7.23.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 31ab631aaba945c118662943e5f1f54a21f07d64f06e06b25d55871168c460f3eeeccdf7b05aa74a1340e2cfbe781ad3c7ceccd0c2585d39f7b73ba11ebaa9d0 + checksum: b56017992ffe7fcd1dd9a9da67c39995a141820316266bcf7d77dc912980d228ccbd3f36191d234f5cc389b09157b5d2a955e33e8fb368319534affd1c72b262 languageName: node linkType: hard @@ -1031,28 +1031,28 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-optional-catch-binding@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.23.3" +"@babel/plugin-transform-optional-catch-binding@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 85ac1e94ee8f21648816151628ff931cc16143ec8c904649a1ecfd8960160290eccc5a197b4ae3ee7a1c7a27a7c4189e61b4de24483d5bad4040784afe2d206f + checksum: 4ef61812af0e4928485e28301226ce61139a8b8cea9e9a919215ebec4891b9fea2eb7a83dc3090e2679b7d7b2c8653da601fbc297d2addc54a908b315173991e languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.3" +"@babel/plugin-transform-optional-chaining@npm:^7.23.3, @babel/plugin-transform-optional-chaining@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 2b358962169d871392aa292a67527e5335909438da0ddbb0d19e7838c0f8a2081cc751a49e6e534ac4d6c932254531a205ac22b197f64fc4c89f41bf9f595497 + checksum: 305b773c29ad61255b0e83ec1e92b2f7af6aa58be4cba1e3852bddaa14f7d2afd7b4438f41c28b179d6faac7eb8d4fb5530a17920294f25d459b8f84406bfbfb languageName: node linkType: hard @@ -1079,9 +1079,9 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-private-property-in-object@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-private-property-in-object@npm:7.23.3" +"@babel/plugin-transform-private-property-in-object@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.23.4" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" "@babel/helper-create-class-features-plugin": "npm:^7.22.15" @@ -1089,7 +1089,7 @@ __metadata: "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9211dd25a6e87a01535f2d97a663fa6de3472b963c8dcfaacce229a2e3fa6500f2e9fc690bc100a540fc7b66c8364faf7ef19b32e9c9b9791e4561b742c15ed3 + checksum: 8d31b28f24204b4d13514cd3a8f3033abf575b1a6039759ddd6e1d82dd33ba7281f9bc85c9f38072a665d69bfa26dc40737eefaf9d397b024654a483d2357bf5 languageName: node linkType: hard @@ -1333,13 +1333,13 @@ __metadata: linkType: hard "@babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.22.4": - version: 7.23.3 - resolution: "@babel/preset-env@npm:7.23.3" + version: 7.23.5 + resolution: "@babel/preset-env@npm:7.23.5" dependencies: - "@babel/compat-data": "npm:^7.23.3" + "@babel/compat-data": "npm:^7.23.5" "@babel/helper-compilation-targets": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-validator-option": "npm:^7.22.15" + "@babel/helper-validator-option": "npm:^7.23.5" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.23.3" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.23.3" "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.23.3" @@ -1363,25 +1363,25 @@ __metadata: "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" "@babel/plugin-transform-arrow-functions": "npm:^7.23.3" - "@babel/plugin-transform-async-generator-functions": "npm:^7.23.3" + "@babel/plugin-transform-async-generator-functions": "npm:^7.23.4" "@babel/plugin-transform-async-to-generator": "npm:^7.23.3" "@babel/plugin-transform-block-scoped-functions": "npm:^7.23.3" - "@babel/plugin-transform-block-scoping": "npm:^7.23.3" + "@babel/plugin-transform-block-scoping": "npm:^7.23.4" "@babel/plugin-transform-class-properties": "npm:^7.23.3" - "@babel/plugin-transform-class-static-block": "npm:^7.23.3" - "@babel/plugin-transform-classes": "npm:^7.23.3" + "@babel/plugin-transform-class-static-block": "npm:^7.23.4" + "@babel/plugin-transform-classes": "npm:^7.23.5" "@babel/plugin-transform-computed-properties": "npm:^7.23.3" "@babel/plugin-transform-destructuring": "npm:^7.23.3" "@babel/plugin-transform-dotall-regex": "npm:^7.23.3" "@babel/plugin-transform-duplicate-keys": "npm:^7.23.3" - "@babel/plugin-transform-dynamic-import": "npm:^7.23.3" + "@babel/plugin-transform-dynamic-import": "npm:^7.23.4" "@babel/plugin-transform-exponentiation-operator": "npm:^7.23.3" - "@babel/plugin-transform-export-namespace-from": "npm:^7.23.3" + "@babel/plugin-transform-export-namespace-from": "npm:^7.23.4" "@babel/plugin-transform-for-of": "npm:^7.23.3" "@babel/plugin-transform-function-name": "npm:^7.23.3" - "@babel/plugin-transform-json-strings": "npm:^7.23.3" + "@babel/plugin-transform-json-strings": "npm:^7.23.4" "@babel/plugin-transform-literals": "npm:^7.23.3" - "@babel/plugin-transform-logical-assignment-operators": "npm:^7.23.3" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.23.4" "@babel/plugin-transform-member-expression-literals": "npm:^7.23.3" "@babel/plugin-transform-modules-amd": "npm:^7.23.3" "@babel/plugin-transform-modules-commonjs": "npm:^7.23.3" @@ -1389,15 +1389,15 @@ __metadata: "@babel/plugin-transform-modules-umd": "npm:^7.23.3" "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.22.5" "@babel/plugin-transform-new-target": "npm:^7.23.3" - "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.23.3" - "@babel/plugin-transform-numeric-separator": "npm:^7.23.3" - "@babel/plugin-transform-object-rest-spread": "npm:^7.23.3" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.23.4" + "@babel/plugin-transform-numeric-separator": "npm:^7.23.4" + "@babel/plugin-transform-object-rest-spread": "npm:^7.23.4" "@babel/plugin-transform-object-super": "npm:^7.23.3" - "@babel/plugin-transform-optional-catch-binding": "npm:^7.23.3" - "@babel/plugin-transform-optional-chaining": "npm:^7.23.3" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.23.4" + "@babel/plugin-transform-optional-chaining": "npm:^7.23.4" "@babel/plugin-transform-parameters": "npm:^7.23.3" "@babel/plugin-transform-private-methods": "npm:^7.23.3" - "@babel/plugin-transform-private-property-in-object": "npm:^7.23.3" + "@babel/plugin-transform-private-property-in-object": "npm:^7.23.4" "@babel/plugin-transform-property-literals": "npm:^7.23.3" "@babel/plugin-transform-regenerator": "npm:^7.23.3" "@babel/plugin-transform-reserved-words": "npm:^7.23.3" @@ -1418,7 +1418,7 @@ __metadata: semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 36b02a86817ab5474bb74a8d62a110723b0b05904a52ddc5627cf89457525b8d5ac0739b8e435a6ae12ef8b90cd5fc191169898c3dc2ac9d2c84026b02f2580a + checksum: 2a0e1274dec045186e131c6433659b75492583290e8d41633c616f6bff829cb2e4b2f9a57f556283a54db3bd6aa697911e56a36f607911a29b731c445a5b5a06 languageName: node linkType: hard @@ -1502,32 +1502,32 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/traverse@npm:7.23.3" +"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/traverse@npm:7.23.5" dependencies: - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.3" + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.5" "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-function-name": "npm:^7.23.0" "@babel/helper-hoist-variables": "npm:^7.22.5" "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.3" - "@babel/types": "npm:^7.23.3" + "@babel/parser": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" debug: "npm:^4.1.0" globals: "npm:^11.1.0" - checksum: 3c2784f4765185126d64fd5eebce0413b7aee6d54f779998594a343a7f973a9693a441ba27533df84e7ab7ce22f1239c6837f35e903132a1b25f7fc7a67bc30f + checksum: c5ea793080ca6719b0a1612198fd25e361cee1f3c14142d7a518d2a1eeb5c1d21f7eec1b26c20ea6e1ddd8ed12ab50b960ff95ffd25be353b6b46e1b54d6f825 languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.23.3 - resolution: "@babel/types@npm:7.23.3" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.23.5 + resolution: "@babel/types@npm:7.23.5" dependencies: - "@babel/helper-string-parser": "npm:^7.22.5" + "@babel/helper-string-parser": "npm:^7.23.4" "@babel/helper-validator-identifier": "npm:^7.22.20" to-fast-properties: "npm:^2.0.0" - checksum: 371a10dd9c8d8ebf48fc5d9e1b327dafd74453f8ea582dcbddd1cee5ae34e8881b743e783a86c08c04dcd1849b1842455472a911ae8a1c185484fe9b7b5f1595 + checksum: 7dd5e2f59828ed046ad0b06b039df2524a8b728d204affb4fc08da2502b9dd3140b1356b5166515d229dc811539a8b70dcd4bc507e06d62a89f4091a38d0b0fb languageName: node linkType: hard From e6fd9a59e6f7a37fcd1276c75aadfddd79c784ca Mon Sep 17 00:00:00 2001 From: Filippo Giunchedi Date: Thu, 30 Nov 2023 11:58:40 +0100 Subject: [PATCH 13/41] Fix FamiliarFollowersController test response comparison (#28121) Co-authored-by: Filippo Giunchedi --- .../api/v1/accounts/familiar_followers_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb b/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb index 22617730945e57..3c7c7e8b84c297 100644 --- a/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb @@ -28,7 +28,7 @@ account_ids = [account_a, account_b, account_b, account_a, account_a].map { |a| a.id.to_s } get :index, params: { id: account_ids } - expect(body_as_json.pluck(:id)).to eq [account_a.id.to_s, account_b.id.to_s] + expect(body_as_json.pluck(:id)).to contain_exactly(account_a.id.to_s, account_b.id.to_s) end end end From ce78a9c9ac3e579d9de1c410d005860a80774a3c Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 06:44:42 -0500 Subject: [PATCH 14/41] Clean up `two_factor_authentication/confirmations` controller spec (#28128) --- .../confirmations_controller_spec.rb | 122 +++++++++--------- 1 file changed, 62 insertions(+), 60 deletions(-) diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb index a5a35e91d05cdf..1b3b0cb0aeebaa 100644 --- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb @@ -20,37 +20,30 @@ [true, false].each do |with_otp_secret| let(:user) { Fabricate(:user, email: 'local-part@domain', otp_secret: with_otp_secret ? 'oldotpsecret' : nil) } - describe 'GET #new' do - context 'when signed in and a new otp secret has been set in the session' do - subject do - sign_in user, scope: :user - get :new, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } - end + context 'when signed in' do + before { sign_in user, scope: :user } - include_examples 'renders :new' - end + describe 'GET #new' do + context 'when a new otp secret has been set in the session' do + subject do + get :new, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + end - it 'redirects if not signed in' do - get :new - expect(response).to redirect_to('/auth/sign_in') - end + include_examples 'renders :new' + end - it 'redirects if a new otp_secret has not been set in the session' do - sign_in user, scope: :user - get :new, session: { challenge_passed_at: Time.now.utc } - expect(response).to redirect_to('/settings/otp_authentication') - end - end + it 'redirects if a new otp_secret has not been set in the session' do + get :new, session: { challenge_passed_at: Time.now.utc } - describe 'POST #create' do - context 'when signed in' do - before do - sign_in user, scope: :user + expect(response).to redirect_to('/settings/otp_authentication') end + end + describe 'POST #create' do describe 'when form_two_factor_confirmation parameter is not provided' do it 'raises ActionController::ParameterMissing' do post :create, params: {}, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + expect(response).to have_http_status(400) end end @@ -58,69 +51,78 @@ describe 'when creation succeeds' do let!(:otp_backup_codes) { user.generate_otp_backup_codes! } - it 'renders page with success' do + before do prepare_user_otp_generation - prepare_user_otp_consumption + prepare_user_otp_consumption_response(true) allow(controller).to receive(:current_user).and_return(user) + end - expect do - post :create, - params: { form_two_factor_confirmation: { otp_attempt: '123456' } }, - session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } - end.to change { user.reload.otp_secret }.to 'thisisasecretforthespecofnewview' + it 'renders page with success' do + expect { post_create_with_options } + .to change { user.reload.otp_secret }.to 'thisisasecretforthespecofnewview' expect(assigns(:recovery_codes)).to eq otp_backup_codes expect(flash[:notice]).to eq 'Two-factor authentication successfully enabled' expect(response).to have_http_status(200) expect(response).to render_template('settings/two_factor_authentication/recovery_codes/index') end - - def prepare_user_otp_generation - allow(user) - .to receive(:generate_otp_backup_codes!) - .and_return(otp_backup_codes) - end - - def prepare_user_otp_consumption - options = { otp_secret: 'thisisasecretforthespecofnewview' } - allow(user) - .to receive(:validate_and_consume_otp!) - .with('123456', options) - .and_return(true) - end end describe 'when creation fails' do subject do - options = { otp_secret: 'thisisasecretforthespecofnewview' } - allow(user) - .to receive(:validate_and_consume_otp!) - .with('123456', options) - .and_return(false) - allow(controller).to receive(:current_user).and_return(user) + expect { post_create_with_options } + .to(not_change { user.reload.otp_secret }) + end - expect do - post :create, - params: { form_two_factor_confirmation: { otp_attempt: '123456' } }, - session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } - end.to(not_change { user.reload.otp_secret }) + before do + prepare_user_otp_consumption_response(false) + allow(controller).to receive(:current_user).and_return(user) end - it 'renders the new view' do + it 'renders page with error message' do subject expect(response.body).to include 'The entered code was invalid! Are server time and device time correct?' end include_examples 'renders :new' end - end - context 'when not signed in' do - it 'redirects if not signed in' do - post :create, params: { form_two_factor_confirmation: { otp_attempt: '123456' } } - expect(response).to redirect_to('/auth/sign_in') + private + + def post_create_with_options + post :create, + params: { form_two_factor_confirmation: { otp_attempt: '123456' } }, + session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + end + + def prepare_user_otp_generation + allow(user) + .to receive(:generate_otp_backup_codes!) + .and_return(otp_backup_codes) + end + + def prepare_user_otp_consumption_response(result) + options = { otp_secret: 'thisisasecretforthespecofnewview' } + allow(user) + .to receive(:validate_and_consume_otp!) + .with('123456', options) + .and_return(result) end end end end + + context 'when not signed in' do + it 'redirects on POST to create' do + post :create, params: { form_two_factor_confirmation: { otp_attempt: '123456' } } + + expect(response).to redirect_to('/auth/sign_in') + end + + it 'redirects on GET to new' do + get :new + + expect(response).to redirect_to('/auth/sign_in') + end + end end From 7faa27e17de515b8718075d89a00942c06c0ef48 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 30 Nov 2023 12:45:54 +0100 Subject: [PATCH 15/41] Change dismissed banners to be stored server-side (#27055) --- .../components/dismissable_banner.tsx | 25 ++++++++++++++++--- app/javascript/mastodon/reducers/settings.js | 9 +++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/app/javascript/mastodon/components/dismissable_banner.tsx b/app/javascript/mastodon/components/dismissable_banner.tsx index 4feb74a3a19ca6..4e6d3bb9a76730 100644 --- a/app/javascript/mastodon/components/dismissable_banner.tsx +++ b/app/javascript/mastodon/components/dismissable_banner.tsx @@ -1,11 +1,18 @@ +/* eslint-disable @typescript-eslint/no-unsafe-call, + @typescript-eslint/no-unsafe-return, + @typescript-eslint/no-unsafe-assignment, + @typescript-eslint/no-unsafe-member-access + -- the settings store is not yet typed */ import type { PropsWithChildren } from 'react'; -import { useCallback, useState } from 'react'; +import { useCallback, useState, useEffect } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg'; +import { changeSetting } from 'mastodon/actions/settings'; import { bannerSettings } from 'mastodon/settings'; +import { useAppSelector, useAppDispatch } from 'mastodon/store'; import { IconButton } from './icon_button'; @@ -21,13 +28,25 @@ export const DismissableBanner: React.FC> = ({ id, children, }) => { - const [visible, setVisible] = useState(!bannerSettings.get(id)); + const dismissed = useAppSelector((state) => + state.settings.getIn(['dismissed_banners', id], false), + ); + const dispatch = useAppDispatch(); + + const [visible, setVisible] = useState(!bannerSettings.get(id) && !dismissed); const intl = useIntl(); const handleDismiss = useCallback(() => { setVisible(false); bannerSettings.set(id, true); - }, [id]); + dispatch(changeSetting(['dismissed_banners', id], true)); + }, [id, dispatch]); + + useEffect(() => { + if (!visible && !dismissed) { + dispatch(changeSetting(['dismissed_banners', id], true)); + } + }, [id, dispatch, visible, dismissed]); if (!visible) { return null; diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js index 07d1bda0f4d08b..a605ecbb8bd62d 100644 --- a/app/javascript/mastodon/reducers/settings.js +++ b/app/javascript/mastodon/reducers/settings.js @@ -100,6 +100,15 @@ const initialState = ImmutableMap({ body: '', }), }), + + dismissed_banners: ImmutableMap({ + 'public_timeline': false, + 'community_timeline': false, + 'home.explore_prompt': false, + 'explore/links': false, + 'explore/statuses': false, + 'explore/tags': false, + }), }); const defaultColumns = fromJS([ From 0212e0cfbfe4b50b5286165ec9887523f82513d1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:22:25 +0100 Subject: [PATCH 16/41] fix(deps): update dependency @babel/runtime to v7.23.5 (#28136) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 69464dfa2f28cd..580407f341c876 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1483,11 +1483,11 @@ __metadata: linkType: hard "@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.23.4 - resolution: "@babel/runtime@npm:7.23.4" + version: 7.23.5 + resolution: "@babel/runtime@npm:7.23.5" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: db2bf183cd0119599b903ca51ca0aeea8e0ab478a16be1aae10dd90473ed614159d3e5adfdd8f8f3d840402428ce0d90b5c01aae95da9e45a2dd83e02d85ca27 + checksum: ca679cc91bb7e424bc2db87bb58cc3b06ade916b9adb21fbbdc43e54cdaacb3eea201ceba2a0464b11d2eb65b9fe6a6ffcf4d7521fa52994f19be96f1af14788 languageName: node linkType: hard From 02a98210e891dff32b1cb958f799213ccfbbc29c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:22:40 +0100 Subject: [PATCH 17/41] fix(deps): update dependency jsdom to v23.0.1 (#28135) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 580407f341c876..ad792d26c5757e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10640,8 +10640,8 @@ __metadata: linkType: hard "jsdom@npm:^23.0.0": - version: 23.0.0 - resolution: "jsdom@npm:23.0.0" + version: 23.0.1 + resolution: "jsdom@npm:23.0.1" dependencies: cssstyle: "npm:^3.0.0" data-urls: "npm:^5.0.0" @@ -10665,11 +10665,11 @@ __metadata: ws: "npm:^8.14.2" xml-name-validator: "npm:^5.0.0" peerDependencies: - canvas: ^3.0.0 + canvas: ^2.11.2 peerDependenciesMeta: canvas: optional: true - checksum: 2c876a02de49e0ed6b667a4eb9b08b8e76ac189a5571ff97791cc9564e713259314deea6d657cc7f59fc30af41b900e7d833c95017e576dfcaf25f32565722af + checksum: 13b2b3693ccb40215d1cce77bac7a295414ee4c0a06e30167f8087c9867145ba23dbd592bd95a801cadd7b3698bfd20b9c3f2c26fd8422607f22609ed2e404ef languageName: node linkType: hard From bb0efe16e62636895079b3a968e444cd6e80b467 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 08:30:35 -0500 Subject: [PATCH 18/41] Remove `default_scope` from `MediaAttachment` class (#28043) --- app/controllers/accounts_controller.rb | 2 +- app/lib/account_statuses_filter.rb | 2 +- app/lib/vacuum/media_attachments_vacuum.rb | 4 ++-- app/models/admin/status_filter.rb | 2 +- app/models/media_attachment.rb | 7 +++---- app/services/backup_service.rb | 2 +- app/services/clear_domain_media_service.rb | 2 +- app/services/delete_account_service.rb | 2 +- app/services/suspend_account_service.rb | 2 +- app/services/unsuspend_account_service.rb | 2 +- .../activitypub/process_status_update_service_spec.rb | 2 +- 11 files changed, 14 insertions(+), 15 deletions(-) diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 850bf881ffa54d..4e475fe78263b1 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -50,7 +50,7 @@ def default_statuses end def only_media_scope - Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id) + Status.joins(:media_attachments).merge(@account.media_attachments).group(:id) end def no_replies_scope diff --git a/app/lib/account_statuses_filter.rb b/app/lib/account_statuses_filter.rb index b34ebb47773986..d1365de586e42b 100644 --- a/app/lib/account_statuses_filter.rb +++ b/app/lib/account_statuses_filter.rb @@ -70,7 +70,7 @@ def filtered_reblogs_scope end def only_media_scope - Status.joins(:media_attachments).merge(account.media_attachments.reorder(nil)).group(Status.arel_table[:id]) + Status.joins(:media_attachments).merge(account.media_attachments).group(Status.arel_table[:id]) end def no_replies_scope diff --git a/app/lib/vacuum/media_attachments_vacuum.rb b/app/lib/vacuum/media_attachments_vacuum.rb index 7b21c84bbce6e9..ab7ea4092faa39 100644 --- a/app/lib/vacuum/media_attachments_vacuum.rb +++ b/app/lib/vacuum/media_attachments_vacuum.rb @@ -27,11 +27,11 @@ def vacuum_orphaned_records! end def media_attachments_past_retention_period - MediaAttachment.unscoped.remote.cached.where(MediaAttachment.arel_table[:created_at].lt(@retention_period.ago)).where(MediaAttachment.arel_table[:updated_at].lt(@retention_period.ago)) + MediaAttachment.remote.cached.where(MediaAttachment.arel_table[:created_at].lt(@retention_period.ago)).where(MediaAttachment.arel_table[:updated_at].lt(@retention_period.ago)) end def orphaned_media_attachments - MediaAttachment.unscoped.unattached.where(MediaAttachment.arel_table[:created_at].lt(TTL.ago)) + MediaAttachment.unattached.where(MediaAttachment.arel_table[:created_at].lt(TTL.ago)) end def retention_period? diff --git a/app/models/admin/status_filter.rb b/app/models/admin/status_filter.rb index 645c2e62075535..4708785e7d4b74 100644 --- a/app/models/admin/status_filter.rb +++ b/app/models/admin/status_filter.rb @@ -32,7 +32,7 @@ def results def scope_for(key, _value) case key.to_s when 'media' - Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id).reorder('statuses.id desc') + Status.joins(:media_attachments).merge(@account.media_attachments).group(:id).reorder('statuses.id desc') else raise Mastodon::InvalidParameterError, "Unknown filter: #{key}" end diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index b567003fb9507e..1f40e5725ebc93 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -205,12 +205,11 @@ class MediaAttachment < ApplicationRecord validates :thumbnail, absence: true, if: -> { local? && !audio_or_video? } scope :attached, -> { where.not(status_id: nil).or(where.not(scheduled_status_id: nil)) } - scope :unattached, -> { where(status_id: nil, scheduled_status_id: nil) } + scope :cached, -> { remote.where.not(file_file_name: nil) } scope :local, -> { where(remote_url: '') } + scope :ordered, -> { order(id: :asc) } scope :remote, -> { where.not(remote_url: '') } - scope :cached, -> { remote.where.not(file_file_name: nil) } - - default_scope { order(id: :asc) } + scope :unattached, -> { where(status_id: nil, scheduled_status_id: nil) } attr_accessor :skip_download diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb index 3ef0366c3c5fc9..886bab1ebfe54d 100644 --- a/app/services/backup_service.rb +++ b/app/services/backup_service.rb @@ -72,7 +72,7 @@ def build_archive! end def dump_media_attachments!(zipfile) - MediaAttachment.attached.where(account: account).reorder(nil).find_in_batches do |media_attachments| + MediaAttachment.attached.where(account: account).find_in_batches do |media_attachments| media_attachments.each do |m| path = m.file&.path next unless path diff --git a/app/services/clear_domain_media_service.rb b/app/services/clear_domain_media_service.rb index 7bf2d62fb004e4..d3ad43e707105b 100644 --- a/app/services/clear_domain_media_service.rb +++ b/app/services/clear_domain_media_service.rb @@ -43,7 +43,7 @@ def blocked_domain_accounts end def media_from_blocked_domain - MediaAttachment.joins(:account).merge(blocked_domain_accounts).reorder(nil) + MediaAttachment.joins(:account).merge(blocked_domain_accounts) end def emojis_from_blocked_domains diff --git a/app/services/delete_account_service.rb b/app/services/delete_account_service.rb index 190a72e5c5f178..7c7cb97df2643c 100644 --- a/app/services/delete_account_service.rb +++ b/app/services/delete_account_service.rb @@ -165,7 +165,7 @@ def purge_mentions! end def purge_media_attachments! - @account.media_attachments.reorder(nil).find_each do |media_attachment| + @account.media_attachments.find_each do |media_attachment| next if keep_account_record? && reported_status_ids.include?(media_attachment.status_id) media_attachment.destroy diff --git a/app/services/suspend_account_service.rb b/app/services/suspend_account_service.rb index e79c2d3d81f51b..8d5446f1a88099 100644 --- a/app/services/suspend_account_service.rb +++ b/app/services/suspend_account_service.rb @@ -65,7 +65,7 @@ def unmerge_from_list_timelines! def privatize_media_attachments! attachment_names = MediaAttachment.attachment_definitions.keys - @account.media_attachments.reorder(nil).find_each do |media_attachment| + @account.media_attachments.find_each do |media_attachment| attachment_names.each do |attachment_name| attachment = media_attachment.public_send(attachment_name) styles = MediaAttachment::DEFAULT_STYLES | attachment.styles.keys diff --git a/app/services/unsuspend_account_service.rb b/app/services/unsuspend_account_service.rb index 93cd04a9438a6c..652dd6a84500da 100644 --- a/app/services/unsuspend_account_service.rb +++ b/app/services/unsuspend_account_service.rb @@ -61,7 +61,7 @@ def merge_into_list_timelines! def publish_media_attachments! attachment_names = MediaAttachment.attachment_definitions.keys - @account.media_attachments.reorder(nil).find_each do |media_attachment| + @account.media_attachments.find_each do |media_attachment| attachment_names.each do |attachment_name| attachment = media_attachment.public_send(attachment_name) styles = MediaAttachment::DEFAULT_STYLES | attachment.styles.keys diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb index 9d91f31cc5c2c5..53cbaf4cc1aaaa 100644 --- a/spec/services/activitypub/process_status_update_service_spec.rb +++ b/spec/services/activitypub/process_status_update_service_spec.rb @@ -384,7 +384,7 @@ def poll_option_json(name, votes) end it 'updates the existing media attachment in-place' do - media_attachment = status.media_attachments.reload.first + media_attachment = status.media_attachments.ordered.reload.first expect(media_attachment).to_not be_nil expect(media_attachment.remote_url).to eq 'https://example.com/foo.png' From 85662a5a57531af5402a6777d0b1089e78c56815 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 30 Nov 2023 14:47:01 +0100 Subject: [PATCH 19/41] Change `img-src` and `media-src` CSP directives to not include `https:` (#28025) --- app/lib/content_security_policy.rb | 4 ++-- config/initializers/content_security_policy.rb | 10 +++++----- spec/lib/content_security_policy_spec.rb | 14 +++++++------- spec/requests/content_security_policy_spec.rb | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/app/lib/content_security_policy.rb b/app/lib/content_security_policy.rb index e8fcf76a6564d7..966e41f03b3f34 100644 --- a/app/lib/content_security_policy.rb +++ b/app/lib/content_security_policy.rb @@ -9,8 +9,8 @@ def assets_host url_from_configured_asset_host || url_from_base_host end - def media_host - cdn_host_value || assets_host + def media_hosts + [assets_host, cdn_host_value].compact end private diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index 3fb80bac49ab72..a8b61e356f01ab 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -10,7 +10,7 @@ policy = ContentSecurityPolicy.new assets_host = policy.assets_host -media_host = policy.media_host +media_hosts = policy.media_hosts def sso_host return unless ENV['ONE_CLICK_SSO_LOGIN'] == 'true' @@ -35,9 +35,9 @@ def sso_host p.default_src :none p.frame_ancestors :none p.font_src :self, assets_host - p.img_src :self, :https, :data, :blob, assets_host + p.img_src :self, :data, :blob, *media_hosts p.style_src :self, assets_host - p.media_src :self, :https, :data, assets_host + p.media_src :self, :data, *media_hosts p.frame_src :self, :https p.manifest_src :self, assets_host @@ -54,10 +54,10 @@ def sso_host webpacker_public_host = ENV.fetch('WEBPACKER_DEV_SERVER_PUBLIC', Webpacker.config.dev_server[:public]) webpacker_urls = %w(ws http).map { |protocol| "#{protocol}#{Webpacker.dev_server.https? ? 's' : ''}://#{webpacker_public_host}" } - p.connect_src :self, :data, :blob, assets_host, media_host, Rails.configuration.x.streaming_api_base_url, *webpacker_urls + p.connect_src :self, :data, :blob, *media_hosts, Rails.configuration.x.streaming_api_base_url, *webpacker_urls p.script_src :self, :unsafe_inline, :unsafe_eval, assets_host else - p.connect_src :self, :data, :blob, assets_host, media_host, Rails.configuration.x.streaming_api_base_url + p.connect_src :self, :data, :blob, *media_hosts, Rails.configuration.x.streaming_api_base_url p.script_src :self, assets_host, "'wasm-unsafe-eval'" end end diff --git a/spec/lib/content_security_policy_spec.rb b/spec/lib/content_security_policy_spec.rb index 2e92f815acc897..4286f14980a682 100644 --- a/spec/lib/content_security_policy_spec.rb +++ b/spec/lib/content_security_policy_spec.rb @@ -59,10 +59,10 @@ end end - describe '#media_host' do + describe '#media_hosts' do context 'when there is no configured CDN' do it 'defaults to using the assets_host value' do - expect(subject.media_host).to eq(subject.assets_host) + expect(subject.media_hosts).to contain_exactly(subject.assets_host) end end @@ -74,7 +74,7 @@ end it 'uses the s3 alias host value' do - expect(subject.media_host).to eq 'https://asset-host.s3-alias.example' + expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://asset-host.s3-alias.example') end end @@ -86,7 +86,7 @@ end it 'uses the s3 alias host value and preserves the path' do - expect(subject.media_host).to eq 'https://asset-host.s3-alias.example/pathname/' + expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://asset-host.s3-alias.example/pathname/') end end @@ -98,7 +98,7 @@ end it 'uses the s3 cloudfront host value' do - expect(subject.media_host).to eq 'https://asset-host.s3-cloudfront.example' + expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://asset-host.s3-cloudfront.example') end end @@ -110,7 +110,7 @@ end it 'uses the azure alias host value' do - expect(subject.media_host).to eq 'https://asset-host.azure-alias.example' + expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://asset-host.azure-alias.example') end end @@ -122,7 +122,7 @@ end it 'uses the s3 hostname host value' do - expect(subject.media_host).to eq 'https://asset-host.s3.example' + expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://asset-host.s3.example') end end end diff --git a/spec/requests/content_security_policy_spec.rb b/spec/requests/content_security_policy_spec.rb index 7eb27d61d615ca..7610e698cdf4cd 100644 --- a/spec/requests/content_security_policy_spec.rb +++ b/spec/requests/content_security_policy_spec.rb @@ -12,15 +12,15 @@ "default-src 'none'", "frame-ancestors 'none'", "font-src 'self' https://cb6e6126.ngrok.io", - "img-src 'self' https: data: blob: https://cb6e6126.ngrok.io", + "img-src 'self' data: blob: https://cb6e6126.ngrok.io", "style-src 'self' https://cb6e6126.ngrok.io 'nonce-ZbA+JmE7+bK8F5qvADZHuQ=='", - "media-src 'self' https: data: https://cb6e6126.ngrok.io", + "media-src 'self' data: https://cb6e6126.ngrok.io", "frame-src 'self' https:", "manifest-src 'self' https://cb6e6126.ngrok.io", "form-action 'self'", "child-src 'self' blob: https://cb6e6126.ngrok.io", "worker-src 'self' blob: https://cb6e6126.ngrok.io", - "connect-src 'self' data: blob: https://cb6e6126.ngrok.io https://cb6e6126.ngrok.io ws://localhost:4000", + "connect-src 'self' data: blob: https://cb6e6126.ngrok.io ws://localhost:4000", "script-src 'self' https://cb6e6126.ngrok.io 'wasm-unsafe-eval'" ) end From b20af17a2c7dec49bc7ad1ec6706c5b02bf4f498 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 30 Nov 2023 14:47:07 +0100 Subject: [PATCH 20/41] Fix onboarding step descriptions being truncated on narrow screens (#28021) --- app/javascript/styles/mastodon/components.scss | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 9c3d9dc2c5202f..2106b529d6c639 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -2732,22 +2732,16 @@ $ui-header-height: 55px; &__description { flex: 1 1 auto; line-height: 20px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; h6 { color: $highlight-text-color; font-weight: 500; font-size: 14px; - overflow: hidden; - text-overflow: ellipsis; } p { color: $darker-text-color; overflow: hidden; - text-overflow: ellipsis; } } } From a8473f582d0d25ac0a2ad385cf3915e8012a3646 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 08:55:20 -0500 Subject: [PATCH 21/41] Add zeitwerk inflector for cli->CLI (#27635) --- config/initializers/inflections.rb | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 3d17509456c0fb..ba459e19f22c0d 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -13,21 +13,22 @@ # end ActiveSupport::Inflector.inflections(:en) do |inflect| - inflect.acronym 'StatsD' - inflect.acronym 'OEmbed' - inflect.acronym 'OStatus' inflect.acronym 'ActivityPub' - inflect.acronym 'PubSubHubbub' inflect.acronym 'ActivityStreams' - inflect.acronym 'JsonLd' - inflect.acronym 'Ed25519' - inflect.acronym 'TOC' - inflect.acronym 'RSS' - inflect.acronym 'REST' - inflect.acronym 'URL' inflect.acronym 'ASCII' + inflect.acronym 'CLI' inflect.acronym 'DeepL' inflect.acronym 'DSL' + inflect.acronym 'Ed25519' + inflect.acronym 'JsonLd' + inflect.acronym 'OEmbed' + inflect.acronym 'OStatus' + inflect.acronym 'PubSubHubbub' + inflect.acronym 'REST' + inflect.acronym 'RSS' + inflect.acronym 'StatsD' + inflect.acronym 'TOC' + inflect.acronym 'URL' inflect.singular 'data', 'data' end From e7c340a63475713d7f55b92fb8c963478f4d622a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 08:59:46 -0500 Subject: [PATCH 22/41] Spec coverage for missing `q` param and error conditions in `api/v2/search` controller (#27842) --- app/controllers/api/v2/search_controller.rb | 31 ++++++++++-- .../api/v2/search_controller_spec.rb | 48 +++++++++++++++++++ 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v2/search_controller.rb b/app/controllers/api/v2/search_controller.rb index 35be549305aaac..4339bee21e3aad 100644 --- a/app/controllers/api/v2/search_controller.rb +++ b/app/controllers/api/v2/search_controller.rb @@ -8,6 +8,11 @@ class Api::V2::SearchController < Api::BaseController before_action -> { authorize_if_got_token! :read, :'read:search' } before_action :validate_search_params! + with_options unless: :user_signed_in? do + before_action :query_pagination_error, if: :pagination_requested? + before_action :remote_resolve_error, if: :remote_resolve_requested? + end + def index @search = Search.new(search_results) render json: @search, serializer: REST::SearchSerializer @@ -21,12 +26,22 @@ def index def validate_search_params! params.require(:q) + end + + def query_pagination_error + render json: { error: 'Search queries pagination is not supported without authentication' }, status: 401 + end - return if user_signed_in? + def remote_resolve_error + render json: { error: 'Search queries that resolve remote resources are not supported without authentication' }, status: 401 + end - return render json: { error: 'Search queries pagination is not supported without authentication' }, status: 401 if params[:offset].present? + def remote_resolve_requested? + truthy_param?(:resolve) + end - render json: { error: 'Search queries that resolve remote resources are not supported without authentication' }, status: 401 if truthy_param?(:resolve) + def pagination_requested? + params[:offset].present? end def search_results @@ -34,7 +49,15 @@ def search_results params[:q], current_account, limit_param(RESULTS_LIMIT), - search_params.merge(resolve: truthy_param?(:resolve), exclude_unreviewed: truthy_param?(:exclude_unreviewed), following: truthy_param?(:following)) + combined_search_params + ) + end + + def combined_search_params + search_params.merge( + resolve: truthy_param?(:resolve), + exclude_unreviewed: truthy_param?(:exclude_unreviewed), + following: truthy_param?(:following) ) end diff --git a/spec/controllers/api/v2/search_controller_spec.rb b/spec/controllers/api/v2/search_controller_spec.rb index d3ff42d6a04f3b..a16716a10c4309 100644 --- a/spec/controllers/api/v2/search_controller_spec.rb +++ b/spec/controllers/api/v2/search_controller_spec.rb @@ -34,6 +34,26 @@ expect(body_as_json[:accounts].pluck(:id)).to contain_exactly(bob.id.to_s, ana.id.to_s, tom.id.to_s) end + context 'with truthy `resolve`' do + let(:params) { { q: 'test1', resolve: '1' } } + + it 'returns http unauthorized' do + get :index, params: params + + expect(response).to have_http_status(200) + end + end + + context 'with `offset`' do + let(:params) { { q: 'test1', offset: 1 } } + + it 'returns http unauthorized' do + get :index, params: params + + expect(response).to have_http_status(200) + end + end + context 'with following=true' do let(:params) { { q: 'test', type: 'accounts', following: 'true' } } @@ -48,6 +68,26 @@ end end end + + context 'when search raises syntax error' do + before { allow(Search).to receive(:new).and_raise(Mastodon::SyntaxError) } + + it 'returns http unprocessable_entity' do + get :index, params: params + + expect(response).to have_http_status(422) + end + end + + context 'when search raises not found error' do + before { allow(Search).to receive(:new).and_raise(ActiveRecord::RecordNotFound) } + + it 'returns http not_found' do + get :index, params: params + + expect(response).to have_http_status(404) + end + end end end @@ -59,6 +99,12 @@ get :index, params: search_params end + context 'without a `q` param' do + it 'returns http bad_request' do + expect(response).to have_http_status(400) + end + end + context 'with a `q` shorter than 5 characters' do let(:search_params) { { q: 'test' } } @@ -79,6 +125,7 @@ it 'returns http unauthorized' do expect(response).to have_http_status(401) + expect(response.body).to match('resolve remote resources') end end @@ -87,6 +134,7 @@ it 'returns http unauthorized' do expect(response).to have_http_status(401) + expect(response.body).to match('pagination is not supported') end end end From 0530ce5e9575c09464847412f43852f438b0494e Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 09:28:05 -0500 Subject: [PATCH 23/41] Convert accounts controller spec to request spec (#28126) --- .../accounts_spec.rb} | 158 +++++++++--------- 1 file changed, 80 insertions(+), 78 deletions(-) rename spec/{controllers/accounts_controller_spec.rb => requests/accounts_spec.rb} (56%) diff --git a/spec/controllers/accounts_controller_spec.rb b/spec/requests/accounts_spec.rb similarity index 56% rename from spec/controllers/accounts_controller_spec.rb rename to spec/requests/accounts_spec.rb index 542a748784adcd..bf067cdc38ac56 100644 --- a/spec/controllers/accounts_controller_spec.rb +++ b/spec/requests/accounts_spec.rb @@ -2,23 +2,22 @@ require 'rails_helper' -RSpec.describe AccountsController do - render_views - +describe 'Accounts show response' do let(:account) { Fabricate(:account) } - describe 'unapproved account check' do + context 'with an unapproved account' do before { account.user.update(approved: false) } it 'returns http not found' do %w(html json rss).each do |format| - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), as: format + expect(response).to have_http_status(404) end end end - describe 'permanently suspended account check' do + context 'with a permanently suspended account' do before do account.suspend! account.deletion_request.destroy @@ -26,25 +25,26 @@ it 'returns http gone' do %w(html json rss).each do |format| - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), as: format + expect(response).to have_http_status(410) end end end - describe 'temporarily suspended account check' do + context 'with a temporarily suspended account' do before { account.suspend! } it 'returns appropriate http response code' do { html: 403, json: 200, rss: 403 }.each do |format, code| - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), as: format expect(response).to have_http_status(code) end end end - describe 'GET #show' do + describe 'GET to short username paths' do context 'with existing statuses' do let!(:status) { Fabricate(:status, account: account) } let!(:status_reply) { Fabricate(:status, account: account, thread: Fabricate(:status)) } @@ -66,17 +66,17 @@ shared_examples 'common HTML response' do it 'returns a standard HTML response', :aggregate_failures do - expect(response).to have_http_status(200) + expect(response) + .to have_http_status(200) + .and render_template(:show) expect(response.headers['Link'].to_s).to include ActivityPub::TagManager.instance.uri_for(account) - - expect(response).to render_template(:show) end end context 'with a normal account in an HTML request' do before do - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), as: format end it_behaves_like 'common HTML response' @@ -84,8 +84,7 @@ context 'with replies' do before do - allow(controller).to receive(:replies_requested?).and_return(true) - get :show, params: { username: account.username, format: format } + get short_account_with_replies_path(username: account.username), as: format end it_behaves_like 'common HTML response' @@ -93,8 +92,7 @@ context 'with media' do before do - allow(controller).to receive(:media_requested?).and_return(true) - get :show, params: { username: account.username, format: format } + get short_account_media_path(username: account.username), as: format end it_behaves_like 'common HTML response' @@ -106,9 +104,8 @@ let!(:status_tag) { Fabricate(:status, account: account) } before do - allow(controller).to receive(:tag_requested?).and_return(true) status_tag.tags << tag - get :show, params: { username: account.username, format: format, tag: tag.to_param } + get short_account_tag_path(username: account.username, tag: tag), as: format end it_behaves_like 'common HTML response' @@ -117,21 +114,25 @@ context 'with JSON' do let(:authorized_fetch_mode) { false } - let(:format) { 'json' } + let(:headers) { { 'ACCEPT' => 'application/json' } } - before do - allow(controller).to receive(:authorized_fetch_mode?).and_return(authorized_fetch_mode) + around do |example| + ClimateControl.modify AUTHORIZED_FETCH: authorized_fetch_mode.to_s do + example.run + end end context 'with a normal account in a JSON request' do before do - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), headers: headers end it 'returns a JSON version of the account', :aggregate_failures do - expect(response).to have_http_status(200) - - expect(response.media_type).to eq 'application/activity+json' + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: eq('application/activity+json') + ) expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary) end @@ -152,13 +153,15 @@ before do sign_in(user) - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), headers: headers.merge({ 'Cookie' => '123' }) end it 'returns a private JSON version of the account', :aggregate_failures do - expect(response).to have_http_status(200) - - expect(response.media_type).to eq 'application/activity+json' + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: eq('application/activity+json') + ) expect(response.headers['Cache-Control']).to include 'private' @@ -170,14 +173,15 @@ let(:remote_account) { Fabricate(:account, domain: 'example.com') } before do - allow(controller).to receive(:signed_request_actor).and_return(remote_account) - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), headers: headers, sign_with: remote_account end it 'returns a JSON version of the account', :aggregate_failures do - expect(response).to have_http_status(200) - - expect(response.media_type).to eq 'application/activity+json' + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: eq('application/activity+json') + ) expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary) end @@ -188,12 +192,13 @@ let(:authorized_fetch_mode) { true } it 'returns a private signature JSON version of the account', :aggregate_failures do - expect(response).to have_http_status(200) - - expect(response.media_type).to eq 'application/activity+json' + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: eq('application/activity+json') + ) expect(response.headers['Cache-Control']).to include 'private' - expect(response.headers['Vary']).to include 'Signature' expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary) @@ -207,60 +212,58 @@ context 'with a normal account in an RSS request' do before do - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username, format: format) end it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie' it 'responds with correct statuses', :aggregate_failures do expect(response).to have_http_status(200) - expect(response.body).to include_status_tag(status_media) - expect(response.body).to include_status_tag(status_self_reply) - expect(response.body).to include_status_tag(status) - expect(response.body).to_not include_status_tag(status_direct) - expect(response.body).to_not include_status_tag(status_private) - expect(response.body).to_not include_status_tag(status_reblog.reblog) - expect(response.body).to_not include_status_tag(status_reply) + expect(response.body).to include(status_tag_for(status_media)) + expect(response.body).to include(status_tag_for(status_self_reply)) + expect(response.body).to include(status_tag_for(status)) + expect(response.body).to_not include(status_tag_for(status_direct)) + expect(response.body).to_not include(status_tag_for(status_private)) + expect(response.body).to_not include(status_tag_for(status_reblog.reblog)) + expect(response.body).to_not include(status_tag_for(status_reply)) end end context 'with replies' do before do - allow(controller).to receive(:replies_requested?).and_return(true) - get :show, params: { username: account.username, format: format } + get short_account_with_replies_path(username: account.username, format: format) end it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie' it 'responds with correct statuses with replies', :aggregate_failures do expect(response).to have_http_status(200) - expect(response.body).to include_status_tag(status_media) - expect(response.body).to include_status_tag(status_reply) - expect(response.body).to include_status_tag(status_self_reply) - expect(response.body).to include_status_tag(status) - expect(response.body).to_not include_status_tag(status_direct) - expect(response.body).to_not include_status_tag(status_private) - expect(response.body).to_not include_status_tag(status_reblog.reblog) + expect(response.body).to include(status_tag_for(status_media)) + expect(response.body).to include(status_tag_for(status_reply)) + expect(response.body).to include(status_tag_for(status_self_reply)) + expect(response.body).to include(status_tag_for(status)) + expect(response.body).to_not include(status_tag_for(status_direct)) + expect(response.body).to_not include(status_tag_for(status_private)) + expect(response.body).to_not include(status_tag_for(status_reblog.reblog)) end end context 'with media' do before do - allow(controller).to receive(:media_requested?).and_return(true) - get :show, params: { username: account.username, format: format } + get short_account_media_path(username: account.username, format: format) end it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie' it 'responds with correct statuses with media', :aggregate_failures do expect(response).to have_http_status(200) - expect(response.body).to include_status_tag(status_media) - expect(response.body).to_not include_status_tag(status_direct) - expect(response.body).to_not include_status_tag(status_private) - expect(response.body).to_not include_status_tag(status_reblog.reblog) - expect(response.body).to_not include_status_tag(status_reply) - expect(response.body).to_not include_status_tag(status_self_reply) - expect(response.body).to_not include_status_tag(status) + expect(response.body).to include(status_tag_for(status_media)) + expect(response.body).to_not include(status_tag_for(status_direct)) + expect(response.body).to_not include(status_tag_for(status_private)) + expect(response.body).to_not include(status_tag_for(status_reblog.reblog)) + expect(response.body).to_not include(status_tag_for(status_reply)) + expect(response.body).to_not include(status_tag_for(status_self_reply)) + expect(response.body).to_not include(status_tag_for(status)) end end @@ -270,30 +273,29 @@ let!(:status_tag) { Fabricate(:status, account: account) } before do - allow(controller).to receive(:tag_requested?).and_return(true) status_tag.tags << tag - get :show, params: { username: account.username, format: format, tag: tag.to_param } + get short_account_tag_path(username: account.username, tag: tag, format: format) end it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie' it 'responds with correct statuses with a tag', :aggregate_failures do expect(response).to have_http_status(200) - expect(response.body).to include_status_tag(status_tag) - expect(response.body).to_not include_status_tag(status_direct) - expect(response.body).to_not include_status_tag(status_media) - expect(response.body).to_not include_status_tag(status_private) - expect(response.body).to_not include_status_tag(status_reblog.reblog) - expect(response.body).to_not include_status_tag(status_reply) - expect(response.body).to_not include_status_tag(status_self_reply) - expect(response.body).to_not include_status_tag(status) + expect(response.body).to include(status_tag_for(status_tag)) + expect(response.body).to_not include(status_tag_for(status_direct)) + expect(response.body).to_not include(status_tag_for(status_media)) + expect(response.body).to_not include(status_tag_for(status_private)) + expect(response.body).to_not include(status_tag_for(status_reblog.reblog)) + expect(response.body).to_not include(status_tag_for(status_reply)) + expect(response.body).to_not include(status_tag_for(status_self_reply)) + expect(response.body).to_not include(status_tag_for(status)) end end end end end - def include_status_tag(status) - include ActivityPub::TagManager.instance.url_for(status) + def status_tag_for(status) + ActivityPub::TagManager.instance.url_for(status) end end From 1f1c75bba56f4b22c5f4c745b8f50a002001213c Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 09:39:41 -0500 Subject: [PATCH 24/41] File cleanup/organization in `controllers/concerns` (#27846) --- app/controllers/admin/export_domain_allows_controller.rb | 2 +- app/controllers/admin/export_domain_blocks_controller.rb | 2 +- app/controllers/api/base_controller.rb | 6 +++--- app/controllers/auth/confirmations_controller.rb | 2 +- app/controllers/auth/registrations_controller.rb | 2 +- app/controllers/auth/sessions_controller.rb | 2 +- .../export_controller_concern.rb} | 2 +- .../concerns/{ => api}/access_token_tracking_concern.rb | 2 +- .../{api_caching_concern.rb => api/caching_concern.rb} | 2 +- app/controllers/concerns/{ => api}/rate_limit_headers.rb | 2 +- app/controllers/concerns/{ => auth}/captcha_concern.rb | 2 +- .../concerns/{ => auth}/registration_spam_concern.rb | 2 +- .../{ => auth}/two_factor_authentication_concern.rb | 2 +- .../concerns/{ => settings}/export_controller_concern.rb | 2 +- .../settings/exports/blocked_accounts_controller.rb | 2 +- .../settings/exports/blocked_domains_controller.rb | 2 +- app/controllers/settings/exports/bookmarks_controller.rb | 2 +- .../settings/exports/following_accounts_controller.rb | 2 +- app/controllers/settings/exports/lists_controller.rb | 2 +- .../settings/exports/muted_accounts_controller.rb | 2 +- .../concerns/{ => api}/rate_limit_headers_spec.rb | 4 ++-- .../{ => settings}/export_controller_concern_spec.rb | 4 ++-- 22 files changed, 26 insertions(+), 26 deletions(-) rename app/controllers/concerns/{admin_export_controller_concern.rb => admin/export_controller_concern.rb} (92%) rename app/controllers/concerns/{ => api}/access_token_tracking_concern.rb (92%) rename app/controllers/concerns/{api_caching_concern.rb => api/caching_concern.rb} (93%) rename app/controllers/concerns/{ => api}/rate_limit_headers.rb (98%) rename app/controllers/concerns/{ => auth}/captcha_concern.rb (98%) rename app/controllers/concerns/{ => auth}/registration_spam_concern.rb (81%) rename app/controllers/concerns/{ => auth}/two_factor_authentication_concern.rb (98%) rename app/controllers/concerns/{ => settings}/export_controller_concern.rb (93%) rename spec/controllers/concerns/{ => api}/rate_limit_headers_spec.rb (95%) rename spec/controllers/concerns/{ => settings}/export_controller_concern_spec.rb (89%) diff --git a/app/controllers/admin/export_domain_allows_controller.rb b/app/controllers/admin/export_domain_allows_controller.rb index adfc39da21c872..ca88c6525e0ee6 100644 --- a/app/controllers/admin/export_domain_allows_controller.rb +++ b/app/controllers/admin/export_domain_allows_controller.rb @@ -4,7 +4,7 @@ module Admin class ExportDomainAllowsController < BaseController - include AdminExportControllerConcern + include Admin::ExportControllerConcern before_action :set_dummy_import!, only: [:new] diff --git a/app/controllers/admin/export_domain_blocks_controller.rb b/app/controllers/admin/export_domain_blocks_controller.rb index 816422d4ffcfae..433b8a158787a7 100644 --- a/app/controllers/admin/export_domain_blocks_controller.rb +++ b/app/controllers/admin/export_domain_blocks_controller.rb @@ -4,7 +4,7 @@ module Admin class ExportDomainBlocksController < BaseController - include AdminExportControllerConcern + include Admin::ExportControllerConcern before_action :set_dummy_import!, only: [:new] diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 135c5756589667..dc760297de7e0b 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -4,9 +4,9 @@ class Api::BaseController < ApplicationController DEFAULT_STATUSES_LIMIT = 20 DEFAULT_ACCOUNTS_LIMIT = 40 - include RateLimitHeaders - include AccessTokenTrackingConcern - include ApiCachingConcern + include Api::RateLimitHeaders + include Api::AccessTokenTrackingConcern + include Api::CachingConcern include Api::ContentSecurityPolicy skip_before_action :require_functional!, unless: :limited_federation_mode? diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb index 05e4605f4e6a46..9f6be9c424d0c4 100644 --- a/app/controllers/auth/confirmations_controller.rb +++ b/app/controllers/auth/confirmations_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Auth::ConfirmationsController < Devise::ConfirmationsController - include CaptchaConcern + include Auth::CaptchaConcern layout 'auth' diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 8be7c5f192f185..4535ecdbd0e835 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -2,7 +2,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController include RegistrationHelper - include RegistrationSpamConcern + include Auth::RegistrationSpamConcern layout :determine_layout diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index 84d9d5e11ed6dd..148ad53755ef8f 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -10,7 +10,7 @@ class Auth::SessionsController < Devise::SessionsController prepend_before_action :check_suspicious!, only: [:create] - include TwoFactorAuthenticationConcern + include Auth::TwoFactorAuthenticationConcern before_action :set_body_classes diff --git a/app/controllers/concerns/admin_export_controller_concern.rb b/app/controllers/concerns/admin/export_controller_concern.rb similarity index 92% rename from app/controllers/concerns/admin_export_controller_concern.rb rename to app/controllers/concerns/admin/export_controller_concern.rb index 4ac48a04b7ced9..6228ae67fe1b9a 100644 --- a/app/controllers/concerns/admin_export_controller_concern.rb +++ b/app/controllers/concerns/admin/export_controller_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AdminExportControllerConcern +module Admin::ExportControllerConcern extend ActiveSupport::Concern private diff --git a/app/controllers/concerns/access_token_tracking_concern.rb b/app/controllers/concerns/api/access_token_tracking_concern.rb similarity index 92% rename from app/controllers/concerns/access_token_tracking_concern.rb rename to app/controllers/concerns/api/access_token_tracking_concern.rb index cf60cfb995ba49..bc6ae51c772d77 100644 --- a/app/controllers/concerns/access_token_tracking_concern.rb +++ b/app/controllers/concerns/api/access_token_tracking_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AccessTokenTrackingConcern +module Api::AccessTokenTrackingConcern extend ActiveSupport::Concern ACCESS_TOKEN_UPDATE_FREQUENCY = 24.hours.freeze diff --git a/app/controllers/concerns/api_caching_concern.rb b/app/controllers/concerns/api/caching_concern.rb similarity index 93% rename from app/controllers/concerns/api_caching_concern.rb rename to app/controllers/concerns/api/caching_concern.rb index 12264d514e50e9..55d7fe56d7b744 100644 --- a/app/controllers/concerns/api_caching_concern.rb +++ b/app/controllers/concerns/api/caching_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module ApiCachingConcern +module Api::CachingConcern extend ActiveSupport::Concern def cache_if_unauthenticated! diff --git a/app/controllers/concerns/rate_limit_headers.rb b/app/controllers/concerns/api/rate_limit_headers.rb similarity index 98% rename from app/controllers/concerns/rate_limit_headers.rb rename to app/controllers/concerns/api/rate_limit_headers.rb index 5b83d8575ba5c4..fe57b6f6bd53e0 100644 --- a/app/controllers/concerns/rate_limit_headers.rb +++ b/app/controllers/concerns/api/rate_limit_headers.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module RateLimitHeaders +module Api::RateLimitHeaders extend ActiveSupport::Concern class_methods do diff --git a/app/controllers/concerns/captcha_concern.rb b/app/controllers/concerns/auth/captcha_concern.rb similarity index 98% rename from app/controllers/concerns/captcha_concern.rb rename to app/controllers/concerns/auth/captcha_concern.rb index 170c8f5e03a20f..cfd93978cea576 100644 --- a/app/controllers/concerns/captcha_concern.rb +++ b/app/controllers/concerns/auth/captcha_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module CaptchaConcern +module Auth::CaptchaConcern extend ActiveSupport::Concern include Hcaptcha::Adapters::ViewMethods diff --git a/app/controllers/concerns/registration_spam_concern.rb b/app/controllers/concerns/auth/registration_spam_concern.rb similarity index 81% rename from app/controllers/concerns/registration_spam_concern.rb rename to app/controllers/concerns/auth/registration_spam_concern.rb index af434c985a0c96..9f4798b5372d59 100644 --- a/app/controllers/concerns/registration_spam_concern.rb +++ b/app/controllers/concerns/auth/registration_spam_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module RegistrationSpamConcern +module Auth::RegistrationSpamConcern extend ActiveSupport::Concern def set_registration_form_time diff --git a/app/controllers/concerns/two_factor_authentication_concern.rb b/app/controllers/concerns/auth/two_factor_authentication_concern.rb similarity index 98% rename from app/controllers/concerns/two_factor_authentication_concern.rb rename to app/controllers/concerns/auth/two_factor_authentication_concern.rb index bc2d194c33ae35..effdb8d21c0885 100644 --- a/app/controllers/concerns/two_factor_authentication_concern.rb +++ b/app/controllers/concerns/auth/two_factor_authentication_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module TwoFactorAuthenticationConcern +module Auth::TwoFactorAuthenticationConcern extend ActiveSupport::Concern included do diff --git a/app/controllers/concerns/export_controller_concern.rb b/app/controllers/concerns/settings/export_controller_concern.rb similarity index 93% rename from app/controllers/concerns/export_controller_concern.rb rename to app/controllers/concerns/settings/export_controller_concern.rb index e1792fd6bf2f71..2cf28cced87234 100644 --- a/app/controllers/concerns/export_controller_concern.rb +++ b/app/controllers/concerns/settings/export_controller_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module ExportControllerConcern +module Settings::ExportControllerConcern extend ActiveSupport::Concern included do diff --git a/app/controllers/settings/exports/blocked_accounts_controller.rb b/app/controllers/settings/exports/blocked_accounts_controller.rb index 2190caa3619e6c..906564a3dcdcbd 100644 --- a/app/controllers/settings/exports/blocked_accounts_controller.rb +++ b/app/controllers/settings/exports/blocked_accounts_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class BlockedAccountsController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/app/controllers/settings/exports/blocked_domains_controller.rb b/app/controllers/settings/exports/blocked_domains_controller.rb index bee4b2431e374e..09dc52392f5cdd 100644 --- a/app/controllers/settings/exports/blocked_domains_controller.rb +++ b/app/controllers/settings/exports/blocked_domains_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class BlockedDomainsController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/app/controllers/settings/exports/bookmarks_controller.rb b/app/controllers/settings/exports/bookmarks_controller.rb index c12e2f147ac0cf..0321565b97c16c 100644 --- a/app/controllers/settings/exports/bookmarks_controller.rb +++ b/app/controllers/settings/exports/bookmarks_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class BookmarksController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/app/controllers/settings/exports/following_accounts_controller.rb b/app/controllers/settings/exports/following_accounts_controller.rb index acefcb15da67aa..0ac9031fb93fb7 100644 --- a/app/controllers/settings/exports/following_accounts_controller.rb +++ b/app/controllers/settings/exports/following_accounts_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class FollowingAccountsController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/app/controllers/settings/exports/lists_controller.rb b/app/controllers/settings/exports/lists_controller.rb index bc65f56a0eff65..d90c71e248aa9a 100644 --- a/app/controllers/settings/exports/lists_controller.rb +++ b/app/controllers/settings/exports/lists_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class ListsController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/app/controllers/settings/exports/muted_accounts_controller.rb b/app/controllers/settings/exports/muted_accounts_controller.rb index 50b7bf1f791192..e4b11589025e8f 100644 --- a/app/controllers/settings/exports/muted_accounts_controller.rb +++ b/app/controllers/settings/exports/muted_accounts_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class MutedAccountsController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/spec/controllers/concerns/rate_limit_headers_spec.rb b/spec/controllers/concerns/api/rate_limit_headers_spec.rb similarity index 95% rename from spec/controllers/concerns/rate_limit_headers_spec.rb rename to spec/controllers/concerns/api/rate_limit_headers_spec.rb index 1cdf741f4ded05..2050de2aed4ed8 100644 --- a/spec/controllers/concerns/rate_limit_headers_spec.rb +++ b/spec/controllers/concerns/api/rate_limit_headers_spec.rb @@ -2,9 +2,9 @@ require 'rails_helper' -describe RateLimitHeaders do +describe Api::RateLimitHeaders do controller(ApplicationController) do - include RateLimitHeaders + include Api::RateLimitHeaders def show head 200 diff --git a/spec/controllers/concerns/export_controller_concern_spec.rb b/spec/controllers/concerns/settings/export_controller_concern_spec.rb similarity index 89% rename from spec/controllers/concerns/export_controller_concern_spec.rb rename to spec/controllers/concerns/settings/export_controller_concern_spec.rb index 7f0a7c5b54a16d..a19af8689ac877 100644 --- a/spec/controllers/concerns/export_controller_concern_spec.rb +++ b/spec/controllers/concerns/settings/export_controller_concern_spec.rb @@ -2,9 +2,9 @@ require 'rails_helper' -describe ExportControllerConcern do +describe Settings::ExportControllerConcern do controller(ApplicationController) do - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file From 35deaaf90bec91f34b3e1f2afa472d5c3f2cdc75 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 10:41:26 -0500 Subject: [PATCH 25/41] Reduce AbcSize complexity in `InitialStateSerializer` (#27782) --- .rubocop_todo.yml | 2 +- app/serializers/initial_state_serializer.rb | 48 ++++++++++++--------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 43af4f670aeac8..dbd5beac2e7fe9 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -26,7 +26,7 @@ Lint/NonLocalExitFromIterator: # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: - Max: 144 + Max: 125 # Configuration parameters: CountBlocks, Max. Metrics/BlockNesting: diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index b707d6fcb6ab84..a8af45990f5a9a 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -39,18 +39,18 @@ def meta if object.current_account store[:me] = object.current_account.id.to_s - store[:unfollow_modal] = object.current_account.user.setting_unfollow_modal - store[:boost_modal] = object.current_account.user.setting_boost_modal - store[:delete_modal] = object.current_account.user.setting_delete_modal - store[:auto_play_gif] = object.current_account.user.setting_auto_play_gif - store[:display_media] = object.current_account.user.setting_display_media - store[:expand_spoilers] = object.current_account.user.setting_expand_spoilers - store[:reduce_motion] = object.current_account.user.setting_reduce_motion - store[:disable_swiping] = object.current_account.user.setting_disable_swiping - store[:advanced_layout] = object.current_account.user.setting_advanced_layout - store[:use_blurhash] = object.current_account.user.setting_use_blurhash - store[:use_pending_items] = object.current_account.user.setting_use_pending_items - store[:show_trends] = Setting.trends && object.current_account.user.setting_trends + store[:unfollow_modal] = object_account_user.setting_unfollow_modal + store[:boost_modal] = object_account_user.setting_boost_modal + store[:delete_modal] = object_account_user.setting_delete_modal + store[:auto_play_gif] = object_account_user.setting_auto_play_gif + store[:display_media] = object_account_user.setting_display_media + store[:expand_spoilers] = object_account_user.setting_expand_spoilers + store[:reduce_motion] = object_account_user.setting_reduce_motion + store[:disable_swiping] = object_account_user.setting_disable_swiping + store[:advanced_layout] = object_account_user.setting_advanced_layout + store[:use_blurhash] = object_account_user.setting_use_blurhash + store[:use_pending_items] = object_account_user.setting_use_pending_items + store[:show_trends] = Setting.trends && object_account_user.setting_trends else store[:auto_play_gif] = Setting.auto_play_gif store[:display_media] = Setting.display_media @@ -71,9 +71,9 @@ def compose if object.current_account store[:me] = object.current_account.id.to_s - store[:default_privacy] = object.visibility || object.current_account.user.setting_default_privacy - store[:default_sensitive] = object.current_account.user.setting_default_sensitive - store[:default_language] = object.current_account.user.preferred_posting_language + store[:default_privacy] = object.visibility || object_account_user.setting_default_privacy + store[:default_sensitive] = object_account_user.setting_default_sensitive + store[:default_language] = object_account_user.preferred_posting_language end store[:text] = object.text if object.text @@ -89,11 +89,11 @@ def accounts associations: [:account_stat, :user, { moved_to_account: [:account_stat, :user] }] ) - store[object.current_account.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.current_account, serializer: REST::AccountSerializer) if object.current_account - store[object.admin.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.admin, serializer: REST::AccountSerializer) if object.admin - store[object.owner.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.owner, serializer: REST::AccountSerializer) if object.owner - store[object.disabled_account.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.disabled_account, serializer: REST::AccountSerializer) if object.disabled_account - store[object.moved_to_account.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.moved_to_account, serializer: REST::AccountSerializer) if object.moved_to_account + store[object.current_account.id.to_s] = serialized_account(object.current_account) if object.current_account + store[object.admin.id.to_s] = serialized_account(object.admin) if object.admin + store[object.owner.id.to_s] = serialized_account(object.owner) if object.owner + store[object.disabled_account.id.to_s] = serialized_account(object.disabled_account) if object.disabled_account + store[object.moved_to_account.id.to_s] = serialized_account(object.moved_to_account) if object.moved_to_account store end @@ -108,6 +108,14 @@ def languages private + def object_account_user + object.current_account.user + end + + def serialized_account(account) + ActiveModelSerializers::SerializableResource.new(account, serializer: REST::AccountSerializer) + end + def instance_presenter @instance_presenter ||= InstancePresenter.new end From 963354978a0ba27c6ecea4a419b3330b3ad97733 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 30 Nov 2023 16:43:26 +0100 Subject: [PATCH 26/41] Add `Account#unavailable?` and `Account#permanently_unavailable?` aliases (#28053) --- app/controllers/api/base_controller.rb | 2 +- .../accounts/follower_accounts_controller.rb | 2 +- .../accounts/following_accounts_controller.rb | 2 +- .../api/v1/accounts/statuses_controller.rb | 2 +- .../auth/registrations_controller.rb | 2 +- .../concerns/account_owned_concern.rb | 6 ++-- .../authorized_applications_controller.rb | 2 +- app/controllers/settings/base_controller.rb | 2 +- .../settings/deletes_controller.rb | 2 +- .../well_known/webfinger_controller.rb | 2 +- app/lib/account_statuses_filter.rb | 6 +--- app/lib/activitypub/activity/move.rb | 2 +- app/models/account.rb | 3 ++ app/models/user.rb | 2 +- app/policies/status_policy.rb | 2 +- .../activitypub/actor_serializer.rb | 22 +++++++------- app/serializers/rest/account_serializer.rb | 30 +++++++++---------- app/services/follow_service.rb | 2 +- app/services/notify_service.rb | 2 +- app/services/process_mentions_service.rb | 2 +- app/services/report_service.rb | 2 +- app/views/admin/accounts/_account.html.haml | 8 ++--- .../authorized_applications/index.html.haml | 2 +- app/workers/account_deletion_worker.rb | 2 +- .../suspended_user_cleanup_scheduler.rb | 4 +-- 25 files changed, 57 insertions(+), 58 deletions(-) diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index dc760297de7e0b..c81ba32b08c086 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -105,7 +105,7 @@ def require_authenticated_user! end def require_not_suspended! - render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.suspended? + render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.unavailable? end def require_user! diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index 1a996d362aa4f4..21b1095f1845f8 100644 --- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb @@ -26,7 +26,7 @@ def load_accounts end def hide_results? - @account.suspended? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) + @account.unavailable? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb index 6e6ebae43b005c..1db521f79cbbd5 100644 --- a/app/controllers/api/v1/accounts/following_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb @@ -26,7 +26,7 @@ def load_accounts end def hide_results? - @account.suspended? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) + @account.unavailable? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb index 51f541bd23ebc9..fe4279302fc891 100644 --- a/app/controllers/api/v1/accounts/statuses_controller.rb +++ b/app/controllers/api/v1/accounts/statuses_controller.rb @@ -19,7 +19,7 @@ def set_account end def load_statuses - @account.suspended? ? [] : cached_account_statuses + @account.unavailable? ? [] : cached_account_statuses end def cached_account_statuses diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 4535ecdbd0e835..acfc0af0d9c0b6 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -120,7 +120,7 @@ def set_strikes end def require_not_suspended! - forbidden if current_account.suspended? + forbidden if current_account.unavailable? end def set_rules diff --git a/app/controllers/concerns/account_owned_concern.rb b/app/controllers/concerns/account_owned_concern.rb index 3fc0938bfc7672..2b132417f7cf33 100644 --- a/app/controllers/concerns/account_owned_concern.rb +++ b/app/controllers/concerns/account_owned_concern.rb @@ -34,8 +34,8 @@ def check_account_confirmation end def check_account_suspension - if @account.suspended_permanently? - permanent_suspension_response + if @account.permanently_unavailable? + permanent_unavailability_response elsif @account.suspended? && !skip_temporary_suspension_response? temporary_suspension_response end @@ -45,7 +45,7 @@ def skip_temporary_suspension_response? false end - def permanent_suspension_response + def permanent_unavailability_response expires_in(3.minutes, public: true) gone end diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index 350ae2e9062177..8440df6b7e69a9 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -31,7 +31,7 @@ def store_current_location end def require_not_suspended! - forbidden if current_account.suspended? + forbidden if current_account.unavailable? end def set_cache_headers diff --git a/app/controllers/settings/base_controller.rb b/app/controllers/settings/base_controller.rb index 64dcd47d120083..f15140aa2be3da 100644 --- a/app/controllers/settings/base_controller.rb +++ b/app/controllers/settings/base_controller.rb @@ -18,6 +18,6 @@ def set_cache_headers end def require_not_suspended! - forbidden if current_account.suspended? + forbidden if current_account.unavailable? end end diff --git a/app/controllers/settings/deletes_controller.rb b/app/controllers/settings/deletes_controller.rb index bb096567a9ceea..16c201b6b3f309 100644 --- a/app/controllers/settings/deletes_controller.rb +++ b/app/controllers/settings/deletes_controller.rb @@ -25,7 +25,7 @@ def resource_params end def require_not_suspended! - forbidden if current_account.suspended? + forbidden if current_account.unavailable? end def challenge_passed? diff --git a/app/controllers/well_known/webfinger_controller.rb b/app/controllers/well_known/webfinger_controller.rb index 4748940f7c2422..364fbf8a18c47e 100644 --- a/app/controllers/well_known/webfinger_controller.rb +++ b/app/controllers/well_known/webfinger_controller.rb @@ -42,7 +42,7 @@ def resource_param end def check_account_suspension - gone if @account.suspended_permanently? + gone if @account.permanently_unavailable? end def gone diff --git a/app/lib/account_statuses_filter.rb b/app/lib/account_statuses_filter.rb index d1365de586e42b..eb7592cdce09e1 100644 --- a/app/lib/account_statuses_filter.rb +++ b/app/lib/account_statuses_filter.rb @@ -32,7 +32,7 @@ def results private def initial_scope - return Status.none if suspended? + return Status.none if account.unavailable? if anonymous? account.statuses.where(visibility: %i(public unlisted)) @@ -95,10 +95,6 @@ def hashtag_scope end end - def suspended? - account.suspended? - end - def anonymous? current_account.nil? end diff --git a/app/lib/activitypub/activity/move.rb b/app/lib/activitypub/activity/move.rb index 8576ceccdf2bc7..7bd7e238e2db06 100644 --- a/app/lib/activitypub/activity/move.rb +++ b/app/lib/activitypub/activity/move.rb @@ -9,7 +9,7 @@ def perform target_account = ActivityPub::FetchRemoteAccountService.new.call(target_uri) - if target_account.nil? || target_account.suspended? || !target_account.also_known_as.include?(origin_account.uri) + if target_account.nil? || target_account.unavailable? || !target_account.also_known_as.include?(origin_account.uri) unmark_as_processing! return end diff --git a/app/models/account.rb b/app/models/account.rb index a25ebc4aaf15d3..03edcb2a25708c 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -246,6 +246,9 @@ def suspended_temporarily? suspended? && deletion_request.present? end + alias unavailable? suspended? + alias permanently_unavailable? suspended_permanently? + def suspend!(date: Time.now.utc, origin: :local, block_email: true) transaction do create_deletion_request! diff --git a/app/models/user.rb b/app/models/user.rb index 5185343af3e207..b0eba97c3636b4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -250,7 +250,7 @@ def functional? end def functional_or_moved? - confirmed? && approved? && !disabled? && !account.suspended? && !account.memorial? + confirmed? && approved? && !disabled? && !account.unavailable? && !account.memorial? end def unconfirmed? diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index f3d0ffdbae2879..322d3aec5cdff7 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -8,7 +8,7 @@ def initialize(current_account, record, preloaded_relations = {}) end def show? - return false if author.suspended? + return false if author.unavailable? if requires_mention? owned? || mention_exists? diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb index 31f39954fb077d..4ab48ff204b344 100644 --- a/app/serializers/activitypub/actor_serializer.rb +++ b/app/serializers/activitypub/actor_serializer.rb @@ -96,19 +96,19 @@ def preferred_username end def discoverable - object.suspended? ? false : (object.discoverable || false) + object.unavailable? ? false : (object.discoverable || false) end def indexable - object.suspended? ? false : (object.indexable || false) + object.unavailable? ? false : (object.indexable || false) end def name - object.suspended? ? object.username : (object.display_name.presence || object.username) + object.unavailable? ? object.username : (object.display_name.presence || object.username) end def summary - object.suspended? ? '' : account_bio_format(object) + object.unavailable? ? '' : account_bio_format(object) end def icon @@ -132,23 +132,23 @@ def url end def avatar_exists? - !object.suspended? && object.avatar? + !object.unavailable? && object.avatar? end def header_exists? - !object.suspended? && object.header? + !object.unavailable? && object.header? end def manually_approves_followers - object.suspended? ? false : object.locked + object.unavailable? ? false : object.locked end def virtual_tags - object.suspended? ? [] : (object.emojis + object.tags) + object.unavailable? ? [] : (object.emojis + object.tags) end def virtual_attachments - object.suspended? ? [] : object.fields + object.unavailable? ? [] : object.fields end def moved_to @@ -156,11 +156,11 @@ def moved_to end def moved? - !object.suspended? && object.moved? + !object.unavailable? && object.moved? end def also_known_as? - !object.suspended? && !object.also_known_as.empty? + !object.unavailable? && !object.also_known_as.empty? end def published diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb index 5d1292a6bdae6f..354d384464dffb 100644 --- a/app/serializers/rest/account_serializer.rb +++ b/app/serializers/rest/account_serializer.rb @@ -61,7 +61,7 @@ def acct end def note - object.suspended? ? '' : account_bio_format(object) + object.unavailable? ? '' : account_bio_format(object) end def url @@ -73,19 +73,19 @@ def uri end def avatar - full_asset_url(object.suspended? ? object.avatar.default_url : object.avatar_original_url) + full_asset_url(object.unavailable? ? object.avatar.default_url : object.avatar_original_url) end def avatar_static - full_asset_url(object.suspended? ? object.avatar.default_url : object.avatar_static_url) + full_asset_url(object.unavailable? ? object.avatar.default_url : object.avatar_static_url) end def header - full_asset_url(object.suspended? ? object.header.default_url : object.header_original_url) + full_asset_url(object.unavailable? ? object.header.default_url : object.header_original_url) end def header_static - full_asset_url(object.suspended? ? object.header.default_url : object.header_static_url) + full_asset_url(object.unavailable? ? object.header.default_url : object.header_static_url) end def created_at @@ -97,39 +97,39 @@ def last_status_at end def display_name - object.suspended? ? '' : object.display_name + object.unavailable? ? '' : object.display_name end def locked - object.suspended? ? false : object.locked + object.unavailable? ? false : object.locked end def bot - object.suspended? ? false : object.bot + object.unavailable? ? false : object.bot end def discoverable - object.suspended? ? false : object.discoverable + object.unavailable? ? false : object.discoverable end def indexable - object.suspended? ? false : object.indexable + object.unavailable? ? false : object.indexable end def moved_to_account - object.suspended? ? nil : AccountDecorator.new(object.moved_to_account) + object.unavailable? ? nil : AccountDecorator.new(object.moved_to_account) end def emojis - object.suspended? ? [] : object.emojis + object.unavailable? ? [] : object.emojis end def fields - object.suspended? ? [] : object.fields + object.unavailable? ? [] : object.fields end def suspended - object.suspended? + object.unavailable? end def silenced @@ -141,7 +141,7 @@ def memorial end def roles - if object.suspended? || object.user.nil? + if object.unavailable? || object.user.nil? [] else [object.user.role].compact.filter(&:highlighted?) diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb index 1aa0241fe62325..af5f996077e4a1 100644 --- a/app/services/follow_service.rb +++ b/app/services/follow_service.rb @@ -50,7 +50,7 @@ def mark_home_feed_as_partial! end def following_not_possible? - @target_account.nil? || @target_account.id == @source_account.id || @target_account.suspended? + @target_account.nil? || @target_account.id == @source_account.id || @target_account.unavailable? end def following_not_allowed? diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 125883b1534d54..13eb20986e3e65 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -108,7 +108,7 @@ def domain_blocking? end def blocked? - blocked = @recipient.suspended? + blocked = @recipient.unavailable? blocked ||= from_self? && @notification.type != :poll return blocked if message? && from_staff? diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index f3fbb802100f42..1c4c7805f1423e 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -51,7 +51,7 @@ def scan_text! # If after resolving it still isn't found or isn't the right # protocol, then give up - next match if mention_undeliverable?(mentioned_account) || mentioned_account&.suspended? + next match if mention_undeliverable?(mentioned_account) || mentioned_account&.unavailable? mention = @previous_mentions.find { |x| x.account_id == mentioned_account.id } mention ||= @current_mentions.find { |x| x.account_id == mentioned_account.id } diff --git a/app/services/report_service.rb b/app/services/report_service.rb index 38e55c5b6347fd..fe546c383e62c0 100644 --- a/app/services/report_service.rb +++ b/app/services/report_service.rb @@ -12,7 +12,7 @@ def call(source_account, target_account, options = {}) @rule_ids = options.delete(:rule_ids).presence @options = options - raise ActiveRecord::RecordNotFound if @target_account.suspended? + raise ActiveRecord::RecordNotFound if @target_account.unavailable? create_report! notify_staff! diff --git a/app/views/admin/accounts/_account.html.haml b/app/views/admin/accounts/_account.html.haml index 755b987a877cd7..d2f6652a00d581 100644 --- a/app/views/admin/accounts/_account.html.haml +++ b/app/views/admin/accounts/_account.html.haml @@ -1,4 +1,4 @@ -.batch-table__row{ class: [!account.suspended? && account.user_pending? && 'batch-table__row--attention', (account.suspended? || account.user_unconfirmed?) && 'batch-table__row--muted'] } +.batch-table__row{ class: [!account.unavailable? && account.user_pending? && 'batch-table__row--attention', (account.unavailable? || account.user_unconfirmed?) && 'batch-table__row--muted'] } %label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox = f.check_box :account_ids, { multiple: true, include_hidden: false }, account.id .batch-table__row__content.batch-table__row__content--unpadded @@ -8,13 +8,13 @@ %td = account_link_to account, path: admin_account_path(account.id) %td.accounts-table__count.optional - - if account.suspended? || account.user_pending? + - if account.unavailable? || account.user_pending? \- - else = friendly_number_to_human account.statuses_count %small= t('accounts.posts', count: account.statuses_count).downcase %td.accounts-table__count.optional - - if account.suspended? || account.user_pending? + - if account.unavailable? || account.user_pending? \- - else = friendly_number_to_human account.followers_count @@ -30,6 +30,6 @@ \- %br/ %samp.ellipsized-ip= relevant_account_ip(account, params[:ip]) - - if !account.suspended? && account.user_pending? && account.user&.invite_request&.text.present? + - if !account.unavailable? && account.user_pending? && account.user&.invite_request&.text.present? .batch-table__row__content__quote %p= account.user&.invite_request&.text diff --git a/app/views/oauth/authorized_applications/index.html.haml b/app/views/oauth/authorized_applications/index.html.haml index 40b09d87f1afb8..92e24d30c8597d 100644 --- a/app/views/oauth/authorized_applications/index.html.haml +++ b/app/views/oauth/authorized_applications/index.html.haml @@ -27,7 +27,7 @@ = t('doorkeeper.authorized_applications.index.authorized_at', date: l(application.created_at.to_date)) - - unless application.superapp? || current_account.suspended? + - unless application.superapp? || current_account.unavailable? %div = table_link_to 'times', t('doorkeeper.authorized_applications.buttons.revoke'), oauth_authorized_application_path(application), method: :delete, data: { confirm: t('doorkeeper.authorized_applications.confirmations.revoke') } diff --git a/app/workers/account_deletion_worker.rb b/app/workers/account_deletion_worker.rb index e4f943fbd1fffd..070352f9572544 100644 --- a/app/workers/account_deletion_worker.rb +++ b/app/workers/account_deletion_worker.rb @@ -7,7 +7,7 @@ class AccountDeletionWorker def perform(account_id, options = {}) account = Account.find(account_id) - return unless account.suspended? + return unless account.unavailable? reserve_username = options.with_indifferent_access.fetch(:reserve_username, true) skip_activitypub = options.with_indifferent_access.fetch(:skip_activitypub, false) diff --git a/app/workers/scheduler/suspended_user_cleanup_scheduler.rb b/app/workers/scheduler/suspended_user_cleanup_scheduler.rb index 90feead676d80d..4ea81c785b38a9 100644 --- a/app/workers/scheduler/suspended_user_cleanup_scheduler.rb +++ b/app/workers/scheduler/suspended_user_cleanup_scheduler.rb @@ -21,12 +21,12 @@ class Scheduler::SuspendedUserCleanupScheduler def perform return if Sidekiq::Queue.new('pull').size > MAX_PULL_SIZE - clean_suspended_accounts! + process_deletion_requests! end private - def clean_suspended_accounts! + def process_deletion_requests! # This should be fine because we only process a small amount of deletion requests at once and # `id` and `created_at` should follow the same order. AccountDeletionRequest.reorder(id: :asc).take(MAX_DELETIONS_PER_JOB).each do |deletion_request| From 8710bdb183073381250085ffa20e21e22d9069b6 Mon Sep 17 00:00:00 2001 From: Michael Stanclift Date: Thu, 30 Nov 2023 10:11:21 -0600 Subject: [PATCH 27/41] Fix mastodon user not being owner of tmp folder in Dockerfile (#28137) --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ed5ebf1e0aaeca..4d5bd57f1180e3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -247,7 +247,9 @@ RUN \ RUN \ # Pre-create and chown system volume to Mastodon user mkdir -p /opt/mastodon/public/system; \ - chown mastodon:mastodon /opt/mastodon/public/system; + chown mastodon:mastodon /opt/mastodon/public/system; \ +# Set Mastodon user as owner of tmp folder + chown -R mastodon:mastodon /opt/mastodon/tmp; # Set the running user for resulting container USER mastodon From b751078fcd21d13f6e4b63d7a86dd2be893d2753 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 05:38:15 -0500 Subject: [PATCH 28/41] Eliminate double subject call in admin/ controller specs (#28158) --- .../account_moderation_notes_controller_spec.rb | 6 +++--- .../admin/custom_emojis_controller_spec.rb | 16 ++++++++-------- .../admin/report_notes_controller_spec.rb | 10 +++++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/spec/controllers/admin/account_moderation_notes_controller_spec.rb b/spec/controllers/admin/account_moderation_notes_controller_spec.rb index 3e1b4b280f678c..8d24a7af37383b 100644 --- a/spec/controllers/admin/account_moderation_notes_controller_spec.rb +++ b/spec/controllers/admin/account_moderation_notes_controller_spec.rb @@ -20,7 +20,7 @@ it 'successfully creates a note' do expect { subject }.to change(AccountModerationNote, :count).by(1) - expect(subject).to redirect_to admin_account_path(target_account.id) + expect(response).to redirect_to admin_account_path(target_account.id) end end @@ -29,7 +29,7 @@ it 'falls to create a note' do expect { subject }.to_not change(AccountModerationNote, :count) - expect(subject).to render_template 'admin/accounts/show' + expect(response).to render_template 'admin/accounts/show' end end end @@ -42,7 +42,7 @@ it 'destroys note' do expect { subject }.to change(AccountModerationNote, :count).by(-1) - expect(subject).to redirect_to admin_account_path(target_account.id) + expect(response).to redirect_to admin_account_path(target_account.id) end end end diff --git a/spec/controllers/admin/custom_emojis_controller_spec.rb b/spec/controllers/admin/custom_emojis_controller_spec.rb index 6c32a3a5793187..9e732200dd26a7 100644 --- a/spec/controllers/admin/custom_emojis_controller_spec.rb +++ b/spec/controllers/admin/custom_emojis_controller_spec.rb @@ -12,24 +12,24 @@ end describe 'GET #index' do - subject { get :index } - before do Fabricate(:custom_emoji) end it 'renders index page' do - expect(subject).to have_http_status 200 - expect(subject).to render_template :index + get :index + + expect(response).to have_http_status 200 + expect(response).to render_template :index end end describe 'GET #new' do - subject { get :new } - it 'renders new page' do - expect(subject).to have_http_status 200 - expect(subject).to render_template :new + get :new + + expect(response).to have_http_status 200 + expect(response).to render_template :new end end diff --git a/spec/controllers/admin/report_notes_controller_spec.rb b/spec/controllers/admin/report_notes_controller_spec.rb index b5ba4a84dcbb7b..4ddf4a4e2476cc 100644 --- a/spec/controllers/admin/report_notes_controller_spec.rb +++ b/spec/controllers/admin/report_notes_controller_spec.rb @@ -27,7 +27,7 @@ it 'creates a report note and resolves report' do expect { subject }.to change(ReportNote, :count).by(1) expect(report.reload).to be_action_taken - expect(subject).to redirect_to admin_reports_path + expect(response).to redirect_to admin_reports_path end end @@ -37,7 +37,7 @@ it 'creates a report note and does not resolve report' do expect { subject }.to change(ReportNote, :count).by(1) expect(report.reload).to_not be_action_taken - expect(subject).to redirect_to admin_report_path(report) + expect(response).to redirect_to admin_report_path(report) end end end @@ -52,7 +52,7 @@ it 'creates a report note and unresolves report' do expect { subject }.to change(ReportNote, :count).by(1) expect(report.reload).to_not be_action_taken - expect(subject).to redirect_to admin_report_path(report) + expect(response).to redirect_to admin_report_path(report) end end @@ -62,7 +62,7 @@ it 'creates a report note and does not unresolve report' do expect { subject }.to change(ReportNote, :count).by(1) expect(report.reload).to be_action_taken - expect(subject).to redirect_to admin_report_path(report) + expect(response).to redirect_to admin_report_path(report) end end end @@ -86,7 +86,7 @@ it 'deletes note' do expect { subject }.to change(ReportNote, :count).by(-1) - expect(subject).to redirect_to admin_report_path(report_note.report) + expect(response).to redirect_to admin_report_path(report_note.report) end end end From 440b80b2e795c21a22de4514160679e68561d98b Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 06:00:41 -0500 Subject: [PATCH 29/41] Model concerns organization into module namespaces (#28149) --- .rubocop_todo.yml | 18 ++++++------- app/models/account.rb | 25 ++++++++++--------- .../associations.rb} | 2 +- .../{account_avatar.rb => account/avatar.rb} | 2 +- .../counters.rb} | 2 +- .../finder_concern.rb} | 2 +- .../{account_header.rb => account/header.rb} | 2 +- .../interactions.rb} | 2 +- .../merging.rb} | 2 +- .../{account_search.rb => account/search.rb} | 2 +- .../statuses_search.rb} | 2 +- .../safe_reblog_insert.rb} | 2 +- .../search_concern.rb} | 2 +- .../snapshot_concern.rb} | 2 +- .../threading_concern.rb} | 2 +- .../has_settings.rb} | 2 +- .../concerns/{ => user}/ldap_authenticable.rb | 2 +- .../concerns/{ => user}/omniauthable.rb | 2 +- .../concerns/{ => user}/pam_authenticable.rb | 2 +- app/models/status.rb | 10 ++++---- app/models/user.rb | 11 ++++---- app/views/settings/profiles/show.html.haml | 4 +-- lib/mastodon/cli/maintenance.rb | 4 +-- spec/models/account_spec.rb | 4 +-- .../counters_spec.rb} | 2 +- .../finder_concern_spec.rb} | 2 +- .../interactions_spec.rb} | 2 +- .../statuses_search_spec.rb} | 2 +- .../threading_concern_spec.rb} | 2 +- .../search_spec.rb} | 2 +- .../statuses_search_spec.rb} | 2 +- 31 files changed, 62 insertions(+), 62 deletions(-) rename app/models/concerns/{account_associations.rb => account/associations.rb} (99%) rename app/models/concerns/{account_avatar.rb => account/avatar.rb} (98%) rename app/models/concerns/{account_counters.rb => account/counters.rb} (99%) rename app/models/concerns/{account_finder_concern.rb => account/finder_concern.rb} (98%) rename app/models/concerns/{account_header.rb => account/header.rb} (98%) rename app/models/concerns/{account_interactions.rb => account/interactions.rb} (99%) rename app/models/concerns/{account_merging.rb => account/merging.rb} (98%) rename app/models/concerns/{account_search.rb => account/search.rb} (99%) rename app/models/concerns/{account_statuses_search.rb => account/statuses_search.rb} (97%) rename app/models/concerns/{status_safe_reblog_insert.rb => status/safe_reblog_insert.rb} (98%) rename app/models/concerns/{status_search_concern.rb => status/search_concern.rb} (97%) rename app/models/concerns/{status_snapshot_concern.rb => status/snapshot_concern.rb} (96%) rename app/models/concerns/{status_threading_concern.rb => status/threading_concern.rb} (98%) rename app/models/concerns/{has_user_settings.rb => user/has_settings.rb} (99%) rename app/models/concerns/{ => user}/ldap_authenticable.rb (98%) rename app/models/concerns/{ => user}/omniauthable.rb (99%) rename app/models/concerns/{ => user}/pam_authenticable.rb (98%) rename spec/models/concerns/{account_counters_spec.rb => account/counters_spec.rb} (98%) rename spec/models/concerns/{account_finder_concern_spec.rb => account/finder_concern_spec.rb} (98%) rename spec/models/concerns/{account_interactions_spec.rb => account/interactions_spec.rb} (99%) rename spec/models/concerns/{account_statuses_search_spec.rb => account/statuses_search_spec.rb} (98%) rename spec/models/concerns/{status_threading_concern_spec.rb => status/threading_concern_spec.rb} (99%) rename spec/search/models/concerns/{account_search_spec.rb => account/search_spec.rb} (98%) rename spec/search/models/concerns/{account_statuses_search_spec.rb => account/statuses_search_spec.rb} (98%) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index dbd5beac2e7fe9..9fb163ceb9d23a 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -107,7 +107,7 @@ Rails/ApplicationController: # Include: app/models/**/*.rb Rails/HasAndBelongsToMany: Exclude: - - 'app/models/concerns/account_associations.rb' + - 'app/models/concerns/account/associations.rb' - 'app/models/preview_card.rb' - 'app/models/status.rb' - 'app/models/tag.rb' @@ -116,7 +116,7 @@ Rails/HasAndBelongsToMany: # Include: app/models/**/*.rb Rails/HasManyOrHasOneDependent: Exclude: - - 'app/models/concerns/account_counters.rb' + - 'app/models/concerns/account/counters.rb' - 'app/models/conversation.rb' - 'app/models/custom_emoji.rb' - 'app/models/custom_emoji_category.rb' @@ -172,7 +172,7 @@ Rails/SkipsModelValidations: Exclude: - 'app/controllers/admin/invites_controller.rb' - 'app/controllers/concerns/session_tracking_concern.rb' - - 'app/models/concerns/account_merging.rb' + - 'app/models/concerns/account/merging.rb' - 'app/models/concerns/expireable.rb' - 'app/models/status.rb' - 'app/models/trends/links.rb' @@ -252,7 +252,7 @@ Rails/WhereExists: - 'app/lib/feed_manager.rb' - 'app/lib/status_cache_hydrator.rb' - 'app/lib/suspicious_sign_in_detector.rb' - - 'app/models/concerns/account_interactions.rb' + - 'app/models/concerns/account/interactions.rb' - 'app/models/featured_tag.rb' - 'app/models/poll.rb' - 'app/models/session_activation.rb' @@ -342,8 +342,8 @@ Style/GuardClause: - 'app/lib/request_pool.rb' - 'app/lib/webfinger.rb' - 'app/lib/webfinger_resource.rb' - - 'app/models/concerns/account_counters.rb' - - 'app/models/concerns/ldap_authenticable.rb' + - 'app/models/concerns/account/counters.rb' + - 'app/models/concerns/user/ldap_authenticable.rb' - 'app/models/tag.rb' - 'app/models/user.rb' - 'app/services/fan_out_on_write_service.rb' @@ -372,8 +372,8 @@ Style/HashAsLastArrayItem: Exclude: - 'app/controllers/admin/statuses_controller.rb' - 'app/controllers/api/v1/statuses_controller.rb' - - 'app/models/concerns/account_counters.rb' - - 'app/models/concerns/status_threading_concern.rb' + - 'app/models/concerns/account/counters.rb' + - 'app/models/concerns/status/threading_concern.rb' - 'app/models/status.rb' - 'app/services/batched_remove_status_service.rb' - 'app/services/notify_service.rb' @@ -486,7 +486,7 @@ Style/RedundantReturn: # AllowedMethods: present?, blank?, presence, try, try! Style/SafeNavigation: Exclude: - - 'app/models/concerns/account_finder_concern.rb' + - 'app/models/concerns/account/finder_concern.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. diff --git a/app/models/account.rb b/app/models/account.rb index 03edcb2a25708c..4119944e598988 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -70,19 +70,20 @@ class Account < ApplicationRecord URL_PREFIX_RE = %r{\Ahttp(s?)://[^/]+} USERNAME_ONLY_RE = /\A#{USERNAME_RE}\z/i - include Attachmentable - include AccountAssociations - include AccountAvatar - include AccountFinderConcern - include AccountHeader - include AccountInteractions - include Paginable - include AccountCounters - include DomainNormalizable + include Attachmentable # Load prior to Avatar & Header concerns + + include Account::Associations + include Account::Avatar + include Account::Counters + include Account::FinderConcern + include Account::Header + include Account::Interactions + include Account::Merging + include Account::Search + include Account::StatusesSearch include DomainMaterializable - include AccountMerging - include AccountSearch - include AccountStatusesSearch + include DomainNormalizable + include Paginable enum protocol: { ostatus: 0, activitypub: 1 } enum suspension_origin: { local: 0, remote: 1 }, _prefix: true diff --git a/app/models/concerns/account_associations.rb b/app/models/concerns/account/associations.rb similarity index 99% rename from app/models/concerns/account_associations.rb rename to app/models/concerns/account/associations.rb index 592812e96010a3..31902ae21a8456 100644 --- a/app/models/concerns/account_associations.rb +++ b/app/models/concerns/account/associations.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AccountAssociations +module Account::Associations extend ActiveSupport::Concern included do diff --git a/app/models/concerns/account_avatar.rb b/app/models/concerns/account/avatar.rb similarity index 98% rename from app/models/concerns/account_avatar.rb rename to app/models/concerns/account/avatar.rb index b5919a9a23d585..39f599db182275 100644 --- a/app/models/concerns/account_avatar.rb +++ b/app/models/concerns/account/avatar.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AccountAvatar +module Account::Avatar extend ActiveSupport::Concern IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze diff --git a/app/models/concerns/account_counters.rb b/app/models/concerns/account/counters.rb similarity index 99% rename from app/models/concerns/account_counters.rb rename to app/models/concerns/account/counters.rb index 3fabb520542e07..fb69be9b7004f3 100644 --- a/app/models/concerns/account_counters.rb +++ b/app/models/concerns/account/counters.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AccountCounters +module Account::Counters extend ActiveSupport::Concern ALLOWED_COUNTER_KEYS = %i(statuses_count following_count followers_count).freeze diff --git a/app/models/concerns/account_finder_concern.rb b/app/models/concerns/account/finder_concern.rb similarity index 98% rename from app/models/concerns/account_finder_concern.rb rename to app/models/concerns/account/finder_concern.rb index 37c3b889593b37..7faaddeb4302c6 100644 --- a/app/models/concerns/account_finder_concern.rb +++ b/app/models/concerns/account/finder_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AccountFinderConcern +module Account::FinderConcern extend ActiveSupport::Concern class_methods do diff --git a/app/models/concerns/account_header.rb b/app/models/concerns/account/header.rb similarity index 98% rename from app/models/concerns/account_header.rb rename to app/models/concerns/account/header.rb index e184880f93af39..44ae774e94d034 100644 --- a/app/models/concerns/account_header.rb +++ b/app/models/concerns/account/header.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AccountHeader +module Account::Header extend ActiveSupport::Concern IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account/interactions.rb similarity index 99% rename from app/models/concerns/account_interactions.rb rename to app/models/concerns/account/interactions.rb index 3c64ebd9faf893..0ea26e628d8656 100644 --- a/app/models/concerns/account_interactions.rb +++ b/app/models/concerns/account/interactions.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AccountInteractions +module Account::Interactions extend ActiveSupport::Concern class_methods do diff --git a/app/models/concerns/account_merging.rb b/app/models/concerns/account/merging.rb similarity index 98% rename from app/models/concerns/account_merging.rb rename to app/models/concerns/account/merging.rb index 14e157a3d89fb4..960ee1819f840b 100644 --- a/app/models/concerns/account_merging.rb +++ b/app/models/concerns/account/merging.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AccountMerging +module Account::Merging extend ActiveSupport::Concern def merge_with!(other_account) diff --git a/app/models/concerns/account_search.rb b/app/models/concerns/account/search.rb similarity index 99% rename from app/models/concerns/account_search.rb rename to app/models/concerns/account/search.rb index b855727b4ddbcc..b02b9bd4611783 100644 --- a/app/models/concerns/account_search.rb +++ b/app/models/concerns/account/search.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AccountSearch +module Account::Search extend ActiveSupport::Concern DISALLOWED_TSQUERY_CHARACTERS = /['?\\:‘’]/ diff --git a/app/models/concerns/account_statuses_search.rb b/app/models/concerns/account/statuses_search.rb similarity index 97% rename from app/models/concerns/account_statuses_search.rb rename to app/models/concerns/account/statuses_search.rb index 4b2bc4117ad2fa..334b7145043cc2 100644 --- a/app/models/concerns/account_statuses_search.rb +++ b/app/models/concerns/account/statuses_search.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AccountStatusesSearch +module Account::StatusesSearch extend ActiveSupport::Concern included do diff --git a/app/models/concerns/status_safe_reblog_insert.rb b/app/models/concerns/status/safe_reblog_insert.rb similarity index 98% rename from app/models/concerns/status_safe_reblog_insert.rb rename to app/models/concerns/status/safe_reblog_insert.rb index 0007b46d402084..60ddb78e52c40e 100644 --- a/app/models/concerns/status_safe_reblog_insert.rb +++ b/app/models/concerns/status/safe_reblog_insert.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module StatusSafeReblogInsert +module Status::SafeReblogInsert extend ActiveSupport::Concern class_methods do diff --git a/app/models/concerns/status_search_concern.rb b/app/models/concerns/status/search_concern.rb similarity index 97% rename from app/models/concerns/status_search_concern.rb rename to app/models/concerns/status/search_concern.rb index 7252fde7374085..c16db8bd8c40aa 100644 --- a/app/models/concerns/status_search_concern.rb +++ b/app/models/concerns/status/search_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module StatusSearchConcern +module Status::SearchConcern extend ActiveSupport::Concern included do diff --git a/app/models/concerns/status_snapshot_concern.rb b/app/models/concerns/status/snapshot_concern.rb similarity index 96% rename from app/models/concerns/status_snapshot_concern.rb rename to app/models/concerns/status/snapshot_concern.rb index 9741b9aeb29539..ba624d943e46ec 100644 --- a/app/models/concerns/status_snapshot_concern.rb +++ b/app/models/concerns/status/snapshot_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module StatusSnapshotConcern +module Status::SnapshotConcern extend ActiveSupport::Concern included do diff --git a/app/models/concerns/status_threading_concern.rb b/app/models/concerns/status/threading_concern.rb similarity index 98% rename from app/models/concerns/status_threading_concern.rb rename to app/models/concerns/status/threading_concern.rb index 2ca3b66c276e68..2606fd2f2783c2 100644 --- a/app/models/concerns/status_threading_concern.rb +++ b/app/models/concerns/status/threading_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module StatusThreadingConcern +module Status::ThreadingConcern extend ActiveSupport::Concern def ancestors(limit, account = nil) diff --git a/app/models/concerns/has_user_settings.rb b/app/models/concerns/user/has_settings.rb similarity index 99% rename from app/models/concerns/has_user_settings.rb rename to app/models/concerns/user/has_settings.rb index b7c7104a1359ed..bfa8aa2ca3549f 100644 --- a/app/models/concerns/has_user_settings.rb +++ b/app/models/concerns/user/has_settings.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module HasUserSettings +module User::HasSettings extend ActiveSupport::Concern included do diff --git a/app/models/concerns/ldap_authenticable.rb b/app/models/concerns/user/ldap_authenticable.rb similarity index 98% rename from app/models/concerns/ldap_authenticable.rb rename to app/models/concerns/user/ldap_authenticable.rb index 775df081764d96..d84ff084b2f10f 100644 --- a/app/models/concerns/ldap_authenticable.rb +++ b/app/models/concerns/user/ldap_authenticable.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module LdapAuthenticable +module User::LdapAuthenticable extend ActiveSupport::Concern class_methods do diff --git a/app/models/concerns/omniauthable.rb b/app/models/concerns/user/omniauthable.rb similarity index 99% rename from app/models/concerns/omniauthable.rb rename to app/models/concerns/user/omniauthable.rb index 3983fbcda8756f..6d1d1b8cc3fbdc 100644 --- a/app/models/concerns/omniauthable.rb +++ b/app/models/concerns/user/omniauthable.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module Omniauthable +module User::Omniauthable extend ActiveSupport::Concern TEMP_EMAIL_PREFIX = 'change@me' diff --git a/app/models/concerns/pam_authenticable.rb b/app/models/concerns/user/pam_authenticable.rb similarity index 98% rename from app/models/concerns/pam_authenticable.rb rename to app/models/concerns/user/pam_authenticable.rb index f97f986a41fe08..a682058ccacd99 100644 --- a/app/models/concerns/pam_authenticable.rb +++ b/app/models/concerns/user/pam_authenticable.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module PamAuthenticable +module User::PamAuthenticable extend ActiveSupport::Concern included do diff --git a/app/models/status.rb b/app/models/status.rb index 41c8950296d0c9..7b1ca69c7c2506 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -30,14 +30,14 @@ # class Status < ApplicationRecord + include Cacheable include Discard::Model include Paginable - include Cacheable - include StatusThreadingConcern - include StatusSnapshotConcern include RateLimitable - include StatusSafeReblogInsert - include StatusSearchConcern + include Status::SafeReblogInsert + include Status::SearchConcern + include Status::SnapshotConcern + include Status::ThreadingConcern rate_limit by: :account, family: :statuses diff --git a/app/models/user.rb b/app/models/user.rb index b0eba97c3636b4..550f8bfd30cdf0 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -53,9 +53,12 @@ class User < ApplicationRecord filtered_languages ) - include Redisable include LanguagesHelper - include HasUserSettings + include Redisable + include User::HasSettings + include User::LdapAuthenticable + include User::Omniauthable + include User::PamAuthenticable # The home and list feeds will be stored in Redis for this amount # of time, and status fan-out to followers will include only people @@ -75,10 +78,6 @@ class User < ApplicationRecord devise :registerable, :recoverable, :validatable, :confirmable - include Omniauthable - include PamAuthenticable - include LdapAuthenticable - belongs_to :account, inverse_of: :user belongs_to :invite, counter_cache: :uses, optional: true belongs_to :created_by_application, class_name: 'Doorkeeper::Application', optional: true diff --git a/app/views/settings/profiles/show.html.haml b/app/views/settings/profiles/show.html.haml index 7c13dc7f44c64a..5f9613c9391171 100644 --- a/app/views/settings/profiles/show.html.haml +++ b/app/views/settings/profiles/show.html.haml @@ -33,7 +33,7 @@ .fields-row .fields-row__column.fields-row__column-6 .fields-group - = f.input :avatar, wrapper: :with_block_label, input_html: { accept: AccountAvatar::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.avatar', dimensions: '400x400', size: number_to_human_size(AccountAvatar::LIMIT)) + = f.input :avatar, wrapper: :with_block_label, input_html: { accept: Account::Avatar::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.avatar', dimensions: '400x400', size: number_to_human_size(Account::Avatar::LIMIT)) .fields-row__column.fields-row__column-6 .fields-group @@ -46,7 +46,7 @@ .fields-row .fields-row__column.fields-row__column-6 .fields-group - = f.input :header, wrapper: :with_block_label, input_html: { accept: AccountHeader::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.header', dimensions: '1500x500', size: number_to_human_size(AccountHeader::LIMIT)) + = f.input :header, wrapper: :with_block_label, input_html: { accept: Account::Header::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.header', dimensions: '1500x500', size: number_to_human_size(Account::Header::LIMIT)) .fields-row__column.fields-row__column-6 .fields-group diff --git a/lib/mastodon/cli/maintenance.rb b/lib/mastodon/cli/maintenance.rb index a95b7a30cdd29d..c53d742548c463 100644 --- a/lib/mastodon/cli/maintenance.rb +++ b/lib/mastodon/cli/maintenance.rb @@ -67,8 +67,8 @@ def acct local? ? username : "#{username}@#{domain}" end - # This is a duplicate of the AccountMerging concern because we need it to - # be independent from code version. + # This is a duplicate of the Account::Merging concern because we need it + # to be independent from code version. def merge_with!(other_account) # Since it's the same remote resource, the remote resource likely # already believes we are following/blocking, so it's safe to diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 9652ea1910fe55..522549125fe55b 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -451,7 +451,7 @@ end it 'limits via constant by default' do - stub_const('AccountSearch::DEFAULT_LIMIT', 1) + stub_const('Account::Search::DEFAULT_LIMIT', 1) 2.times.each { Fabricate(:account, display_name: 'Display Name') } results = described_class.search_for('display') expect(results.size).to eq 1 @@ -595,7 +595,7 @@ end it 'limits by 10 by default' do - stub_const('AccountSearch::DEFAULT_LIMIT', 1) + stub_const('Account::Search::DEFAULT_LIMIT', 1) 2.times { Fabricate(:account, display_name: 'Display Name') } results = described_class.advanced_search_for('display', account) expect(results.size).to eq 1 diff --git a/spec/models/concerns/account_counters_spec.rb b/spec/models/concerns/account/counters_spec.rb similarity index 98% rename from spec/models/concerns/account_counters_spec.rb rename to spec/models/concerns/account/counters_spec.rb index fb02d79f11831f..2e1cd700bc2a75 100644 --- a/spec/models/concerns/account_counters_spec.rb +++ b/spec/models/concerns/account/counters_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe AccountCounters do +describe Account::Counters do let!(:account) { Fabricate(:account) } describe '#increment_count!' do diff --git a/spec/models/concerns/account_finder_concern_spec.rb b/spec/models/concerns/account/finder_concern_spec.rb similarity index 98% rename from spec/models/concerns/account_finder_concern_spec.rb rename to spec/models/concerns/account/finder_concern_spec.rb index 3a94c4d54526f5..ab5149e987ff15 100644 --- a/spec/models/concerns/account_finder_concern_spec.rb +++ b/spec/models/concerns/account/finder_concern_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe AccountFinderConcern do +describe Account::FinderConcern do describe 'local finders' do let!(:account) { Fabricate(:account, username: 'Alice') } diff --git a/spec/models/concerns/account_interactions_spec.rb b/spec/models/concerns/account/interactions_spec.rb similarity index 99% rename from spec/models/concerns/account_interactions_spec.rb rename to spec/models/concerns/account/interactions_spec.rb index 6687c84436b50d..6fac41e07115eb 100644 --- a/spec/models/concerns/account_interactions_spec.rb +++ b/spec/models/concerns/account/interactions_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe AccountInteractions do +describe Account::Interactions do let(:account) { Fabricate(:account, username: 'account') } let(:account_id) { account.id } let(:account_ids) { [account_id] } diff --git a/spec/models/concerns/account_statuses_search_spec.rb b/spec/models/concerns/account/statuses_search_spec.rb similarity index 98% rename from spec/models/concerns/account_statuses_search_spec.rb rename to spec/models/concerns/account/statuses_search_spec.rb index 46362936f4a330..ab249d62d0756a 100644 --- a/spec/models/concerns/account_statuses_search_spec.rb +++ b/spec/models/concerns/account/statuses_search_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe AccountStatusesSearch do +describe Account::StatusesSearch do let(:account) { Fabricate(:account, indexable: indexable) } before do diff --git a/spec/models/concerns/status_threading_concern_spec.rb b/spec/models/concerns/status/threading_concern_spec.rb similarity index 99% rename from spec/models/concerns/status_threading_concern_spec.rb rename to spec/models/concerns/status/threading_concern_spec.rb index 2eac1ca6e5ceb4..09fb21856618a1 100644 --- a/spec/models/concerns/status_threading_concern_spec.rb +++ b/spec/models/concerns/status/threading_concern_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe StatusThreadingConcern do +describe Status::ThreadingConcern do describe '#ancestors' do let!(:alice) { Fabricate(:account, username: 'alice') } let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') } diff --git a/spec/search/models/concerns/account_search_spec.rb b/spec/search/models/concerns/account/search_spec.rb similarity index 98% rename from spec/search/models/concerns/account_search_spec.rb rename to spec/search/models/concerns/account/search_spec.rb index 65e1e4de1c9289..d8d7f355dd4bf3 100644 --- a/spec/search/models/concerns/account_search_spec.rb +++ b/spec/search/models/concerns/account/search_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe AccountSearch do +describe Account::Search do describe 'a non-discoverable account becoming discoverable' do let(:account) { Account.find_by(username: 'search_test_account_1') } diff --git a/spec/search/models/concerns/account_statuses_search_spec.rb b/spec/search/models/concerns/account/statuses_search_spec.rb similarity index 98% rename from spec/search/models/concerns/account_statuses_search_spec.rb rename to spec/search/models/concerns/account/statuses_search_spec.rb index d35cfa56392760..bf2606eecea67f 100644 --- a/spec/search/models/concerns/account_statuses_search_spec.rb +++ b/spec/search/models/concerns/account/statuses_search_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe AccountStatusesSearch do +describe Account::StatusesSearch do describe 'a non-indexable account becoming indexable' do let(:account) { Account.find_by(username: 'search_test_account_1') } From 272592d16d40e804ec325ef3b5e6de9bbad5f2dd Mon Sep 17 00:00:00 2001 From: Michael Stanclift Date: Fri, 1 Dec 2023 05:06:37 -0600 Subject: [PATCH 30/41] Change startup command for Puma in Docker Compose (#28138) --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index bcfa4c85f1bf3a..93451d9611036a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -59,7 +59,7 @@ services: image: ghcr.io/mastodon/mastodon:v4.2.0 restart: always env_file: .env.production - command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000" + command: bundle exec puma -C config/puma.rb networks: - external_network - internal_network From 92fa9b109f78647710c52d86fa777ab3972e2f1b Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 06:56:47 -0500 Subject: [PATCH 31/41] Add spec coverage for media CLI usage command (#28167) --- spec/lib/mastodon/cli/media_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/spec/lib/mastodon/cli/media_spec.rb b/spec/lib/mastodon/cli/media_spec.rb index 9543640e967667..305d67d28f0021 100644 --- a/spec/lib/mastodon/cli/media_spec.rb +++ b/spec/lib/mastodon/cli/media_spec.rb @@ -78,4 +78,16 @@ end end end + + describe '#usage' do + context 'without options' do + let(:options) { {} } + + it 'reports about storage size' do + expect { cli.invoke(:usage, [], options) }.to output( + a_string_including('0 Bytes') + ).to_stdout + end + end + end end From 7753e5f715ba105a8ec3dd335e8af4a9448aee63 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 07:00:34 -0500 Subject: [PATCH 32/41] Add shared example for CLI command specs (#28165) --- spec/lib/mastodon/cli/accounts_spec.rb | 8 ++------ spec/lib/mastodon/cli/cache_spec.rb | 6 +----- spec/lib/mastodon/cli/canonical_email_blocks_spec.rb | 6 +----- spec/lib/mastodon/cli/domains_spec.rb | 6 +----- spec/lib/mastodon/cli/email_domain_blocks_spec.rb | 6 +----- spec/lib/mastodon/cli/emoji_spec.rb | 6 +----- spec/lib/mastodon/cli/feeds_spec.rb | 6 +----- spec/lib/mastodon/cli/ip_blocks_spec.rb | 6 +----- spec/lib/mastodon/cli/main_spec.rb | 6 +----- spec/lib/mastodon/cli/maintenance_spec.rb | 6 +----- spec/lib/mastodon/cli/media_spec.rb | 6 +----- spec/lib/mastodon/cli/preview_cards_spec.rb | 6 +----- spec/lib/mastodon/cli/search_spec.rb | 6 +----- spec/lib/mastodon/cli/settings_spec.rb | 6 +----- spec/lib/mastodon/cli/statuses_spec.rb | 6 +----- spec/lib/mastodon/cli/upgrade_spec.rb | 6 +----- spec/support/examples/cli.rb | 11 +++++++++++ 17 files changed, 28 insertions(+), 81 deletions(-) create mode 100644 spec/support/examples/cli.rb diff --git a/spec/lib/mastodon/cli/accounts_spec.rb b/spec/lib/mastodon/cli/accounts_spec.rb index 626cf4778cde79..3216d0d1bd9f28 100644 --- a/spec/lib/mastodon/cli/accounts_spec.rb +++ b/spec/lib/mastodon/cli/accounts_spec.rb @@ -6,6 +6,8 @@ describe Mastodon::CLI::Accounts do let(:cli) { described_class.new } + it_behaves_like 'CLI Command' + # `parallelize_with_progress` cannot run in transactions, so instead, # stub it with an alternative implementation that runs sequentially # and can run in transactions. @@ -24,12 +26,6 @@ def stub_parallelize_with_progress! end end - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end - describe '#create' do shared_examples 'a new user with given email address and username' do it 'creates a new user with the specified email address' do diff --git a/spec/lib/mastodon/cli/cache_spec.rb b/spec/lib/mastodon/cli/cache_spec.rb index 3ab42dc8cee6f6..c1ce04710c735c 100644 --- a/spec/lib/mastodon/cli/cache_spec.rb +++ b/spec/lib/mastodon/cli/cache_spec.rb @@ -6,11 +6,7 @@ describe Mastodon::CLI::Cache do let(:cli) { described_class.new } - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' describe '#clear' do before { allow(Rails.cache).to receive(:clear) } diff --git a/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb b/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb index eb57a3cd15a6e5..6e4675748e1756 100644 --- a/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb +++ b/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb @@ -6,11 +6,7 @@ describe Mastodon::CLI::CanonicalEmailBlocks do let(:cli) { described_class.new } - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' describe '#find' do let(:arguments) { ['user@example.com'] } diff --git a/spec/lib/mastodon/cli/domains_spec.rb b/spec/lib/mastodon/cli/domains_spec.rb index ea58845c00bfe9..765b63e2a793d2 100644 --- a/spec/lib/mastodon/cli/domains_spec.rb +++ b/spec/lib/mastodon/cli/domains_spec.rb @@ -4,9 +4,5 @@ require 'mastodon/cli/domains' describe Mastodon::CLI::Domains do - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' end diff --git a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb index 333ae3f2b74510..060943b1881486 100644 --- a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb +++ b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb @@ -4,9 +4,5 @@ require 'mastodon/cli/email_domain_blocks' describe Mastodon::CLI::EmailDomainBlocks do - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' end diff --git a/spec/lib/mastodon/cli/emoji_spec.rb b/spec/lib/mastodon/cli/emoji_spec.rb index 9b586537299f16..5d109eb5247fb6 100644 --- a/spec/lib/mastodon/cli/emoji_spec.rb +++ b/spec/lib/mastodon/cli/emoji_spec.rb @@ -4,9 +4,5 @@ require 'mastodon/cli/emoji' describe Mastodon::CLI::Emoji do - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' end diff --git a/spec/lib/mastodon/cli/feeds_spec.rb b/spec/lib/mastodon/cli/feeds_spec.rb index 030f0872124b19..e16113c8546fdb 100644 --- a/spec/lib/mastodon/cli/feeds_spec.rb +++ b/spec/lib/mastodon/cli/feeds_spec.rb @@ -6,11 +6,7 @@ describe Mastodon::CLI::Feeds do let(:cli) { described_class.new } - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' describe '#build' do before { Fabricate(:account) } diff --git a/spec/lib/mastodon/cli/ip_blocks_spec.rb b/spec/lib/mastodon/cli/ip_blocks_spec.rb index 030d9fcb19e487..684314dc7ad8bc 100644 --- a/spec/lib/mastodon/cli/ip_blocks_spec.rb +++ b/spec/lib/mastodon/cli/ip_blocks_spec.rb @@ -6,11 +6,7 @@ describe Mastodon::CLI::IpBlocks do let(:cli) { described_class.new } - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' describe '#add' do let(:ip_list) do diff --git a/spec/lib/mastodon/cli/main_spec.rb b/spec/lib/mastodon/cli/main_spec.rb index e3709afe37adc0..b5b5d69062124b 100644 --- a/spec/lib/mastodon/cli/main_spec.rb +++ b/spec/lib/mastodon/cli/main_spec.rb @@ -4,11 +4,7 @@ require 'mastodon/cli/main' describe Mastodon::CLI::Main do - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' describe 'version' do it 'returns the Mastodon version' do diff --git a/spec/lib/mastodon/cli/maintenance_spec.rb b/spec/lib/mastodon/cli/maintenance_spec.rb index a6789ea5a41c46..95e695ab559641 100644 --- a/spec/lib/mastodon/cli/maintenance_spec.rb +++ b/spec/lib/mastodon/cli/maintenance_spec.rb @@ -6,11 +6,7 @@ describe Mastodon::CLI::Maintenance do let(:cli) { described_class.new } - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' describe '#fix_duplicates' do context 'when the database version is too old' do diff --git a/spec/lib/mastodon/cli/media_spec.rb b/spec/lib/mastodon/cli/media_spec.rb index 305d67d28f0021..15f84c14b842ef 100644 --- a/spec/lib/mastodon/cli/media_spec.rb +++ b/spec/lib/mastodon/cli/media_spec.rb @@ -6,11 +6,7 @@ describe Mastodon::CLI::Media do let(:cli) { described_class.new } - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' describe '#remove' do context 'with --prune-profiles and --remove-headers' do diff --git a/spec/lib/mastodon/cli/preview_cards_spec.rb b/spec/lib/mastodon/cli/preview_cards_spec.rb index 1e064ed58ed0cf..a766d250eb72f5 100644 --- a/spec/lib/mastodon/cli/preview_cards_spec.rb +++ b/spec/lib/mastodon/cli/preview_cards_spec.rb @@ -6,11 +6,7 @@ describe Mastodon::CLI::PreviewCards do let(:cli) { described_class.new } - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' describe '#remove' do context 'with relevant preview cards' do diff --git a/spec/lib/mastodon/cli/search_spec.rb b/spec/lib/mastodon/cli/search_spec.rb index d5cae5bf49f708..785dc2bd619d97 100644 --- a/spec/lib/mastodon/cli/search_spec.rb +++ b/spec/lib/mastodon/cli/search_spec.rb @@ -4,9 +4,5 @@ require 'mastodon/cli/search' describe Mastodon::CLI::Search do - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' end diff --git a/spec/lib/mastodon/cli/settings_spec.rb b/spec/lib/mastodon/cli/settings_spec.rb index ae58e74e56dbd2..7dcd1110baedb8 100644 --- a/spec/lib/mastodon/cli/settings_spec.rb +++ b/spec/lib/mastodon/cli/settings_spec.rb @@ -4,11 +4,7 @@ require 'mastodon/cli/settings' describe Mastodon::CLI::Settings do - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' describe 'subcommand "registrations"' do let(:cli) { Mastodon::CLI::Registrations.new } diff --git a/spec/lib/mastodon/cli/statuses_spec.rb b/spec/lib/mastodon/cli/statuses_spec.rb index 38ebcd99347103..70e4e2c086df6c 100644 --- a/spec/lib/mastodon/cli/statuses_spec.rb +++ b/spec/lib/mastodon/cli/statuses_spec.rb @@ -6,11 +6,7 @@ describe Mastodon::CLI::Statuses do let(:cli) { described_class.new } - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' describe '#remove', use_transactional_tests: false do context 'with small batch size' do diff --git a/spec/lib/mastodon/cli/upgrade_spec.rb b/spec/lib/mastodon/cli/upgrade_spec.rb index 9e0ab9d06e403a..817044f7eaca34 100644 --- a/spec/lib/mastodon/cli/upgrade_spec.rb +++ b/spec/lib/mastodon/cli/upgrade_spec.rb @@ -4,9 +4,5 @@ require 'mastodon/cli/upgrade' describe Mastodon::CLI::Upgrade do - describe '.exit_on_failure?' do - it 'returns true' do - expect(described_class.exit_on_failure?).to be true - end - end + it_behaves_like 'CLI Command' end diff --git a/spec/support/examples/cli.rb b/spec/support/examples/cli.rb new file mode 100644 index 00000000000000..091c842bd1aaec --- /dev/null +++ b/spec/support/examples/cli.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +shared_examples 'CLI Command' do + it 'configures Thor to exit on failure' do + expect(described_class.exit_on_failure?).to be true + end + + it 'descends from the CLI base class' do + expect(described_class.new).to be_a(Mastodon::CLI::Base) + end +end From 1564799952ec4b8039eecb28125493814bd56ed0 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 09:18:45 -0500 Subject: [PATCH 33/41] Add spec coverage for media CLI `refresh` command (#28166) --- lib/mastodon/cli/media.rb | 1 + spec/lib/mastodon/cli/media_spec.rb | 73 +++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/lib/mastodon/cli/media.rb b/lib/mastodon/cli/media.rb index c906161770a6ea..c3275b799f48c2 100644 --- a/lib/mastodon/cli/media.rb +++ b/lib/mastodon/cli/media.rb @@ -265,6 +265,7 @@ def refresh elsif options[:days].present? scope = MediaAttachment.remote else + say('Specify the source of media attachments', :red) exit(1) end diff --git a/spec/lib/mastodon/cli/media_spec.rb b/spec/lib/mastodon/cli/media_spec.rb index 15f84c14b842ef..6d510c1f5a4902 100644 --- a/spec/lib/mastodon/cli/media_spec.rb +++ b/spec/lib/mastodon/cli/media_spec.rb @@ -86,4 +86,77 @@ end end end + + describe '#refresh' do + context 'without any options' do + let(:options) { {} } + + it 'warns about usage and exits' do + expect { cli.invoke(:refresh, [], options) }.to output( + a_string_including('Specify the source') + ).to_stdout.and raise_error(SystemExit) + end + end + + context 'with --status option' do + before do + media_attachment.update(file_file_name: nil) + end + + let(:media_attachment) { Fabricate(:media_attachment, status: status, remote_url: 'https://host.example/asset.jpg') } + let(:options) { { status: status.id } } + let(:status) { Fabricate(:status) } + + it 'redownloads the attachment file' do + expect { cli.invoke(:refresh, [], options) }.to output( + a_string_including('Downloaded 1 media') + ).to_stdout + end + end + + context 'with --account option' do + context 'when the account does not exist' do + let(:options) { { account: 'not-real-user@example.host' } } + + it 'warns about usage and exits' do + expect { cli.invoke(:refresh, [], options) }.to output( + a_string_including('No such account') + ).to_stdout.and raise_error(SystemExit) + end + end + + context 'when the account exists' do + before do + media_attachment.update(file_file_name: nil) + end + + let(:media_attachment) { Fabricate(:media_attachment, account: account) } + let(:options) { { account: account.acct } } + let(:account) { Fabricate(:account) } + + it 'redownloads the attachment file' do + expect { cli.invoke(:refresh, [], options) }.to output( + a_string_including('Downloaded 1 media') + ).to_stdout + end + end + end + + context 'with --domain option' do + before do + media_attachment.update(file_file_name: nil) + end + + let(:domain) { 'example.host' } + let(:media_attachment) { Fabricate(:media_attachment, account: account) } + let(:options) { { domain: domain } } + let(:account) { Fabricate(:account, domain: domain) } + + it 'redownloads the attachment file' do + expect { cli.invoke(:refresh, [], options) }.to output( + a_string_including('Downloaded 1 media') + ).to_stdout + end + end + end end From f70f39dd04886c2ced6d424cdcb8690fcddd52f7 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 10:52:47 -0500 Subject: [PATCH 34/41] Add explicit `dependent: nil` to associations (#28169) --- .rubocop_todo.yml | 14 -------------- app/models/concerns/account/counters.rb | 2 +- app/models/conversation.rb | 2 +- app/models/custom_emoji.rb | 2 +- app/models/custom_emoji_category.rb | 2 +- app/models/domain_block.rb | 2 +- app/models/invite.rb | 2 +- app/models/status.rb | 14 +++++++++----- app/models/user.rb | 8 ++++---- app/models/web/push_subscription.rb | 2 +- 10 files changed, 20 insertions(+), 30 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 9fb163ceb9d23a..03543c8e0d23c9 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -112,20 +112,6 @@ Rails/HasAndBelongsToMany: - 'app/models/status.rb' - 'app/models/tag.rb' -# Configuration parameters: Include. -# Include: app/models/**/*.rb -Rails/HasManyOrHasOneDependent: - Exclude: - - 'app/models/concerns/account/counters.rb' - - 'app/models/conversation.rb' - - 'app/models/custom_emoji.rb' - - 'app/models/custom_emoji_category.rb' - - 'app/models/domain_block.rb' - - 'app/models/invite.rb' - - 'app/models/status.rb' - - 'app/models/user.rb' - - 'app/models/web/push_subscription.rb' - # Configuration parameters: Include. # Include: app/controllers/**/*.rb, app/mailers/**/*.rb Rails/LexicallyScopedActionFilter: diff --git a/app/models/concerns/account/counters.rb b/app/models/concerns/account/counters.rb index fb69be9b7004f3..4488398128aab5 100644 --- a/app/models/concerns/account/counters.rb +++ b/app/models/concerns/account/counters.rb @@ -6,7 +6,7 @@ module Account::Counters ALLOWED_COUNTER_KEYS = %i(statuses_count following_count followers_count).freeze included do - has_one :account_stat, inverse_of: :account + has_one :account_stat, inverse_of: :account, dependent: nil after_save :save_account_stat end diff --git a/app/models/conversation.rb b/app/models/conversation.rb index 5de2599627842d..a7fe1488407dce 100644 --- a/app/models/conversation.rb +++ b/app/models/conversation.rb @@ -13,7 +13,7 @@ class Conversation < ApplicationRecord validates :uri, uniqueness: true, if: :uri? - has_many :statuses + has_many :statuses, dependent: nil def local? uri.nil? diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb index 717de27723f770..97b1c63bf3732c 100644 --- a/app/models/custom_emoji.rb +++ b/app/models/custom_emoji.rb @@ -37,7 +37,7 @@ class CustomEmoji < ApplicationRecord belongs_to :category, class_name: 'CustomEmojiCategory', optional: true - has_one :local_counterpart, -> { where(domain: nil) }, class_name: 'CustomEmoji', primary_key: :shortcode, foreign_key: :shortcode, inverse_of: false + has_one :local_counterpart, -> { where(domain: nil) }, class_name: 'CustomEmoji', primary_key: :shortcode, foreign_key: :shortcode, inverse_of: false, dependent: nil has_attached_file :image, styles: { static: { format: 'png', convert_options: '-coalesce +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' } }, validate_media_type: false diff --git a/app/models/custom_emoji_category.rb b/app/models/custom_emoji_category.rb index 3c87f2b2e56444..f480746517d4ea 100644 --- a/app/models/custom_emoji_category.rb +++ b/app/models/custom_emoji_category.rb @@ -11,7 +11,7 @@ # class CustomEmojiCategory < ApplicationRecord - has_many :emojis, class_name: 'CustomEmoji', foreign_key: 'category_id', inverse_of: :category + has_many :emojis, class_name: 'CustomEmoji', foreign_key: 'category_id', inverse_of: :category, dependent: nil validates :name, presence: true, uniqueness: true end diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index a7af2d62e2d019..ff23f8fcc46449 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -25,7 +25,7 @@ class DomainBlock < ApplicationRecord validates :domain, presence: true, uniqueness: true, domain: true - has_many :accounts, foreign_key: :domain, primary_key: :domain, inverse_of: false + has_many :accounts, foreign_key: :domain, primary_key: :domain, inverse_of: false, dependent: nil delegate :count, to: :accounts, prefix: true scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) } diff --git a/app/models/invite.rb b/app/models/invite.rb index 8e816cef062e20..c0cbc584586196 100644 --- a/app/models/invite.rb +++ b/app/models/invite.rb @@ -20,7 +20,7 @@ class Invite < ApplicationRecord include Expireable belongs_to :user, inverse_of: :invites - has_many :users, inverse_of: :invite + has_many :users, inverse_of: :invite, dependent: nil scope :available, -> { where(expires_at: nil).or(where('expires_at >= ?', Time.now.utc)) } diff --git a/app/models/status.rb b/app/models/status.rb index 7b1ca69c7c2506..eb7159dc61e75a 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -66,12 +66,14 @@ class Status < ApplicationRecord has_many :bookmarks, inverse_of: :status, dependent: :destroy has_many :reblogs, foreign_key: 'reblog_of_id', class_name: 'Status', inverse_of: :reblog, dependent: :destroy has_many :reblogged_by_accounts, through: :reblogs, class_name: 'Account', source: :account - has_many :replies, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :thread + has_many :replies, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :thread, dependent: nil has_many :mentions, dependent: :destroy, inverse_of: :status has_many :mentioned_accounts, through: :mentions, source: :account, class_name: 'Account' - has_many :active_mentions, -> { active }, class_name: 'Mention', inverse_of: :status has_many :media_attachments, dependent: :nullify + # The `dependent` option is enabled by the initial `mentions` association declaration + has_many :active_mentions, -> { active }, class_name: 'Mention', inverse_of: :status # rubocop:disable Rails/HasManyOrHasOneDependent + # Those associations are used for the private search index has_many :local_mentioned, -> { merge(Account.local) }, through: :active_mentions, source: :account has_many :local_favorited, -> { merge(Account.local) }, through: :favourites, source: :account @@ -80,11 +82,13 @@ class Status < ApplicationRecord has_and_belongs_to_many :tags - has_one :preview_cards_status, inverse_of: :status # Because of a composite primary key, the dependent option cannot be used + # Because of a composite primary key, the `dependent` option cannot be used on this association + has_one :preview_cards_status, inverse_of: :status # rubocop:disable Rails/HasManyOrHasOneDependent + has_one :notification, as: :activity, dependent: :destroy - has_one :status_stat, inverse_of: :status + has_one :status_stat, inverse_of: :status, dependent: nil has_one :poll, inverse_of: :status, dependent: :destroy - has_one :trend, class_name: 'StatusTrend', inverse_of: :status + has_one :trend, class_name: 'StatusTrend', inverse_of: :status, dependent: nil validates :uri, uniqueness: true, presence: true, unless: :local? validates :text, presence: true, unless: -> { with_media? || reblog? } diff --git a/app/models/user.rb b/app/models/user.rb index 550f8bfd30cdf0..a1574c02ad86c9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -84,12 +84,12 @@ class User < ApplicationRecord belongs_to :role, class_name: 'UserRole', optional: true accepts_nested_attributes_for :account - has_many :applications, class_name: 'Doorkeeper::Application', as: :owner - has_many :backups, inverse_of: :user - has_many :invites, inverse_of: :user + has_many :applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: nil + has_many :backups, inverse_of: :user, dependent: nil + has_many :invites, inverse_of: :user, dependent: nil has_many :markers, inverse_of: :user, dependent: :destroy has_many :webauthn_credentials, dependent: :destroy - has_many :ips, class_name: 'UserIp', inverse_of: :user + has_many :ips, class_name: 'UserIp', inverse_of: :user, dependent: nil has_one :invite_request, class_name: 'UserInviteRequest', inverse_of: :user, dependent: :destroy accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? && !Setting.require_invite_text } diff --git a/app/models/web/push_subscription.rb b/app/models/web/push_subscription.rb index 0ffbe068eb0440..a3a2ec3f03eeb7 100644 --- a/app/models/web/push_subscription.rb +++ b/app/models/web/push_subscription.rb @@ -19,7 +19,7 @@ class Web::PushSubscription < ApplicationRecord belongs_to :user, optional: true belongs_to :access_token, class_name: 'Doorkeeper::AccessToken', optional: true - has_one :session_activation, foreign_key: 'web_push_subscription_id', inverse_of: :web_push_subscription + has_one :session_activation, foreign_key: 'web_push_subscription_id', inverse_of: :web_push_subscription, dependent: nil validates :endpoint, presence: true validates :key_p256dh, presence: true From a98fccf84e9deed1ea1aa52b5adbc0c1f0bdfaab Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 10:52:52 -0500 Subject: [PATCH 35/41] Fix `Style/SelfAssignment` cop (#28171) --- lib/mastodon/snowflake.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/snowflake.rb b/lib/mastodon/snowflake.rb index 0a596b29401270..ec4f6140ca40ad 100644 --- a/lib/mastodon/snowflake.rb +++ b/lib/mastodon/snowflake.rb @@ -99,7 +99,7 @@ def ensure_id_sequences_exist def id_at(timestamp, with_random: true) id = timestamp.to_i * 1000 id += rand(1000) if with_random - id = id << 16 + id <<= 16 id += rand(2**16) if with_random id end From d83d01eb1e2f2ae56cd3f3a40e254fcfec51360c Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 10:52:56 -0500 Subject: [PATCH 36/41] Fix `Lint/RedundantSafeNavigation` cop (#28172) --- app/controllers/api/v1/accounts_controller.rb | 2 +- app/models/trends/history.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 653529316fbb4e..be251b42594870 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -49,7 +49,7 @@ def block end def mute - MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: (params[:duration]&.to_i || 0)) + MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: params[:duration].to_i) render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships end diff --git a/app/models/trends/history.rb b/app/models/trends/history.rb index db368993372e4b..21331f00dca466 100644 --- a/app/models/trends/history.rb +++ b/app/models/trends/history.rb @@ -37,7 +37,7 @@ def accounts end def uses - with_redis { |redis| redis.get(key_for(:uses))&.to_i || 0 } + with_redis { |redis| redis.get(key_for(:uses)).to_i } end def add(account_id) From aa8563d43df93647db50e52eddccba63500e0c88 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 10:53:15 -0500 Subject: [PATCH 37/41] Fix `Style/SuperWithArgsParentheses` cop (#28174) --- spec/support/signed_request_helpers.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/support/signed_request_helpers.rb b/spec/support/signed_request_helpers.rb index 33d7dba6b87b90..eba4095e43870e 100644 --- a/spec/support/signed_request_helpers.rb +++ b/spec/support/signed_request_helpers.rb @@ -2,7 +2,7 @@ module SignedRequestHelpers def get(path, headers: nil, sign_with: nil, **args) - return super path, headers: headers, **args if sign_with.nil? + return super(path, headers: headers, **args) if sign_with.nil? headers ||= {} headers['Date'] = Time.now.utc.httpdate @@ -16,6 +16,6 @@ def get(path, headers: nil, sign_with: nil, **args) headers['Signature'] = "keyId=\"#{key_id}\",algorithm=\"rsa-sha256\",headers=\"#{signed_headers.keys.join(' ').downcase}\",signature=\"#{signature}\"" - super path, headers: headers, **args + super(path, headers: headers, **args) end end From 5631f139c1f6f923923a82f8c55d5ab0820a2788 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 10:53:35 -0500 Subject: [PATCH 38/41] Fix `Lint/SymbolConversion` cop (#28175) --- app/models/concerns/remotable.rb | 2 +- app/models/user_settings/setting.rb | 2 +- config/deploy.rb | 2 +- spec/models/concerns/remotable_spec.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb index cb8f46e688a5b3..bd8b6f4eb9a538 100644 --- a/app/models/concerns/remotable.rb +++ b/app/models/concerns/remotable.rb @@ -5,7 +5,7 @@ module Remotable class_methods do def remotable_attachment(attachment_name, limit, suppress_errors: true, download_on_assign: true, attribute_name: nil) - attribute_name ||= "#{attachment_name}_remote_url".to_sym + attribute_name ||= :"#{attachment_name}_remote_url" define_method("download_#{attachment_name}!") do |url = nil| url ||= self[attribute_name] diff --git a/app/models/user_settings/setting.rb b/app/models/user_settings/setting.rb index 9c17017440ca28..1ab6cbeab2d2cd 100644 --- a/app/models/user_settings/setting.rb +++ b/app/models/user_settings/setting.rb @@ -62,7 +62,7 @@ def to_a def key if namespace - "#{namespace}.#{name}".to_sym + :"#{namespace}.#{name}" else name end diff --git a/config/deploy.rb b/config/deploy.rb index b19567a729d3bb..75bfcc26f4a739 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -20,7 +20,7 @@ SYSTEMD_SERVICES.each do |service| SERVICE_ACTIONS.each do |action| desc "Perform a #{action} on #{service} service" - task "#{service}:#{action}".to_sym do + task :"#{service}:#{action}" do on roles(:app) do # runs e.g. "sudo restart mastodon-sidekiq.service" sudo :systemctl, action, "#{fetch(:application)}-#{service}.service" diff --git a/spec/models/concerns/remotable_spec.rb b/spec/models/concerns/remotable_spec.rb index db690da3c21f15..9f6aeb7fb4ead2 100644 --- a/spec/models/concerns/remotable_spec.rb +++ b/spec/models/concerns/remotable_spec.rb @@ -31,7 +31,7 @@ def self.attachment_definitions end end - let(:attribute_name) { "#{hoge}_remote_url".to_sym } + let(:attribute_name) { :"#{hoge}_remote_url" } let(:code) { 200 } let(:file) { 'filename="foo.txt"' } let(:foo) { foo_class.new } From 3bc437b99a19bba26c0c637b18ce6c7410d5a606 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 11:00:44 -0500 Subject: [PATCH 39/41] Fix `Style/RedundantParentheses` cop (#28176) --- app/controllers/api/base_controller.rb | 2 +- app/lib/feed_manager.rb | 4 ++-- lib/mastodon/cli/media.rb | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index c81ba32b08c086..b3c60fcaf4b1e5 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -64,7 +64,7 @@ class Api::BaseController < ApplicationController end def doorkeeper_unauthorized_render_options(error: nil) - { json: { error: (error.try(:description) || 'Not authorized') } } + { json: { error: error.try(:description) || 'Not authorized' } } end def doorkeeper_forbidden_render_options(*) diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 4e645a11f67519..53767486ff80aa 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -420,8 +420,8 @@ def filter_from_mentions?(status, receiver_id) check_for_blocks = status.active_mentions.pluck(:account_id) check_for_blocks.push(status.in_reply_to_account) if status.reply? && !status.in_reply_to_account_id.nil? - should_filter = blocks_or_mutes?(receiver_id, check_for_blocks, :mentions) # Filter if it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked (or muted) - should_filter ||= (status.account.silenced? && !Follow.where(account_id: receiver_id, target_account_id: status.account_id).exists?) # of if the account is silenced and I'm not following them + should_filter = blocks_or_mutes?(receiver_id, check_for_blocks, :mentions) # Filter if it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked (or muted) + should_filter ||= status.account.silenced? && !Follow.where(account_id: receiver_id, target_account_id: status.account_id).exists? # of if the account is silenced and I'm not following them should_filter end diff --git a/lib/mastodon/cli/media.rb b/lib/mastodon/cli/media.rb index c3275b799f48c2..a796bb729a73d6 100644 --- a/lib/mastodon/cli/media.rb +++ b/lib/mastodon/cli/media.rb @@ -48,8 +48,8 @@ def remove next if account.avatar.blank? && account.header.blank? next if options[:remove_headers] && account.header.blank? - size = (account.header_file_size || 0) - size += (account.avatar_file_size || 0) if options[:prune_profiles] + size = account.header_file_size || 0 + size += account.avatar_file_size || 0 if options[:prune_profiles] unless dry_run? account.header.destroy From 469ee2ae36d0c4b355fd5486c294133be75288a0 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 1 Dec 2023 11:07:19 -0500 Subject: [PATCH 40/41] Fix `Style/HashEachMethods` cop (#28173) --- db/seeds/03_roles.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/seeds/03_roles.rb b/db/seeds/03_roles.rb index 8b359582b537f8..95a989a95c70f8 100644 --- a/db/seeds/03_roles.rb +++ b/db/seeds/03_roles.rb @@ -6,6 +6,6 @@ # Create default roles defined in config file default_roles = YAML.load_file(Rails.root.join('config', 'roles.yml')) -default_roles.each do |_, config| +default_roles.each_value do |config| UserRole.create_with(position: config['position'], permissions_as_keys: config['permissions'], highlighted: true).find_or_create_by(name: config['name']) end From 456597dae5251af841e46ab0608e0d44a7de1197 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Dec 2023 17:22:15 +0100 Subject: [PATCH 41/41] Update dependency doorkeeper to v5.6.8 (#28177) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 40f85c7d484b14..4c78e6b0a89f0d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -245,7 +245,7 @@ GEM docile (1.4.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - doorkeeper (5.6.7) + doorkeeper (5.6.8) railties (>= 5) dotenv (2.8.1) dotenv-rails (2.8.1) @@ -617,7 +617,7 @@ GEM redlock (1.3.2) redis (>= 3.0.0, < 6.0) regexp_parser (2.8.2) - reline (0.4.0) + reline (0.4.1) io-console (~> 0.5) request_store (1.5.1) rack (>= 1.4)