diff --git a/.devcontainer/compose.yaml b/.devcontainer/compose.yaml index 705d26e0ab..4d5ed0f25f 100644 --- a/.devcontainer/compose.yaml +++ b/.devcontainer/compose.yaml @@ -10,6 +10,7 @@ services: RAILS_ENV: development NODE_ENV: development BIND: 0.0.0.0 + BOOTSNAP_CACHE_DIR: /tmp REDIS_HOST: redis REDIS_PORT: '6379' DB_HOST: db diff --git a/Dockerfile b/Dockerfile index deeac8b466..4e1bb24ff8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1.12 # This file is designed for production server deployment, not local development work -# For a containerized local dev environment, see: https://github.com/mastodon/mastodon/blob/main/README.md#docker +# For a containerized local dev environment, see: https://github.com/mastodon/mastodon/blob/main/docs/DEVELOPMENT.md#docker # Please see https://docs.docker.com/engine/reference/builder for information about # the extended buildx capabilities used in this file. @@ -9,6 +9,7 @@ # See: https://docs.docker.com/build/building/multi-platform/ ARG TARGETPLATFORM=${TARGETPLATFORM} ARG BUILDPLATFORM=${BUILDPLATFORM} +ARG BASE_REGISTRY="docker.io" # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.4.x"] # renovate: datasource=docker depName=docker.io/ruby @@ -19,9 +20,9 @@ ARG NODE_MAJOR_VERSION="22" # Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"] ARG DEBIAN_VERSION="bookworm" # Node image to use for base image based on combined variables (ex: 20-bookworm-slim) -FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node +FROM ${BASE_REGISTRY}/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node # Ruby image to use for base image based on combined variables (ex: 3.4.x-slim-bookworm) -FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby +FROM ${BASE_REGISTRY}/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby # Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA # Example: v4.3.0-nightly.2023.11.09+pr-123456 diff --git a/Gemfile b/Gemfile index 5becc118d3..89648e8cac 100644 --- a/Gemfile +++ b/Gemfile @@ -100,6 +100,8 @@ gem 'json-ld' gem 'json-ld-preloaded', '~> 3.2' gem 'rdf-normalize', '~> 0.5' +gem 'prometheus_exporter', '~> 2.2', require: false + gem 'opentelemetry-api', '~> 1.4.0' group :opentelemetry do diff --git a/Gemfile.lock b/Gemfile.lock index c67516feb2..8547e4fba1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -370,7 +370,7 @@ GEM marcel (~> 1.0.1) mime-types terrapin (>= 0.6.0, < 2.0) - language_server-protocol (3.17.0.3) + language_server-protocol (3.17.0.4) launchy (3.0.1) addressable (~> 2.8) childprocess (~> 5.0) @@ -530,7 +530,7 @@ GEM opentelemetry-instrumentation-rack (0.26.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-rails (0.35.0) + opentelemetry-instrumentation-rails (0.35.1) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-action_mailer (~> 0.4.0) opentelemetry-instrumentation-action_pack (~> 0.11.0) @@ -557,7 +557,7 @@ GEM opentelemetry-api (~> 1.0) orm_adapter (0.5.0) ostruct (0.6.1) - ox (2.14.20) + ox (2.14.21) bigdecimal (>= 3.0) parallel (1.26.3) parser (3.3.7.0) @@ -580,6 +580,8 @@ GEM net-smtp premailer (~> 1.7, >= 1.7.9) prettyprint (0.2.0) + prometheus_exporter (2.2.0) + webrick propshaft (1.1.0) actionpack (>= 7.0.0) activesupport (>= 7.0.0) @@ -714,7 +716,7 @@ GEM rspec-mocks (~> 3.0) sidekiq (>= 5, < 8) rspec-support (3.13.2) - rubocop (1.70.0) + rubocop (1.71.0) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) @@ -724,14 +726,14 @@ GEM rubocop-ast (>= 1.36.2, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.37.0) + rubocop-ast (1.38.0) parser (>= 3.3.1.0) rubocop-capybara (2.21.0) rubocop (~> 1.41) rubocop-performance (1.23.1) rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails (2.28.0) + rubocop-rails (2.29.1) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.52.0, < 2.0) @@ -984,6 +986,7 @@ DEPENDENCIES pg (~> 1.5) pghero premailer-rails + prometheus_exporter (~> 2.2) propshaft public_suffix (~> 6.0) puma (~> 6.3) diff --git a/app/controllers/admin/account_actions_controller.rb b/app/controllers/admin/account_actions_controller.rb index e674bf55a0..91849811e3 100644 --- a/app/controllers/admin/account_actions_controller.rb +++ b/app/controllers/admin/account_actions_controller.rb @@ -34,7 +34,8 @@ module Admin end def resource_params - params.require(:admin_account_action).permit(:type, :report_id, :warning_preset_id, :text, :send_email_notification, :include_statuses) + params + .expect(admin_account_action: [:type, :report_id, :warning_preset_id, :text, :send_email_notification, :include_statuses]) end end end diff --git a/app/controllers/admin/account_moderation_notes_controller.rb b/app/controllers/admin/account_moderation_notes_controller.rb index a3c4adf59a..7f65ced517 100644 --- a/app/controllers/admin/account_moderation_notes_controller.rb +++ b/app/controllers/admin/account_moderation_notes_controller.rb @@ -29,10 +29,8 @@ module Admin private def resource_params - params.require(:account_moderation_note).permit( - :content, - :target_account_id - ) + params + .expect(account_moderation_note: [:content, :target_account_id]) end def set_account_moderation_note diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb index a4d5018d0a..a779a0cf51 100644 --- a/app/controllers/admin/accounts_controller.rb +++ b/app/controllers/admin/accounts_controller.rb @@ -172,7 +172,8 @@ module Admin end def form_account_batch_params - params.require(:form_account_batch).permit(:action, account_ids: []) + params + .expect(form_account_batch: [:action, account_ids: []]) end def action_from_button diff --git a/app/controllers/admin/announcements_controller.rb b/app/controllers/admin/announcements_controller.rb index 12230a6506..eaf84aab25 100644 --- a/app/controllers/admin/announcements_controller.rb +++ b/app/controllers/admin/announcements_controller.rb @@ -84,6 +84,7 @@ class Admin::AnnouncementsController < Admin::BaseController end def resource_params - params.require(:announcement).permit(:text, :scheduled_at, :starts_at, :ends_at, :all_day) + params + .expect(announcement: [:text, :scheduled_at, :starts_at, :ends_at, :all_day]) end end diff --git a/app/controllers/admin/change_emails_controller.rb b/app/controllers/admin/change_emails_controller.rb index a689d3a530..c923b94b1a 100644 --- a/app/controllers/admin/change_emails_controller.rb +++ b/app/controllers/admin/change_emails_controller.rb @@ -41,9 +41,8 @@ module Admin end def resource_params - params.require(:user).permit( - :unconfirmed_email - ) + params + .expect(user: [:unconfirmed_email]) end end end diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb index 34368f08a2..596b167249 100644 --- a/app/controllers/admin/custom_emojis_controller.rb +++ b/app/controllers/admin/custom_emojis_controller.rb @@ -67,11 +67,13 @@ module Admin end def resource_params - params.require(:custom_emoji).permit(:shortcode, :image, :category_id, :visible_in_picker, :aliases_raw, :license) + params + .expect(custom_emoji: [:shortcode, :image, :category_id, :visible_in_picker, :aliases_raw, :license]) end def update_params - params.require(:custom_emoji).permit(:category_id, :visible_in_picker, :aliases_raw, :license) + params + .expect(custom_emoji: [:category_id, :visible_in_picker, :aliases_raw, :license]) end def filtered_custom_emojis @@ -101,7 +103,8 @@ module Admin end def form_custom_emoji_batch_params - params.require(:form_custom_emoji_batch).permit(:action, :category_id, :category_name, custom_emoji_ids: []) + params + .expect(form_custom_emoji_batch: [:action, :category_id, :category_name, custom_emoji_ids: []]) end end end diff --git a/app/controllers/admin/domain_allows_controller.rb b/app/controllers/admin/domain_allows_controller.rb index b0f139e3a8..913c1a8246 100644 --- a/app/controllers/admin/domain_allows_controller.rb +++ b/app/controllers/admin/domain_allows_controller.rb @@ -37,6 +37,7 @@ class Admin::DomainAllowsController < Admin::BaseController end def resource_params - params.require(:domain_allow).permit(:domain) + params + .expect(domain_allow: [:domain]) end end diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb index 78d2a2da28..520db814f2 100644 --- a/app/controllers/admin/domain_blocks_controller.rb +++ b/app/controllers/admin/domain_blocks_controller.rb @@ -35,7 +35,9 @@ module Admin rescue Mastodon::NotPermittedError flash[:alert] = I18n.t('admin.domain_blocks.not_permitted') else - redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg') + flash[:notice] = I18n.t('admin.domain_blocks.created_msg') + ensure + redirect_to admin_instances_path(limited: '1') end def new @@ -124,9 +126,14 @@ module Admin end def form_domain_block_batch_params - params.require(:form_domain_block_batch).permit(domain_blocks_attributes: [:enabled, :domain, :severity, :reject_media, :reject_favourite, :reject_reply_exclude_followers, - :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :reject_friend, :block_trends, :detect_invalid_subscription, - :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden]) + params + .expect( + form_domain_block_batch: [ + domain_blocks_attributes: [[:enabled, :domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate, + :reject_favourite, :reject_reply_exclude_followers, :reject_send_sensitive, :reject_hashtag, + :reject_straight_follow, :reject_new_follow, :reject_friend, :block_trends, :detect_invalid_subscription, :hidden]], + ] + ) end def action_from_button diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index 9501ebd63a..12f221164f 100644 --- a/app/controllers/admin/email_domain_blocks_controller.rb +++ b/app/controllers/admin/email_domain_blocks_controller.rb @@ -62,11 +62,13 @@ module Admin end def resource_params - params.require(:email_domain_block).permit(:domain, :allow_with_approval, other_domains: []) + params + .expect(email_domain_block: [:domain, :allow_with_approval, other_domains: []]) end def form_email_domain_block_batch_params - params.require(:form_email_domain_block_batch).permit(email_domain_block_ids: []) + params + .expect(form_email_domain_block_batch: [email_domain_block_ids: []]) end def action_from_button diff --git a/app/controllers/admin/follow_recommendations_controller.rb b/app/controllers/admin/follow_recommendations_controller.rb index a54e41bd8c..b060cfbe94 100644 --- a/app/controllers/admin/follow_recommendations_controller.rb +++ b/app/controllers/admin/follow_recommendations_controller.rb @@ -37,7 +37,8 @@ module Admin end def form_account_batch_params - params.require(:form_account_batch).permit(:action, account_ids: []) + params + .expect(form_account_batch: [:action, account_ids: []]) end def filter_params diff --git a/app/controllers/admin/friend_servers_controller.rb b/app/controllers/admin/friend_servers_controller.rb index 729d3b3912..ec41ba672c 100644 --- a/app/controllers/admin/friend_servers_controller.rb +++ b/app/controllers/admin/friend_servers_controller.rb @@ -79,11 +79,11 @@ module Admin end def resource_params - params.require(:friend_domain).permit(:domain, :inbox_url, :available, :pseudo_relay, :delivery_local, :unlocked, :allow_all_posts) + params.expect(friend_domain: [:domain, :inbox_url, :available, :pseudo_relay, :delivery_local, :unlocked, :allow_all_posts]) end def update_resource_params - params.require(:friend_domain).permit(:inbox_url, :available, :pseudo_relay, :delivery_local, :unlocked, :allow_all_posts) + params.expect(friend_domain: [:inbox_url, :available, :pseudo_relay, :delivery_local, :unlocked, :allow_all_posts]) end def warn_signatures_not_enabled! diff --git a/app/controllers/admin/invites_controller.rb b/app/controllers/admin/invites_controller.rb index 614e2a32d0..ac4ee35271 100644 --- a/app/controllers/admin/invites_controller.rb +++ b/app/controllers/admin/invites_controller.rb @@ -39,7 +39,8 @@ module Admin private def resource_params - params.require(:invite).permit(:max_uses, :expires_in) + params + .expect(invite: [:max_uses, :expires_in]) end def filtered_invites diff --git a/app/controllers/admin/ip_blocks_controller.rb b/app/controllers/admin/ip_blocks_controller.rb index 1bd7ec8059..afabda1b88 100644 --- a/app/controllers/admin/ip_blocks_controller.rb +++ b/app/controllers/admin/ip_blocks_controller.rb @@ -44,7 +44,8 @@ module Admin private def resource_params - params.require(:ip_block).permit(:ip, :severity, :comment, :expires_in) + params + .expect(ip_block: [:ip, :severity, :comment, :expires_in]) end def action_from_button @@ -52,7 +53,8 @@ module Admin end def form_ip_block_batch_params - params.require(:form_ip_block_batch).permit(ip_block_ids: []) + params + .expect(form_ip_block_batch: [ip_block_ids: []]) end end end diff --git a/app/controllers/admin/ng_rules_controller.rb b/app/controllers/admin/ng_rules_controller.rb index f37424cced..0bdda41c0c 100644 --- a/app/controllers/admin/ng_rules_controller.rb +++ b/app/controllers/admin/ng_rules_controller.rb @@ -82,16 +82,16 @@ module Admin end def resource_params - params.require(:ng_rule).permit(:title, :expires_in, :available, :account_domain, :account_username, :account_display_name, - :account_note, :account_field_name, :account_field_value, :account_avatar_state, - :account_header_state, :account_include_local, :status_spoiler_text, :status_text, :status_tag, - :status_sensitive_state, :status_cw_state, :status_media_state, :status_poll_state, - :status_mention_state, :status_reference_state, - :status_quote_state, :status_reply_state, :status_media_threshold, :status_poll_threshold, - :status_mention_threshold, :status_allow_follower_mention, - :reaction_allow_follower, :emoji_reaction_name, :emoji_reaction_origin_domain, - :status_reference_threshold, :account_allow_followed_by_local, :record_history_also_local, - status_visibility: [], status_searchability: [], reaction_type: []) + params.expect(ng_rule: [:title, :expires_in, :available, :account_domain, :account_username, :account_display_name, + :account_note, :account_field_name, :account_field_value, :account_avatar_state, + :account_header_state, :account_include_local, :status_spoiler_text, :status_text, :status_tag, + :status_sensitive_state, :status_cw_state, :status_media_state, :status_poll_state, + :status_mention_state, :status_reference_state, + :status_quote_state, :status_reply_state, :status_media_threshold, :status_poll_threshold, + :status_mention_threshold, :status_allow_follower_mention, + :reaction_allow_follower, :emoji_reaction_name, :emoji_reaction_origin_domain, + :status_reference_threshold, :account_allow_followed_by_local, :record_history_also_local, + status_visibility: [], status_searchability: [], reaction_type: []]) end def test_words! diff --git a/app/controllers/admin/ng_words_controller.rb b/app/controllers/admin/ng_words_controller.rb index a70a435fa4..f052843475 100644 --- a/app/controllers/admin/ng_words_controller.rb +++ b/app/controllers/admin/ng_words_controller.rb @@ -36,7 +36,7 @@ module Admin private def settings_params - params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS) + params.expect(form_admin_settings: [*Form::AdminSettings::KEYS]) end def settings_params_test diff --git a/app/controllers/admin/relays_controller.rb b/app/controllers/admin/relays_controller.rb index f05255adb6..9a796949de 100644 --- a/app/controllers/admin/relays_controller.rb +++ b/app/controllers/admin/relays_controller.rb @@ -57,7 +57,8 @@ module Admin end def resource_params - params.require(:relay).permit(:inbox_url) + params + .expect(relay: [:inbox_url]) end def warn_signatures_not_enabled! diff --git a/app/controllers/admin/report_notes_controller.rb b/app/controllers/admin/report_notes_controller.rb index 6b16c29fc7..10dbe846e4 100644 --- a/app/controllers/admin/report_notes_controller.rb +++ b/app/controllers/admin/report_notes_controller.rb @@ -47,10 +47,8 @@ module Admin end def resource_params - params.require(:report_note).permit( - :content, - :report_id - ) + params + .expect(report_note: [:content, :report_id]) end def set_report_note diff --git a/app/controllers/admin/roles_controller.rb b/app/controllers/admin/roles_controller.rb index bcfc11159c..2f9af8a6fc 100644 --- a/app/controllers/admin/roles_controller.rb +++ b/app/controllers/admin/roles_controller.rb @@ -61,7 +61,8 @@ module Admin end def resource_params - params.require(:user_role).permit(:name, :color, :highlighted, :position, permissions_as_keys: []) + params + .expect(user_role: [:name, :color, :highlighted, :position, permissions_as_keys: []]) end end end diff --git a/app/controllers/admin/rules_controller.rb b/app/controllers/admin/rules_controller.rb index b8def22ba3..289b6a98c3 100644 --- a/app/controllers/admin/rules_controller.rb +++ b/app/controllers/admin/rules_controller.rb @@ -53,7 +53,8 @@ module Admin end def resource_params - params.require(:rule).permit(:text, :hint, :priority) + params + .expect(rule: [:text, :hint, :priority]) end end end diff --git a/app/controllers/admin/sensitive_words_controller.rb b/app/controllers/admin/sensitive_words_controller.rb index 24cdd4efcb..716dcc708a 100644 --- a/app/controllers/admin/sensitive_words_controller.rb +++ b/app/controllers/admin/sensitive_words_controller.rb @@ -37,7 +37,7 @@ module Admin end def settings_params - params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS) + params.expect(form_admin_settings: [*Form::AdminSettings::KEYS]) end def settings_params_test diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index 338a3638c4..2ae5ec8255 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -28,7 +28,8 @@ module Admin end def settings_params - params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS) + params + .expect(form_admin_settings: [*Form::AdminSettings::KEYS]) end end end diff --git a/app/controllers/admin/special_domains_controller.rb b/app/controllers/admin/special_domains_controller.rb index 0ddbf26786..b36fe28d6e 100644 --- a/app/controllers/admin/special_domains_controller.rb +++ b/app/controllers/admin/special_domains_controller.rb @@ -28,7 +28,7 @@ module Admin end def settings_params - params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS) + params.expect(form_admin_settings: [*Form::AdminSettings::KEYS]) end end end diff --git a/app/controllers/admin/special_instances_controller.rb b/app/controllers/admin/special_instances_controller.rb index 3fd35d474e..a16bae13ef 100644 --- a/app/controllers/admin/special_instances_controller.rb +++ b/app/controllers/admin/special_instances_controller.rb @@ -28,7 +28,7 @@ module Admin end def settings_params - params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS) + params.expect(form_admin_settings: [*Form::AdminSettings::KEYS]) end end end diff --git a/app/controllers/admin/statuses_controller.rb b/app/controllers/admin/statuses_controller.rb index 047f79e04b..956950fe0d 100644 --- a/app/controllers/admin/statuses_controller.rb +++ b/app/controllers/admin/statuses_controller.rb @@ -98,7 +98,8 @@ module Admin helper_method :batched_ordered_status_edits def admin_status_batch_action_params - params.require(:admin_status_batch_action).permit(status_ids: []) + params + .expect(admin_status_batch_action: [status_ids: []]) end def after_create_redirect_path diff --git a/app/controllers/admin/tags_controller.rb b/app/controllers/admin/tags_controller.rb index 4759d15bc4..a7bfd64794 100644 --- a/app/controllers/admin/tags_controller.rb +++ b/app/controllers/admin/tags_controller.rb @@ -37,7 +37,8 @@ module Admin end def tag_params - params.require(:tag).permit(:name, :display_name, :trendable, :usable, :listable) + params + .expect(tag: [:name, :display_name, :trendable, :usable, :listable]) end def filtered_tags diff --git a/app/controllers/admin/terms_of_service/drafts_controller.rb b/app/controllers/admin/terms_of_service/drafts_controller.rb index 5d32c0bd83..02cb05946f 100644 --- a/app/controllers/admin/terms_of_service/drafts_controller.rb +++ b/app/controllers/admin/terms_of_service/drafts_controller.rb @@ -31,6 +31,7 @@ class Admin::TermsOfService::DraftsController < Admin::BaseController end def resource_params - params.require(:terms_of_service).permit(:text, :changelog) + params + .expect(terms_of_service: [:text, :changelog]) end end diff --git a/app/controllers/admin/terms_of_service/generates_controller.rb b/app/controllers/admin/terms_of_service/generates_controller.rb index 28037674a3..0edc87893e 100644 --- a/app/controllers/admin/terms_of_service/generates_controller.rb +++ b/app/controllers/admin/terms_of_service/generates_controller.rb @@ -32,6 +32,7 @@ class Admin::TermsOfService::GeneratesController < Admin::BaseController end def resource_params - params.require(:terms_of_service_generator).permit(*TermsOfService::Generator::VARIABLES) + params + .expect(terms_of_service_generator: [*TermsOfService::Generator::VARIABLES]) end end diff --git a/app/controllers/admin/trends/links/preview_card_providers_controller.rb b/app/controllers/admin/trends/links/preview_card_providers_controller.rb index 5e4b4084f8..5a650d5d8c 100644 --- a/app/controllers/admin/trends/links/preview_card_providers_controller.rb +++ b/app/controllers/admin/trends/links/preview_card_providers_controller.rb @@ -31,7 +31,8 @@ class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseControll end def trends_preview_card_provider_batch_params - params.require(:trends_preview_card_provider_batch).permit(:action, preview_card_provider_ids: []) + params + .expect(trends_preview_card_provider_batch: [:action, preview_card_provider_ids: []]) end def action_from_button diff --git a/app/controllers/admin/trends/links_controller.rb b/app/controllers/admin/trends/links_controller.rb index 65eca11c7f..68aa73c992 100644 --- a/app/controllers/admin/trends/links_controller.rb +++ b/app/controllers/admin/trends/links_controller.rb @@ -31,7 +31,8 @@ class Admin::Trends::LinksController < Admin::BaseController end def trends_preview_card_batch_params - params.require(:trends_preview_card_batch).permit(:action, preview_card_ids: []) + params + .expect(trends_preview_card_batch: [:action, preview_card_ids: []]) end def action_from_button diff --git a/app/controllers/admin/trends/statuses_controller.rb b/app/controllers/admin/trends/statuses_controller.rb index 682fe70bb5..873d777fe3 100644 --- a/app/controllers/admin/trends/statuses_controller.rb +++ b/app/controllers/admin/trends/statuses_controller.rb @@ -31,7 +31,8 @@ class Admin::Trends::StatusesController < Admin::BaseController end def trends_status_batch_params - params.require(:trends_status_batch).permit(:action, status_ids: []) + params + .expect(trends_status_batch: [:action, status_ids: []]) end def action_from_button diff --git a/app/controllers/admin/trends/tags_controller.rb b/app/controllers/admin/trends/tags_controller.rb index fcd23fbf66..1ccd740686 100644 --- a/app/controllers/admin/trends/tags_controller.rb +++ b/app/controllers/admin/trends/tags_controller.rb @@ -31,7 +31,8 @@ class Admin::Trends::TagsController < Admin::BaseController end def trends_tag_batch_params - params.require(:trends_tag_batch).permit(:action, tag_ids: []) + params + .expect(trends_tag_batch: [:action, tag_ids: []]) end def action_from_button diff --git a/app/controllers/admin/users/roles_controller.rb b/app/controllers/admin/users/roles_controller.rb index f5dfc643d4..e8b58de504 100644 --- a/app/controllers/admin/users/roles_controller.rb +++ b/app/controllers/admin/users/roles_controller.rb @@ -28,7 +28,8 @@ module Admin end def resource_params - params.require(:user).permit(:role_id) + params + .expect(user: [:role_id]) end end end diff --git a/app/controllers/admin/warning_presets_controller.rb b/app/controllers/admin/warning_presets_controller.rb index efbf65b119..dcf88294ee 100644 --- a/app/controllers/admin/warning_presets_controller.rb +++ b/app/controllers/admin/warning_presets_controller.rb @@ -52,7 +52,8 @@ module Admin end def warning_preset_params - params.require(:account_warning_preset).permit(:title, :text) + params + .expect(account_warning_preset: [:title, :text]) end end end diff --git a/app/controllers/admin/webhooks_controller.rb b/app/controllers/admin/webhooks_controller.rb index f1aad7c4b5..31db369637 100644 --- a/app/controllers/admin/webhooks_controller.rb +++ b/app/controllers/admin/webhooks_controller.rb @@ -74,7 +74,8 @@ module Admin end def resource_params - params.require(:webhook).permit(:url, :template, events: []) + params + .expect(webhook: [:url, :template, events: []]) end end end diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index 18603a32f2..eb8ac38da9 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -73,7 +73,7 @@ class Auth::SessionsController < Devise::SessionsController end def user_params - params.require(:user).permit(:email, :password, :otp_attempt, :disable_css, credential: {}) + params.expect(user: [:email, :password, :otp_attempt, :disable_css, credential: {}]) end def login_page_params diff --git a/app/controllers/concerns/admin/export_controller_concern.rb b/app/controllers/concerns/admin/export_controller_concern.rb index 6228ae67fe..ce03b2a24a 100644 --- a/app/controllers/concerns/admin/export_controller_concern.rb +++ b/app/controllers/concerns/admin/export_controller_concern.rb @@ -24,6 +24,6 @@ module Admin::ExportControllerConcern end def import_params - params.require(:admin_import).permit(:data) + params.expect(admin_import: [:data]) end end diff --git a/app/controllers/concerns/challengable_concern.rb b/app/controllers/concerns/challengable_concern.rb index c8d1a0bef7..7fbc469bdf 100644 --- a/app/controllers/concerns/challengable_concern.rb +++ b/app/controllers/concerns/challengable_concern.rb @@ -58,6 +58,6 @@ module ChallengableConcern end def challenge_params - params.require(:form_challenge).permit(:current_password, :return_to) + params.expect(form_challenge: [:current_password, :return_to]) end end diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb index 4ae63632c0..5f7ef8dd63 100644 --- a/app/controllers/concerns/signature_verification.rb +++ b/app/controllers/concerns/signature_verification.rb @@ -117,7 +117,7 @@ module SignatureVerification def verify_signature_strength! raise SignatureVerificationError, 'Mastodon requires the Date header or (created) pseudo-header to be signed' unless signed_headers.include?('date') || signed_headers.include?('(created)') - raise SignatureVerificationError, 'Mastodon requires the Digest header or (request-target) pseudo-header to be signed' unless signed_headers.include?(Request::REQUEST_TARGET) || signed_headers.include?('digest') + raise SignatureVerificationError, 'Mastodon requires the Digest header or (request-target) pseudo-header to be signed' unless signed_headers.include?(HttpSignatureDraft::REQUEST_TARGET) || signed_headers.include?('digest') raise SignatureVerificationError, 'Mastodon requires the Host header to be signed when doing a GET request' if request.get? && !signed_headers.include?('host') raise SignatureVerificationError, 'Mastodon requires the Digest header to be signed when doing a POST request' if request.post? && !signed_headers.include?('digest') end @@ -155,14 +155,14 @@ module SignatureVerification def build_signed_string(include_query_string: true) signed_headers.map do |signed_header| case signed_header - when Request::REQUEST_TARGET + when HttpSignatureDraft::REQUEST_TARGET if include_query_string - "#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.original_fullpath}" + "#{HttpSignatureDraft::REQUEST_TARGET}: #{request.method.downcase} #{request.original_fullpath}" else # Current versions of Mastodon incorrectly omit the query string from the (request-target) pseudo-header. # Therefore, temporarily support such incorrect signatures for compatibility. # TODO: remove eventually some time after release of the fixed version - "#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}" + "#{HttpSignatureDraft::REQUEST_TARGET}: #{request.method.downcase} #{request.path}" end when '(created)' raise SignatureVerificationError, 'Invalid pseudo-header (created) for rsa-sha256' unless signature_algorithm == 'hs2019' diff --git a/app/controllers/filters/statuses_controller.rb b/app/controllers/filters/statuses_controller.rb index 7ada13f680..ca5205d042 100644 --- a/app/controllers/filters/statuses_controller.rb +++ b/app/controllers/filters/statuses_controller.rb @@ -34,7 +34,7 @@ class Filters::StatusesController < ApplicationController end def status_filter_batch_action_params - params.require(:form_status_filter_batch_action).permit(status_filter_ids: []) + params.expect(form_status_filter_batch_action: [status_filter_ids: []]) end def action_from_button diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb index d351afcfb7..43105d70c8 100644 --- a/app/controllers/relationships_controller.rb +++ b/app/controllers/relationships_controller.rb @@ -36,7 +36,7 @@ class RelationshipsController < ApplicationController end def form_account_batch_params - params.require(:form_account_batch).permit(:action, account_ids: []) + params.expect(form_account_batch: [:action, account_ids: []]) end def following_relationship? diff --git a/app/controllers/settings/applications_controller.rb b/app/controllers/settings/applications_controller.rb index d6573f9b49..9785a1b90f 100644 --- a/app/controllers/settings/applications_controller.rb +++ b/app/controllers/settings/applications_controller.rb @@ -60,16 +60,12 @@ class Settings::ApplicationsController < Settings::BaseController end def application_params - params.require(:doorkeeper_application).permit( - :name, - :redirect_uri, - :scopes, - :website - ) + params + .expect(doorkeeper_application: [:name, :redirect_uri, :scopes, :website]) end def prepare_scopes - scopes = params.fetch(:doorkeeper_application, {}).fetch(:scopes, nil) + scopes = application_params.fetch(:doorkeeper_application, {}).fetch(:scopes, nil) params[:doorkeeper_application][:scopes] = scopes.join(' ') if scopes.is_a? Array end end diff --git a/app/controllers/settings/preferences/base_controller.rb b/app/controllers/settings/preferences/base_controller.rb index d3e62fb5d9..c2e705da3c 100644 --- a/app/controllers/settings/preferences/base_controller.rb +++ b/app/controllers/settings/preferences/base_controller.rb @@ -25,10 +25,10 @@ class Settings::Preferences::BaseController < Settings::BaseController end def original_user_params - params.require(:user).permit(:locale, :time_zone, :custom_css_text, chosen_languages: [], settings_attributes: UserSettings.keys) + params.expect(user: [:locale, :time_zone, :custom_css_text, chosen_languages: [], settings_attributes: UserSettings.keys]) end def disabled_visibilities_params - params.require(:user).permit(settings_attributes: { enabled_visibilities: [] }) + params.expect(user: [settings_attributes: { enabled_visibilities: [] }]) end end diff --git a/app/controllers/settings/privacy_extra_controller.rb b/app/controllers/settings/privacy_extra_controller.rb index 54cedf2c4b..f1292e644c 100644 --- a/app/controllers/settings/privacy_extra_controller.rb +++ b/app/controllers/settings/privacy_extra_controller.rb @@ -18,7 +18,7 @@ class Settings::PrivacyExtraController < Settings::BaseController private def account_params - params.require(:account).permit(settings: UserSettings.keys) + params.expect(account: [settings: UserSettings.keys]) end def set_account diff --git a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb index 1a0afe58b0..eae990e79b 100644 --- a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb +++ b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb @@ -38,7 +38,7 @@ module Settings private def confirmation_params - params.require(:form_two_factor_confirmation).permit(:otp_attempt) + params.expect(form_two_factor_confirmation: [:otp_attempt]) end def prepare_two_factor_form diff --git a/app/controllers/settings/verifications_controller.rb b/app/controllers/settings/verifications_controller.rb index 9cc60ba2e8..bed29dbeec 100644 --- a/app/controllers/settings/verifications_controller.rb +++ b/app/controllers/settings/verifications_controller.rb @@ -18,7 +18,7 @@ class Settings::VerificationsController < Settings::BaseController private def account_params - params.require(:account).permit(:attribution_domains).tap do |params| + params.expect(account: [:attribution_domains]).tap do |params| params[:attribution_domains] = params[:attribution_domains].split if params[:attribution_domains] end end diff --git a/app/javascript/hooks/useSelectableClick.ts b/app/javascript/hooks/useSelectableClick.ts new file mode 100644 index 0000000000..c8f16f0b0f --- /dev/null +++ b/app/javascript/hooks/useSelectableClick.ts @@ -0,0 +1,55 @@ +import { useRef, useCallback } from 'react'; + +type Position = [number, number]; + +export const useSelectableClick = ( + onClick: React.MouseEventHandler, + maxDelta = 5, +) => { + const clickPositionRef = useRef(null); + + const handleMouseDown = useCallback((e: React.MouseEvent) => { + clickPositionRef.current = [e.clientX, e.clientY]; + }, []); + + const handleMouseUp = useCallback( + (e: React.MouseEvent) => { + if (!clickPositionRef.current) { + return; + } + + const [startX, startY] = clickPositionRef.current; + const [deltaX, deltaY] = [ + Math.abs(e.clientX - startX), + Math.abs(e.clientY - startY), + ]; + + let element: EventTarget | null = e.target; + + while (element && element instanceof HTMLElement) { + if ( + element.localName === 'button' || + element.localName === 'a' || + element.localName === 'label' + ) { + return; + } + + element = element.parentNode; + } + + if ( + deltaX + deltaY < maxDelta && + (e.button === 0 || e.button === 1) && + e.detail >= 1 + ) { + onClick(e); + } + + clickPositionRef.current = null; + }, + [maxDelta, onClick], + ); + + return [handleMouseDown, handleMouseUp] as const; +}; diff --git a/app/javascript/mastodon/components/alt_text_badge.tsx b/app/javascript/mastodon/components/alt_text_badge.tsx index 99bec1ee51..466c5cf1bc 100644 --- a/app/javascript/mastodon/components/alt_text_badge.tsx +++ b/app/javascript/mastodon/components/alt_text_badge.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback, useRef } from 'react'; +import { useState, useCallback, useRef, useId } from 'react'; import { FormattedMessage } from 'react-intl'; @@ -8,12 +8,15 @@ import type { UsePopperOptions, } from 'react-overlays/esm/usePopper'; +import { useSelectableClick } from '@/hooks/useSelectableClick'; + const offset = [0, 4] as OffsetValue; const popperConfig = { strategy: 'fixed' } as UsePopperOptions; export const AltTextBadge: React.FC<{ description: string; }> = ({ description }) => { + const accessibilityId = useId(); const anchorRef = useRef(null); const [open, setOpen] = useState(false); @@ -25,12 +28,16 @@ export const AltTextBadge: React.FC<{ setOpen(false); }, [setOpen]); + const [handleMouseDown, handleMouseUp] = useSelectableClick(handleClose); + return ( <> @@ -47,9 +54,12 @@ export const AltTextBadge: React.FC<{ > {({ props }) => (
-