From 86500e3312394de52413254e81bbc91f1a9333a0 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 04:08:07 -0500 Subject: [PATCH 01/53] Extract scenic view model common methods to concern (#28111) --- app/models/account_summary.rb | 14 +++--------- app/models/concerns/database_view_record.rb | 25 +++++++++++++++++++++ app/models/follow_recommendation.rb | 12 ++-------- app/models/instance.rb | 10 ++------- app/models/user_ip.rb | 6 ++--- 5 files changed, 34 insertions(+), 33 deletions(-) create mode 100644 app/models/concerns/database_view_record.rb diff --git a/app/models/account_summary.rb b/app/models/account_summary.rb index 30ada50cc02932..327c0ef305ab7c 100644 --- a/app/models/account_summary.rb +++ b/app/models/account_summary.rb @@ -10,21 +10,13 @@ # class AccountSummary < ApplicationRecord + include DatabaseViewRecord + self.primary_key = :account_id - has_many :follow_recommendation_suppressions, primary_key: :account_id, foreign_key: :account_id, inverse_of: false + has_many :follow_recommendation_suppressions, primary_key: :account_id, foreign_key: :account_id, inverse_of: false, dependent: nil scope :safe, -> { where(sensitive: false) } scope :localized, ->(locale) { order(Arel::Nodes::Case.new.when(arel_table[:language].eq(locale)).then(1).else(0).desc) } scope :filtered, -> { where.missing(:follow_recommendation_suppressions) } - - def self.refresh - Scenic.database.refresh_materialized_view(table_name, concurrently: true, cascade: false) - rescue ActiveRecord::StatementInvalid - Scenic.database.refresh_materialized_view(table_name, concurrently: false, cascade: false) - end - - def readonly? - true - end end diff --git a/app/models/concerns/database_view_record.rb b/app/models/concerns/database_view_record.rb new file mode 100644 index 00000000000000..8b6672e2991a4c --- /dev/null +++ b/app/models/concerns/database_view_record.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module DatabaseViewRecord + extend ActiveSupport::Concern + + class_methods do + def refresh + Scenic.database.refresh_materialized_view( + table_name, + concurrently: true, + cascade: false + ) + rescue ActiveRecord::StatementInvalid + Scenic.database.refresh_materialized_view( + table_name, + concurrently: false, + cascade: false + ) + end + end + + def readonly? + true + end +end diff --git a/app/models/follow_recommendation.rb b/app/models/follow_recommendation.rb index 6b49a3ca660170..7ac9e6dfb95743 100644 --- a/app/models/follow_recommendation.rb +++ b/app/models/follow_recommendation.rb @@ -10,6 +10,8 @@ # class FollowRecommendation < ApplicationRecord + include DatabaseViewRecord + self.primary_key = :account_id self.table_name = :global_follow_recommendations @@ -17,14 +19,4 @@ class FollowRecommendation < ApplicationRecord belongs_to :account scope :localized, ->(locale) { joins(:account_summary).merge(AccountSummary.localized(locale)) } - - def self.refresh - Scenic.database.refresh_materialized_view(table_name, concurrently: true, cascade: false) - rescue ActiveRecord::StatementInvalid - Scenic.database.refresh_materialized_view(table_name, concurrently: false, cascade: false) - end - - def readonly? - true - end end diff --git a/app/models/instance.rb b/app/models/instance.rb index 0fd31c8097cab6..3bd4b924ae73c3 100644 --- a/app/models/instance.rb +++ b/app/models/instance.rb @@ -9,6 +9,8 @@ # class Instance < ApplicationRecord + include DatabaseViewRecord + self.primary_key = :domain attr_accessor :failure_days @@ -27,10 +29,6 @@ class Instance < ApplicationRecord scope :by_domain_and_subdomains, ->(domain) { where("reverse('.' || domain) LIKE reverse(?)", "%.#{domain}") } scope :with_domain_follows, ->(domains) { where(domain: domains).where(domain_account_follows) } - def self.refresh - Scenic.database.refresh_materialized_view(table_name, concurrently: true, cascade: false) - end - def self.domain_account_follows Arel.sql( <<~SQL.squish @@ -44,10 +42,6 @@ def self.domain_account_follows ) end - def readonly? - true - end - def delivery_failure_tracker @delivery_failure_tracker ||= DeliveryFailureTracker.new(domain) end diff --git a/app/models/user_ip.rb b/app/models/user_ip.rb index 38287c2a607a58..87b86a24d43f9a 100644 --- a/app/models/user_ip.rb +++ b/app/models/user_ip.rb @@ -10,11 +10,9 @@ # class UserIp < ApplicationRecord + include DatabaseViewRecord + self.primary_key = :user_id belongs_to :user - - def readonly? - true - end end From f00ba02653ef4e654571e8942b404fcd925662b1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:20:23 +0100 Subject: [PATCH 02/53] Update dependency nokogiri to v1.16.2 [SECURITY] (#29106) 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 01f5b4592947dc..7c10a419ada8dc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -465,7 +465,7 @@ GEM net-smtp (0.4.0.1) net-protocol nio4r (2.5.9) - nokogiri (1.16.0) + nokogiri (1.16.2) mini_portile2 (~> 2.8.2) racc (~> 1.4) oj (3.16.3) From 916aeb574d24e2dce1cfefac4694066c7caf65ca Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:23:55 +0100 Subject: [PATCH 03/53] Update DefinitelyTyped types (non-major) (#29088) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4d1084c229bf91..8055554014b0de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3179,12 +3179,12 @@ __metadata: linkType: hard "@types/jest@npm:^29.5.2": - version: 29.5.11 - resolution: "@types/jest@npm:29.5.11" + version: 29.5.12 + resolution: "@types/jest@npm:29.5.12" dependencies: expect: "npm:^29.0.0" pretty-format: "npm:^29.0.0" - checksum: 524a3394845214581278bf4d75055927261fbeac7e1a89cd621bd0636da37d265fe0a85eac58b5778758faad1cbd7c7c361dfc190c78ebde03a91cce33463261 + checksum: 25fc8e4c611fa6c4421e631432e9f0a6865a8cb07c9815ec9ac90d630271cad773b2ee5fe08066f7b95bebd18bb967f8ce05d018ee9ab0430f9dfd1d84665b6f languageName: node linkType: hard @@ -3286,13 +3286,13 @@ __metadata: linkType: hard "@types/pg@npm:^8.6.6": - version: 8.10.9 - resolution: "@types/pg@npm:8.10.9" + version: 8.11.0 + resolution: "@types/pg@npm:8.11.0" dependencies: "@types/node": "npm:*" pg-protocol: "npm:*" pg-types: "npm:^4.0.1" - checksum: 6b3bec7230d09da6459636a66dfd6fb538378e466ffff0a0bcd07d67aa4ddce49c73afc7442f53adec92a49dbf9e71d8d847e0075750d7545331735dfd92d22c + checksum: df2c2ac11fa5e8863a98aadce9a9168af5cfc38a226a228d8b1be513ef48d33ceb9bfaa64ef685a87e0611a4f8d94f2e0736bb2812fa00ed264f76679b86945d languageName: node linkType: hard @@ -3476,13 +3476,13 @@ __metadata: linkType: hard "@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7": - version: 18.2.48 - resolution: "@types/react@npm:18.2.48" + version: 18.2.54 + resolution: "@types/react@npm:18.2.54" dependencies: "@types/prop-types": "npm:*" "@types/scheduler": "npm:*" csstype: "npm:^3.0.2" - checksum: 7e89f18ea2928b1638f564b156d692894dcb9352a7e0a807873c97e858abe1f23dbd165a25dd088a991344e973fdeef88ba5724bfb64504b74072cbc9c220c3a + checksum: ad38193c30a063a481aeec2460de6396c80d8de2f1c7a8cbb80a4e8bc594f74c308ce93e165d743b38507c3ac0a491c24ce0efbd84c9ab21fd5fd38d2963d329 languageName: node linkType: hard @@ -3599,9 +3599,9 @@ __metadata: linkType: hard "@types/uuid@npm:^9.0.0": - version: 9.0.7 - resolution: "@types/uuid@npm:9.0.7" - checksum: b329ebd4f9d1d8e08d4f2cc211be4922d70d1149f73d5772630e4a3acfb5170c6d37b3d7a39a0412f1a56e86e8a844c7f297c798b082f90380608bf766688787 + version: 9.0.8 + resolution: "@types/uuid@npm:9.0.8" + checksum: b411b93054cb1d4361919579ef3508a1f12bf15b5fdd97337d3d351bece6c921b52b6daeef89b62340fd73fd60da407878432a1af777f40648cbe53a01723489 languageName: node linkType: hard From 586b4faf61dac5156a79637b49ce07ca401077d4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:24:44 +0100 Subject: [PATCH 04/53] Update dependency haml_lint to v0.56.0 (#29082) 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 7c10a419ada8dc..960bd48de439a8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -319,7 +319,7 @@ GEM activesupport (>= 5.1) haml (>= 4.0.6) railties (>= 5.1) - haml_lint (0.55.0) + haml_lint (0.56.0) haml (>= 5.0) parallel (~> 1.10) rainbow From 5ca45403e24522257da4ed608c265078b558ab8a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 04:33:11 -0500 Subject: [PATCH 05/53] Update `nsa` gem to version 0.3.0 (#29065) --- Gemfile | 2 +- Gemfile.lock | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/Gemfile b/Gemfile index 906441ec67cb42..5f09b4beb255fa 100644 --- a/Gemfile +++ b/Gemfile @@ -63,7 +63,7 @@ gem 'kaminari', '~> 1.2' gem 'link_header', '~> 0.0' gem 'mime-types', '~> 3.5.0', require: 'mime/types/columnar' gem 'nokogiri', '~> 1.15' -gem 'nsa', github: 'jhawthorn/nsa', ref: 'e020fcc3a54d993ab45b7194d89ab720296c111b' +gem 'nsa' gem 'oj', '~> 3.14' gem 'ox', '~> 2.14' gem 'parslet' diff --git a/Gemfile.lock b/Gemfile.lock index 960bd48de439a8..9de0af9a4bad55 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,17 +7,6 @@ GIT hkdf (~> 0.2) jwt (~> 2.0) -GIT - remote: https://github.com/jhawthorn/nsa.git - revision: e020fcc3a54d993ab45b7194d89ab720296c111b - ref: e020fcc3a54d993ab45b7194d89ab720296c111b - specs: - nsa (0.2.8) - activesupport (>= 4.2, < 7.2) - concurrent-ruby (~> 1.0, >= 1.0.2) - sidekiq (>= 3.5) - statsd-ruby (~> 1.4, >= 1.4.0) - GEM remote: https://rubygems.org/ specs: @@ -468,6 +457,11 @@ GEM nokogiri (1.16.2) mini_portile2 (~> 2.8.2) racc (~> 1.4) + nsa (0.3.0) + activesupport (>= 4.2, < 7.2) + concurrent-ruby (~> 1.0, >= 1.0.2) + sidekiq (>= 3.5) + statsd-ruby (~> 1.4, >= 1.4.0) oj (3.16.3) bigdecimal (>= 3.0) omniauth (2.1.1) @@ -886,7 +880,7 @@ DEPENDENCIES net-http (~> 0.4.0) net-ldap (~> 0.18) nokogiri (~> 1.15) - nsa! + nsa oj (~> 3.14) omniauth (~> 2.0) omniauth-cas (~> 3.0.0.beta.1) From a2d8aa1583545d52b4825a38dc1880f7dd81223d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:33:41 +0100 Subject: [PATCH 06/53] Update dependency tzinfo-data to v1.2024.1 (#29052) 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 9de0af9a4bad55..d6a51e2f0ae875 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -765,7 +765,7 @@ GEM unf (~> 0.1.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - tzinfo-data (1.2023.4) + tzinfo-data (1.2024.1) tzinfo (>= 1.0.0) unf (0.1.4) unf_ext From 779d987fbc42412f80cce93a8f5979525c894d5d Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 04:34:28 -0500 Subject: [PATCH 07/53] Update `codedoc/codecov-action` to v4 (#29036) --- .github/workflows/test-ruby.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-ruby.yml b/.github/workflows/test-ruby.yml index 346703ced4328c..4275f594206767 100644 --- a/.github/workflows/test-ruby.yml +++ b/.github/workflows/test-ruby.yml @@ -139,7 +139,7 @@ jobs: - name: Upload coverage reports to Codecov if: matrix.ruby-version == '.ruby-version' - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: files: coverage/lcov/mastodon.lcov From 66dda7c762d19c18dc1d7e3105a26377c5b6e932 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 6 Feb 2024 10:35:27 +0100 Subject: [PATCH 08/53] Fix already-invalid reports failing to resolve (#29027) --- app/models/report.rb | 6 ++---- spec/models/report_spec.rb | 13 +++++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/models/report.rb b/app/models/report.rb index 38da26d7b75408..1b132753b515f5 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -47,9 +47,9 @@ class Report < ApplicationRecord delegate :local?, to: :account validates :comment, length: { maximum: 1_000 }, if: :local? - validates :rule_ids, absence: true, unless: :violation? + validates :rule_ids, absence: true, if: -> { (category_changed? || rule_ids_changed?) && !violation? } - validate :validate_rule_ids + validate :validate_rule_ids, if: -> { (category_changed? || rule_ids_changed?) && violation? } # entries here need to be kept in sync with the front-end: # - app/javascript/mastodon/features/notifications/components/report.jsx @@ -162,8 +162,6 @@ def set_uri end def validate_rule_ids - return unless violation? - errors.add(:rule_ids, I18n.t('reports.errors.invalid_rules')) unless rules.size == rule_ids&.size end diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb index c514c63b39226f..0168268bcb7723 100644 --- a/spec/models/report_spec.rb +++ b/spec/models/report_spec.rb @@ -133,5 +133,18 @@ report = Fabricate.build(:report, account: remote_account, comment: Faker::Lorem.characters(number: 1001)) expect(report.valid?).to be true end + + it 'is invalid if it references invalid rules' do + report = Fabricate.build(:report, category: :violation, rule_ids: [-1]) + expect(report.valid?).to be false + expect(report).to model_have_error_on_field(:rule_ids) + end + + it 'is invalid if it references rules but category is not "violation"' do + rule = Fabricate(:rule) + report = Fabricate.build(:report, category: :spam, rule_ids: rule.id) + expect(report.valid?).to be false + expect(report).to model_have_error_on_field(:rule_ids) + end end end From 9ce914cc897d2b1100cee8cb6d792a2283d877ec Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 6 Feb 2024 10:35:36 +0100 Subject: [PATCH 09/53] Fix report reason selector in moderation interface not unselecting rules when changing category (#29026) --- .../mastodon/components/admin/ReportReasonSelector.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx b/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx index ecce92b309429d..90f4334a6e1ad2 100644 --- a/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx +++ b/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx @@ -124,7 +124,7 @@ class ReportReasonSelector extends PureComponent { api().put(`/api/v1/admin/reports/${id}`, { category, - rule_ids, + rule_ids: category === 'violation' ? rule_ids : [], }).catch(err => { console.error(err); }); From 90f4b8d53a027e39049b5b6f4decfe605f925bda Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:37:03 +0100 Subject: [PATCH 10/53] Update dependency postcss to v8.4.34 (#29103) 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 8055554014b0de..8783c33f86e9b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13144,13 +13144,13 @@ __metadata: linkType: hard "postcss@npm:^8.2.15, postcss@npm:^8.4.24, postcss@npm:^8.4.33": - version: 8.4.33 - resolution: "postcss@npm:8.4.33" + version: 8.4.34 + resolution: "postcss@npm:8.4.34" dependencies: nanoid: "npm:^3.3.7" picocolors: "npm:^1.0.0" source-map-js: "npm:^1.0.2" - checksum: 16eda83458fcd8a91bece287b5920c7f57164c3ea293e6c80d0ea71ce7843007bcd8592260a5160b9a7f02693e6ac93e2495b02d8c7596d3f3f72c1447e3ba79 + checksum: 4d6f072cdfdc1ced16b4336263d830f8b4397fc47b9b382e02f6448fda9386d881aa9d27fbe0dd124f59c76f3a5da4f360919d25dfc818eca50b48f042af35a8 languageName: node linkType: hard From 62028b1b1bf32623c13e2c5f3419c8ab03fc1db2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:38:32 +0100 Subject: [PATCH 11/53] Update libretranslate/libretranslate Docker tag to v1.5.5 (#29090) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 88979723c338eb..ecdf9f5f53060c 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -70,7 +70,7 @@ services: hard: -1 libretranslate: - image: libretranslate/libretranslate:v1.5.4 + image: libretranslate/libretranslate:v1.5.5 restart: unless-stopped volumes: - lt-data:/home/libretranslate/.local From 0bec5c0755cfb270c692fd39b0f22e98ab1b4e0b Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 04:56:24 -0500 Subject: [PATCH 12/53] Remove migration base class switcher from `RailsSettingsMigration` (#29047) --- db/migrate/20161006213403_rails_settings_migration.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/db/migrate/20161006213403_rails_settings_migration.rb b/db/migrate/20161006213403_rails_settings_migration.rb index 401b7a83b7c1dd..9764196fab453a 100644 --- a/db/migrate/20161006213403_rails_settings_migration.rb +++ b/db/migrate/20161006213403_rails_settings_migration.rb @@ -1,12 +1,6 @@ # frozen_string_literal: true -MIGRATION_BASE_CLASS = if ActiveRecord::VERSION::MAJOR >= 5 - ActiveRecord::Migration[5.0] - else - ActiveRecord::Migration[4.2] - end - -class RailsSettingsMigration < MIGRATION_BASE_CLASS +class RailsSettingsMigration < ActiveRecord::Migration[5.0] def self.up create_table :settings do |t| t.string :var, null: false From a31427a629df020a975276cbff157691e51d7456 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 12:33:06 +0100 Subject: [PATCH 13/53] Update dependency pino to v8.18.0 (#29043) 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 8783c33f86e9b2..75b4c355af97a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12667,8 +12667,8 @@ __metadata: linkType: hard "pino@npm:^8.17.1, pino@npm:^8.17.2": - version: 8.17.2 - resolution: "pino@npm:8.17.2" + version: 8.18.0 + resolution: "pino@npm:8.18.0" dependencies: atomic-sleep: "npm:^1.0.0" fast-redact: "npm:^3.1.1" @@ -12683,7 +12683,7 @@ __metadata: thread-stream: "npm:^2.0.0" bin: pino: bin.js - checksum: 9e55af6cd9d1833a4dbe64924fc73163295acd3c988a9c7db88926669f2574ab7ec607e8487b6dd71dbdad2d7c1c1aac439f37e59233f37220b1a9d88fa2ce01 + checksum: ca73bb31e4656954413b89f48c486b1680fec0c6bb12d4d796c5ccf8eca40f3ee12c9532a0fa61284ed9a800c14eaa0f496f520057ef70cdee0447114813e8eb languageName: node linkType: hard From 4cf07ed78c0f4959160f22506e1f03dc5737a815 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 06:34:11 -0500 Subject: [PATCH 14/53] Add missing action logging to `api/v1/admin/reports#update` (#29044) --- .../api/v1/admin/reports_controller.rb | 1 + .../admin/reports_controller_spec.rb | 10 +++++++ spec/requests/api/v1/admin/reports_spec.rb | 26 +++++++++++++++---- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/v1/admin/reports_controller.rb b/app/controllers/api/v1/admin/reports_controller.rb index 9dfb181a288e6b..7129a5f6ca30fc 100644 --- a/app/controllers/api/v1/admin/reports_controller.rb +++ b/app/controllers/api/v1/admin/reports_controller.rb @@ -35,6 +35,7 @@ def show def update authorize @report, :update? @report.update!(report_params) + log_action :update, @report render json: @report, serializer: REST::Admin::ReportSerializer end diff --git a/spec/controllers/admin/reports_controller_spec.rb b/spec/controllers/admin/reports_controller_spec.rb index 97daaf8da96401..02760154fbe5ff 100644 --- a/spec/controllers/admin/reports_controller_spec.rb +++ b/spec/controllers/admin/reports_controller_spec.rb @@ -58,6 +58,7 @@ report.reload expect(report.action_taken_by_account).to eq user.account expect(report.action_taken?).to be true + expect(last_action_log.target).to eq(report) end end @@ -70,6 +71,7 @@ report.reload expect(report.action_taken_by_account).to be_nil expect(report.action_taken?).to be false + expect(last_action_log.target).to eq(report) end end @@ -81,6 +83,7 @@ expect(response).to redirect_to(admin_report_path(report)) report.reload expect(report.assigned_account).to eq user.account + expect(last_action_log.target).to eq(report) end end @@ -92,6 +95,13 @@ expect(response).to redirect_to(admin_report_path(report)) report.reload expect(report.assigned_account).to be_nil + expect(last_action_log.target).to eq(report) end end + + private + + def last_action_log + Admin::ActionLog.last + end end diff --git a/spec/requests/api/v1/admin/reports_spec.rb b/spec/requests/api/v1/admin/reports_spec.rb index 5403457db029ee..4b0b7e17134734 100644 --- a/spec/requests/api/v1/admin/reports_spec.rb +++ b/spec/requests/api/v1/admin/reports_spec.rb @@ -151,7 +151,9 @@ let(:params) { { category: 'spam' } } it 'updates the report category', :aggregate_failures do - expect { subject }.to change { report.reload.category }.from('other').to('spam') + expect { subject } + .to change { report.reload.category }.from('other').to('spam') + .and create_an_action_log expect(response).to have_http_status(200) @@ -184,7 +186,9 @@ it_behaves_like 'forbidden for wrong role', '' it 'marks report as resolved', :aggregate_failures do - expect { subject }.to change { report.reload.unresolved? }.from(true).to(false) + expect { subject } + .to change { report.reload.unresolved? }.from(true).to(false) + .and create_an_action_log expect(response).to have_http_status(200) end end @@ -200,7 +204,9 @@ it_behaves_like 'forbidden for wrong role', '' it 'marks report as unresolved', :aggregate_failures do - expect { subject }.to change { report.reload.unresolved? }.from(false).to(true) + expect { subject } + .to change { report.reload.unresolved? }.from(false).to(true) + .and create_an_action_log expect(response).to have_http_status(200) end end @@ -216,7 +222,9 @@ it_behaves_like 'forbidden for wrong role', '' it 'assigns report to the requesting user', :aggregate_failures do - expect { subject }.to change { report.reload.assigned_account_id }.from(nil).to(user.account.id) + expect { subject } + .to change { report.reload.assigned_account_id }.from(nil).to(user.account.id) + .and create_an_action_log expect(response).to have_http_status(200) end end @@ -232,8 +240,16 @@ it_behaves_like 'forbidden for wrong role', '' it 'unassigns report from assignee', :aggregate_failures do - expect { subject }.to change { report.reload.assigned_account_id }.from(user.account.id).to(nil) + expect { subject } + .to change { report.reload.assigned_account_id }.from(user.account.id).to(nil) + .and create_an_action_log expect(response).to have_http_status(200) end end + + private + + def create_an_action_log + change(Admin::ActionLog, :count).by(1) + end end From dedefdc303a2438d9b9026797bb00a41930b91e2 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 06:40:24 -0500 Subject: [PATCH 15/53] Move length value mapping to constant in ids to bigints migration (#29048) --- db/migrate/20170918125918_ids_to_bigints.rb | 152 +++++++++++--------- 1 file changed, 82 insertions(+), 70 deletions(-) diff --git a/db/migrate/20170918125918_ids_to_bigints.rb b/db/migrate/20170918125918_ids_to_bigints.rb index 83c5ab971b4763..64f1d0093a2a1e 100644 --- a/db/migrate/20170918125918_ids_to_bigints.rb +++ b/db/migrate/20170918125918_ids_to_bigints.rb @@ -7,80 +7,73 @@ class IdsToBigints < ActiveRecord::Migration[5.1] include Mastodon::MigrationHelpers include Mastodon::MigrationWarning + TABLE_COLUMN_MAPPING = [ + [:account_domain_blocks, :account_id], + [:account_domain_blocks, :id], + [:accounts, :id], + [:blocks, :account_id], + [:blocks, :id], + [:blocks, :target_account_id], + [:conversation_mutes, :account_id], + [:conversation_mutes, :id], + [:domain_blocks, :id], + [:favourites, :account_id], + [:favourites, :id], + [:favourites, :status_id], + [:follow_requests, :account_id], + [:follow_requests, :id], + [:follow_requests, :target_account_id], + [:follows, :account_id], + [:follows, :id], + [:follows, :target_account_id], + [:imports, :account_id], + [:imports, :id], + [:media_attachments, :account_id], + [:media_attachments, :id], + [:mentions, :account_id], + [:mentions, :id], + [:mutes, :account_id], + [:mutes, :id], + [:mutes, :target_account_id], + [:notifications, :account_id], + [:notifications, :from_account_id], + [:notifications, :id], + [:oauth_access_grants, :application_id], + [:oauth_access_grants, :id], + [:oauth_access_grants, :resource_owner_id], + [:oauth_access_tokens, :application_id], + [:oauth_access_tokens, :id], + [:oauth_access_tokens, :resource_owner_id], + [:oauth_applications, :id], + [:oauth_applications, :owner_id], + [:reports, :account_id], + [:reports, :action_taken_by_account_id], + [:reports, :id], + [:reports, :target_account_id], + [:session_activations, :access_token_id], + [:session_activations, :user_id], + [:session_activations, :web_push_subscription_id], + [:settings, :id], + [:settings, :thing_id], + [:statuses, :account_id], + [:statuses, :application_id], + [:statuses, :in_reply_to_account_id], + [:stream_entries, :account_id], + [:stream_entries, :id], + [:subscriptions, :account_id], + [:subscriptions, :id], + [:tags, :id], + [:users, :account_id], + [:users, :id], + [:web_settings, :id], + [:web_settings, :user_id], + ].freeze + disable_ddl_transaction! def migrate_columns(to_type) - included_columns = [ - [:account_domain_blocks, :account_id], - [:account_domain_blocks, :id], - [:accounts, :id], - [:blocks, :account_id], - [:blocks, :id], - [:blocks, :target_account_id], - [:conversation_mutes, :account_id], - [:conversation_mutes, :id], - [:domain_blocks, :id], - [:favourites, :account_id], - [:favourites, :id], - [:favourites, :status_id], - [:follow_requests, :account_id], - [:follow_requests, :id], - [:follow_requests, :target_account_id], - [:follows, :account_id], - [:follows, :id], - [:follows, :target_account_id], - [:imports, :account_id], - [:imports, :id], - [:media_attachments, :account_id], - [:media_attachments, :id], - [:mentions, :account_id], - [:mentions, :id], - [:mutes, :account_id], - [:mutes, :id], - [:mutes, :target_account_id], - [:notifications, :account_id], - [:notifications, :from_account_id], - [:notifications, :id], - [:oauth_access_grants, :application_id], - [:oauth_access_grants, :id], - [:oauth_access_grants, :resource_owner_id], - [:oauth_access_tokens, :application_id], - [:oauth_access_tokens, :id], - [:oauth_access_tokens, :resource_owner_id], - [:oauth_applications, :id], - [:oauth_applications, :owner_id], - [:reports, :account_id], - [:reports, :action_taken_by_account_id], - [:reports, :id], - [:reports, :target_account_id], - [:session_activations, :access_token_id], - [:session_activations, :user_id], - [:session_activations, :web_push_subscription_id], - [:settings, :id], - [:settings, :thing_id], - [:statuses, :account_id], - [:statuses, :application_id], - [:statuses, :in_reply_to_account_id], - [:stream_entries, :account_id], - [:stream_entries, :id], - [:subscriptions, :account_id], - [:subscriptions, :id], - [:tags, :id], - [:users, :account_id], - [:users, :id], - [:web_settings, :id], - [:web_settings, :user_id], - ] - included_columns << [:deprecated_preview_cards, :id] if table_exists?(:deprecated_preview_cards) - - migration_duration_warning(<<~EXPLANATION) - This migration has some sections that can be safely interrupted - and restarted later, and will tell you when those are occurring. + display_warning - For more information, see https://github.com/mastodon/mastodon/pull/5088 - EXPLANATION - - tables = included_columns.map(&:first).uniq table_sizes = {} # Sort tables by their size @@ -103,6 +96,25 @@ def migrate_columns(to_type) end end + def display_warning + migration_duration_warning(<<~EXPLANATION) + This migration has some sections that can be safely interrupted + and restarted later, and will tell you when those are occurring. + + For more information, see https://github.com/mastodon/mastodon/pull/5088 + EXPLANATION + end + + def tables + included_columns.map(&:first).uniq + end + + def included_columns + TABLE_COLUMN_MAPPING.dup.tap do |included_columns| + included_columns << [:deprecated_preview_cards, :id] if table_exists?(:deprecated_preview_cards) + end + end + def up migrate_columns(:bigint) end From 4fb7f611de1cf33a74ff57f1c400e9cba7a24771 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Tue, 6 Feb 2024 13:38:14 +0100 Subject: [PATCH 16/53] Return domain block digests from admin domain blocks API (#29092) --- app/serializers/rest/admin/domain_block_serializer.rb | 6 +++++- spec/requests/api/v1/admin/domain_blocks_spec.rb | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/serializers/rest/admin/domain_block_serializer.rb b/app/serializers/rest/admin/domain_block_serializer.rb index b955d008a6e62b..e94a337cb8d9f9 100644 --- a/app/serializers/rest/admin/domain_block_serializer.rb +++ b/app/serializers/rest/admin/domain_block_serializer.rb @@ -1,11 +1,15 @@ # frozen_string_literal: true class REST::Admin::DomainBlockSerializer < ActiveModel::Serializer - attributes :id, :domain, :created_at, :severity, + attributes :id, :domain, :digest, :created_at, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate def id object.id.to_s end + + def digest + object.domain_digest + end end diff --git a/spec/requests/api/v1/admin/domain_blocks_spec.rb b/spec/requests/api/v1/admin/domain_blocks_spec.rb index 1fb6fc8228b0b9..47aaf44d8054b3 100644 --- a/spec/requests/api/v1/admin/domain_blocks_spec.rb +++ b/spec/requests/api/v1/admin/domain_blocks_spec.rb @@ -49,6 +49,7 @@ { id: domain_block.id.to_s, domain: domain_block.domain, + digest: domain_block.domain_digest, created_at: domain_block.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ'), severity: domain_block.severity.to_s, reject_media: domain_block.reject_media, @@ -97,6 +98,7 @@ { id: domain_block.id.to_s, domain: domain_block.domain, + digest: domain_block.domain_digest, created_at: domain_block.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ'), severity: domain_block.severity.to_s, reject_media: domain_block.reject_media, @@ -188,6 +190,7 @@ { id: domain_block.id.to_s, domain: domain_block.domain, + digest: domain_block.domain_digest, severity: 'suspend', } ) From df7acdcee516d6321a40c0f1cbc55c41b039e3c7 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 07:47:04 -0500 Subject: [PATCH 17/53] Update markers API spec for error case (#29096) --- spec/requests/api/v1/markers_spec.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/spec/requests/api/v1/markers_spec.rb b/spec/requests/api/v1/markers_spec.rb index a1ca4ba7549ae7..b04adf25943e28 100644 --- a/spec/requests/api/v1/markers_spec.rb +++ b/spec/requests/api/v1/markers_spec.rb @@ -52,5 +52,19 @@ expect(user.markers.first.last_read_id).to eq 70_120 end end + + context 'when database object becomes stale' do + before do + allow(Marker).to receive(:transaction).and_raise(ActiveRecord::StaleObjectError) + post '/api/v1/markers', headers: headers, params: { home: { last_read_id: '69420' } } + end + + it 'returns error json' do + expect(response) + .to have_http_status(409) + expect(body_as_json) + .to include(error: /Conflict during update/) + end + end end end From 577520b6376f5ad14aa343a2aba881e7e1ef1897 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 07:49:48 -0500 Subject: [PATCH 18/53] Replace deprecated `Sidekiq::Testing` block style (#29097) --- spec/rails_helper.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index aaf587f49b2f7b..51253390961a52 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -95,8 +95,13 @@ def sign_in(resource, _deprecated = nil, scope: nil) self.use_transactional_tests = true end - config.around(:each, :sidekiq_inline) do |example| - Sidekiq::Testing.inline!(&example) + config.around do |example| + if example.metadata[:sidekiq_inline] == true + Sidekiq::Testing.inline! + else + Sidekiq::Testing.fake! + end + example.run end config.before :each, type: :cli do From e8cc98977d081898682e0ca25154be7fb2c358fb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 13:52:28 +0100 Subject: [PATCH 19/53] Update dependency bootsnap to '~> 1.18.0' (#29019) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 5f09b4beb255fa..355e69b0c467b3 100644 --- a/Gemfile +++ b/Gemfile @@ -26,7 +26,7 @@ gem 'blurhash', '~> 0.1' gem 'active_model_serializers', '~> 0.10' gem 'addressable', '~> 2.8' -gem 'bootsnap', '~> 1.17.0', require: false +gem 'bootsnap', '~> 1.18.0', require: false gem 'browser' gem 'charlock_holmes', '~> 0.7.7' gem 'chewy', '~> 7.3' diff --git a/Gemfile.lock b/Gemfile.lock index d6a51e2f0ae875..57ad96437f0638 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -144,7 +144,7 @@ GEM binding_of_caller (1.0.0) debug_inspector (>= 0.0.1) blurhash (0.1.7) - bootsnap (1.17.1) + bootsnap (1.18.3) msgpack (~> 1.2) brakeman (6.1.1) racc @@ -823,7 +823,7 @@ DEPENDENCIES better_errors (~> 2.9) binding_of_caller (~> 1.0) blurhash (~> 0.1) - bootsnap (~> 1.17.0) + bootsnap (~> 1.18.0) brakeman (~> 6.0) browser bundler-audit (~> 0.9) From 0877f6fda417d27e7e6b9bd1d888dec1b97a7792 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 07:56:22 -0500 Subject: [PATCH 20/53] Remove redundant `return` in `IntentsController` (#29099) --- app/controllers/intents_controller.rb | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/app/controllers/intents_controller.rb b/app/controllers/intents_controller.rb index ea024e30e6bcf9..65c315208dfa93 100644 --- a/app/controllers/intents_controller.rb +++ b/app/controllers/intents_controller.rb @@ -1,27 +1,26 @@ # frozen_string_literal: true class IntentsController < ApplicationController - before_action :check_uri + EXPECTED_SCHEME = 'web+mastodon' + before_action :handle_invalid_uri, unless: :valid_uri? rescue_from Addressable::URI::InvalidURIError, with: :handle_invalid_uri def show - if uri.scheme == 'web+mastodon' - case uri.host - when 'follow' - return redirect_to authorize_interaction_path(uri: uri.query_values['uri'].delete_prefix('acct:')) - when 'share' - return redirect_to share_path(text: uri.query_values['text']) - end + case uri.host + when 'follow' + redirect_to authorize_interaction_path(uri: uri.query_values['uri'].delete_prefix('acct:')) + when 'share' + redirect_to share_path(text: uri.query_values['text']) + else + handle_invalid_uri end - - not_found end private - def check_uri - not_found if uri.blank? + def valid_uri? + uri.present? && uri.scheme == EXPECTED_SCHEME end def handle_invalid_uri From 978fdc71cab327c98b3c03c05f3f716fbeedf6c9 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 08:04:02 -0500 Subject: [PATCH 21/53] Reduce expectation count in example from `ProcessAccountService` spec (#29100) --- .rubocop_todo.yml | 2 +- .../process_account_service_spec.rb | 24 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index c8165c1edf6483..09e9fd73d8d27c 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -39,7 +39,7 @@ RSpec/ExampleLength: Max: 22 RSpec/MultipleExpectations: - Max: 8 + Max: 7 # Configuration parameters: AllowSubject. RSpec/MultipleMemoizedHelpers: diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb index 9abe03181e7373..824577d1b0505f 100644 --- a/spec/services/activitypub/process_account_service_spec.rb +++ b/spec/services/activitypub/process_account_service_spec.rb @@ -21,14 +21,22 @@ it 'parses out of attachment' do account = subject.call('alice', 'example.com', payload) - expect(account.fields).to be_a Array - expect(account.fields.size).to eq 2 - expect(account.fields[0]).to be_a Account::Field - expect(account.fields[0].name).to eq 'Pronouns' - expect(account.fields[0].value).to eq 'They/them' - expect(account.fields[1]).to be_a Account::Field - expect(account.fields[1].name).to eq 'Occupation' - expect(account.fields[1].value).to eq 'Unit test' + + expect(account.fields) + .to be_an(Array) + .and have_attributes(size: 2) + expect(account.fields.first) + .to be_an(Account::Field) + .and have_attributes( + name: eq('Pronouns'), + value: eq('They/them') + ) + expect(account.fields.last) + .to be_an(Account::Field) + .and have_attributes( + name: eq('Occupation'), + value: eq('Unit test') + ) end end From 2d6ab445562fd6c4d56d7aef5dd406c15de8bbf9 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 08:10:00 -0500 Subject: [PATCH 22/53] Reduce request/response round-trips in ap/collections controller spec (#29102) --- .../collections_controller_spec.rb | 90 ++++++------------- 1 file changed, 28 insertions(+), 62 deletions(-) diff --git a/spec/controllers/activitypub/collections_controller_spec.rb b/spec/controllers/activitypub/collections_controller_spec.rb index cf484ff5a43ad9..11ef03c8425c1c 100644 --- a/spec/controllers/activitypub/collections_controller_spec.rb +++ b/spec/controllers/activitypub/collections_controller_spec.rb @@ -17,34 +17,27 @@ end describe 'GET #show' do + subject(:response) { get :show, params: { id: id, account_username: account.username } } + context 'when id is "featured"' do - context 'without signature' do - subject(:response) { get :show, params: { id: 'featured', account_username: account.username } } + let(:id) { 'featured' } - let(:body) { body_as_json } + context 'without signature' do let(:remote_account) { nil } - it 'returns http success' do + it 'returns http success and correct media type' do expect(response).to have_http_status(200) - end - - it 'returns application/activity+json' do expect(response.media_type).to eq 'application/activity+json' end it_behaves_like 'cacheable response' - it 'returns orderedItems with pinned statuses' do - expect(body[:orderedItems]).to be_an Array - expect(body[:orderedItems].size).to eq 3 - end - - it 'includes URI of private pinned status' do - expect(body[:orderedItems]).to include(ActivityPub::TagManager.instance.uri_for(private_pinned)) - end - - it 'does not include contents of private pinned status' do - expect(response.body).to_not include(private_pinned.text) + it 'returns orderedItems with correct items' do + expect(body_as_json[:orderedItems]) + .to be_an(Array) + .and have_attributes(size: 3) + .and include(ActivityPub::TagManager.instance.uri_for(private_pinned)) + .and not_include(private_pinned.text) end context 'when account is permanently suspended' do @@ -73,33 +66,19 @@ let(:remote_account) { Fabricate(:account, domain: 'example.com') } context 'when getting a featured resource' do - before do - get :show, params: { id: 'featured', account_username: account.username } - end - - it 'returns http success' do + it 'returns http success and correct media type' do expect(response).to have_http_status(200) - end - - it 'returns application/activity+json' do expect(response.media_type).to eq 'application/activity+json' end it_behaves_like 'cacheable response' - it 'returns orderedItems with pinned statuses' do - json = body_as_json - expect(json[:orderedItems]).to be_an Array - expect(json[:orderedItems].size).to eq 3 - end - - it 'includes URI of private pinned status' do - json = body_as_json - expect(json[:orderedItems]).to include(ActivityPub::TagManager.instance.uri_for(private_pinned)) - end - - it 'does not include contents of private pinned status' do - expect(response.body).to_not include(private_pinned.text) + it 'returns orderedItems with expected items' do + expect(body_as_json[:orderedItems]) + .to be_an(Array) + .and have_attributes(size: 3) + .and include(ActivityPub::TagManager.instance.uri_for(private_pinned)) + .and not_include(private_pinned.text) end end @@ -111,50 +90,36 @@ context 'when signed request account is blocked' do before do account.block!(remote_account) - get :show, params: { id: 'featured', account_username: account.username } end - it 'returns http success' do + it 'returns http success and correct media type and cache headers' do expect(response).to have_http_status(200) - end - - it 'returns application/activity+json' do expect(response.media_type).to eq 'application/activity+json' - end - - it 'returns private Cache-Control header' do expect(response.headers['Cache-Control']).to include 'private' end it 'returns empty orderedItems' do - json = body_as_json - expect(json[:orderedItems]).to be_an Array - expect(json[:orderedItems].size).to eq 0 + expect(body_as_json[:orderedItems]) + .to be_an(Array) + .and have_attributes(size: 0) end end context 'when signed request account is domain blocked' do before do account.block_domain!(remote_account.domain) - get :show, params: { id: 'featured', account_username: account.username } end - it 'returns http success' do + it 'returns http success and correct media type and cache headers' do expect(response).to have_http_status(200) - end - - it 'returns application/activity+json' do expect(response.media_type).to eq 'application/activity+json' - end - - it 'returns private Cache-Control header' do expect(response.headers['Cache-Control']).to include 'private' end it 'returns empty orderedItems' do - json = body_as_json - expect(json[:orderedItems]).to be_an Array - expect(json[:orderedItems].size).to eq 0 + expect(body_as_json[:orderedItems]) + .to be_an(Array) + .and have_attributes(size: 0) end end end @@ -162,8 +127,9 @@ end context 'when id is not "featured"' do + let(:id) { 'hoge' } + it 'returns http not found' do - get :show, params: { id: 'hoge', account_username: account.username } expect(response).to have_http_status(404) end end From 69e61fff38b426109bd074ccf93f5d2874d430c2 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 08:18:37 -0500 Subject: [PATCH 23/53] Move direct serializer usage out of admin view partial (#29028) --- app/helpers/react_component_helper.rb | 11 +++++++++++ app/views/admin/reports/_media_attachments.html.haml | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/helpers/react_component_helper.rb b/app/helpers/react_component_helper.rb index ce616e830621b0..821a6f1e2d451d 100644 --- a/app/helpers/react_component_helper.rb +++ b/app/helpers/react_component_helper.rb @@ -15,9 +15,20 @@ def react_admin_component(name, props = {}) div_tag_with_data(data) end + def serialized_media_attachments(media_attachments) + media_attachments.map { |attachment| serialized_attachment(attachment) } + end + private def div_tag_with_data(data) content_tag(:div, nil, data: data) end + + def serialized_attachment(attachment) + ActiveModelSerializers::SerializableResource.new( + attachment, + serializer: REST::MediaAttachmentSerializer + ).as_json + end end diff --git a/app/views/admin/reports/_media_attachments.html.haml b/app/views/admin/reports/_media_attachments.html.haml index 3c52d691781efe..45cc4c5aa31078 100644 --- a/app/views/admin/reports/_media_attachments.html.haml +++ b/app/views/admin/reports/_media_attachments.html.haml @@ -12,6 +12,6 @@ = react_component :media_gallery, height: 343, lang: status.language, - media: status.ordered_media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }, + media: serialized_media_attachments(status.ordered_media_attachments), sensitive: status.sensitive?, visible: false From cf42eba0f997aa8065beac853b79d993e8a2495b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:31:54 +0100 Subject: [PATCH 24/53] Update dependency brakeman to v6.1.2 (#29062) 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 57ad96437f0638..b76f449b26448a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -146,7 +146,7 @@ GEM blurhash (0.1.7) bootsnap (1.18.3) msgpack (~> 1.2) - brakeman (6.1.1) + brakeman (6.1.2) racc browser (5.3.1) brpoplpush-redis_script (0.1.3) From 93a5b3f9df7dcf1965525ee2a1202e5f1e07bf05 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 08:33:42 -0500 Subject: [PATCH 25/53] Move status serializer chooser to private method (#29030) --- app/controllers/api/v1/statuses_controller.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index 064e7632a8009a..702896db246d9c 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -71,7 +71,7 @@ def create with_rate_limit: true ) - render json: @status, serializer: @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer + render json: @status, serializer: serializer_for_status rescue PostStatusService::UnexpectedMentionsError => e unexpected_accounts = ActiveModel::Serializer::CollectionSerializer.new( e.accounts, @@ -155,6 +155,10 @@ def status_params ) end + def serializer_for_status + @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer + end + def pagination_params(core_params) params.slice(:limit).permit(:limit).merge(core_params) end From 0df86d77fd5f57fc88cfd00a2cf2c265215a2839 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 09:36:04 -0500 Subject: [PATCH 26/53] Reduce `RSpec/ExampleLength` in PostStatusService spec example (#29105) --- spec/services/post_status_service_spec.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb index 1e5c420a63b245..d10a82607e009b 100644 --- a/spec/services/post_status_service_spec.rb +++ b/spec/services/post_status_service_spec.rb @@ -228,13 +228,7 @@ subject.call( account, text: 'test status update', - media_ids: [ - Fabricate(:media_attachment, account: account), - Fabricate(:media_attachment, account: account), - Fabricate(:media_attachment, account: account), - Fabricate(:media_attachment, account: account), - Fabricate(:media_attachment, account: account), - ].map(&:id) + media_ids: Array.new(5) { Fabricate(:media_attachment, account: account) }.map(&:id) ) end.to raise_error( Mastodon::ValidationError, From 2f19ddd1fa1c14db1edaedc93f29bb4f66ab2cf0 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 09:54:26 -0500 Subject: [PATCH 27/53] Move status serializer error handling to private method (#29031) --- app/controllers/api/v1/statuses_controller.rb | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index 702896db246d9c..01c3718763f824 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -73,11 +73,7 @@ def create render json: @status, serializer: serializer_for_status rescue PostStatusService::UnexpectedMentionsError => e - unexpected_accounts = ActiveModel::Serializer::CollectionSerializer.new( - e.accounts, - serializer: REST::AccountSerializer - ) - render json: { error: e.message, unexpected_accounts: unexpected_accounts }, status: 422 + render json: unexpected_accounts_error_json(e), status: 422 end def update @@ -159,6 +155,17 @@ def serializer_for_status @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer end + def unexpected_accounts_error_json(error) + { + error: error.message, + unexpected_accounts: serialized_accounts(error.accounts), + } + end + + def serialized_accounts(accounts) + ActiveModel::Serializer::CollectionSerializer.new(accounts, serializer: REST::AccountSerializer) + end + def pagination_params(core_params) params.slice(:limit).permit(:limit).merge(core_params) end From 64300e0fe344b9dee015e65423c327742db246af Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 6 Feb 2024 16:32:09 +0100 Subject: [PATCH 28/53] Fix self-destruct schedule not actually replacing initial schedule (#29049) --- config/initializers/sidekiq.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 9a2743ed5b0263..53b02edc40227e 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -26,6 +26,7 @@ 'queue' => 'scheduler', }, } + SidekiqScheduler::Scheduler.instance.reload_schedule! end end From 1e0b0a3486cf04666b7cbd67a4a72cf7f8068c97 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 6 Feb 2024 11:42:25 -0500 Subject: [PATCH 29/53] Use SQL heredoc on long statement lines in migrations (#29112) --- ...0317193015_add_search_index_to_accounts.rb | 12 +++++++- ...5042_add_case_insensitive_index_to_tags.rb | 29 +++++++++++++++++-- ..._fix_canonical_email_blocks_foreign_key.rb | 17 +++++++++-- .../20220309213005_fix_reblog_deleted_at.rb | 11 ++++++- 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/db/migrate/20170317193015_add_search_index_to_accounts.rb b/db/migrate/20170317193015_add_search_index_to_accounts.rb index e29da61b157ba2..0edc38154973ae 100644 --- a/db/migrate/20170317193015_add_search_index_to_accounts.rb +++ b/db/migrate/20170317193015_add_search_index_to_accounts.rb @@ -2,7 +2,17 @@ class AddSearchIndexToAccounts < ActiveRecord::Migration[5.0] def up - execute 'CREATE INDEX search_index ON accounts USING gin((setweight(to_tsvector(\'simple\', accounts.display_name), \'A\') || setweight(to_tsvector(\'simple\', accounts.username), \'B\') || setweight(to_tsvector(\'simple\', coalesce(accounts.domain, \'\')), \'C\')));' + execute <<~SQL.squish + CREATE INDEX search_index + ON accounts + USING gin( + ( + setweight(to_tsvector('simple', accounts.display_name), 'A') || + setweight(to_tsvector('simple', accounts.username), 'B') || + setweight(to_tsvector('simple', coalesce(accounts.domain, '')), 'C') + ) + ) + SQL end def down diff --git a/db/migrate/20190726175042_add_case_insensitive_index_to_tags.rb b/db/migrate/20190726175042_add_case_insensitive_index_to_tags.rb index f2d3aa8ee86077..02f073e14f505d 100644 --- a/db/migrate/20190726175042_add_case_insensitive_index_to_tags.rb +++ b/db/migrate/20190726175042_add_case_insensitive_index_to_tags.rb @@ -9,9 +9,32 @@ def up redundant_tag_ids = row['ids'].split(',')[1..] safety_assured do - execute "UPDATE accounts_tags AS t0 SET tag_id = #{canonical_tag_id} WHERE tag_id IN (#{redundant_tag_ids.join(', ')}) AND NOT EXISTS (SELECT t1.tag_id FROM accounts_tags AS t1 WHERE t1.tag_id = #{canonical_tag_id} AND t1.account_id = t0.account_id)" - execute "UPDATE statuses_tags AS t0 SET tag_id = #{canonical_tag_id} WHERE tag_id IN (#{redundant_tag_ids.join(', ')}) AND NOT EXISTS (SELECT t1.tag_id FROM statuses_tags AS t1 WHERE t1.tag_id = #{canonical_tag_id} AND t1.status_id = t0.status_id)" - execute "UPDATE featured_tags AS t0 SET tag_id = #{canonical_tag_id} WHERE tag_id IN (#{redundant_tag_ids.join(', ')}) AND NOT EXISTS (SELECT t1.tag_id FROM featured_tags AS t1 WHERE t1.tag_id = #{canonical_tag_id} AND t1.account_id = t0.account_id)" + execute <<~SQL.squish + UPDATE accounts_tags + AS t0 + SET tag_id = #{canonical_tag_id} + WHERE + tag_id IN (#{redundant_tag_ids.join(', ')}) + AND NOT EXISTS (SELECT t1.tag_id FROM accounts_tags AS t1 WHERE t1.tag_id = #{canonical_tag_id} AND t1.account_id = t0.account_id) + SQL + + execute <<~SQL.squish + UPDATE statuses_tags + AS t0 + SET tag_id = #{canonical_tag_id} + WHERE + tag_id IN (#{redundant_tag_ids.join(', ')}) + AND NOT EXISTS (SELECT t1.tag_id FROM statuses_tags AS t1 WHERE t1.tag_id = #{canonical_tag_id} AND t1.status_id = t0.status_id) + SQL + + execute <<~SQL.squish + UPDATE featured_tags + AS t0 + SET tag_id = #{canonical_tag_id} + WHERE + tag_id IN (#{redundant_tag_ids.join(', ')}) + AND NOT EXISTS (SELECT t1.tag_id FROM featured_tags AS t1 WHERE t1.tag_id = #{canonical_tag_id} AND t1.account_id = t0.account_id) + SQL end Tag.where(id: redundant_tag_ids).in_batches.delete_all diff --git a/db/migrate/20210630000137_fix_canonical_email_blocks_foreign_key.rb b/db/migrate/20210630000137_fix_canonical_email_blocks_foreign_key.rb index 9b475966bb617a..90a1b1a5cfe9cb 100644 --- a/db/migrate/20210630000137_fix_canonical_email_blocks_foreign_key.rb +++ b/db/migrate/20210630000137_fix_canonical_email_blocks_foreign_key.rb @@ -3,13 +3,26 @@ class FixCanonicalEmailBlocksForeignKey < ActiveRecord::Migration[6.1] def up safety_assured do - execute 'ALTER TABLE canonical_email_blocks DROP CONSTRAINT fk_rails_1ecb262096, ADD CONSTRAINT fk_rails_1ecb262096 FOREIGN KEY (reference_account_id) REFERENCES accounts(id) ON DELETE CASCADE;' + execute <<~SQL.squish + ALTER TABLE canonical_email_blocks + DROP CONSTRAINT fk_rails_1ecb262096, + ADD CONSTRAINT fk_rails_1ecb262096 + FOREIGN KEY (reference_account_id) + REFERENCES accounts(id) + ON DELETE CASCADE + SQL end end def down safety_assured do - execute 'ALTER TABLE canonical_email_blocks DROP CONSTRAINT fk_rails_1ecb262096, ADD CONSTRAINT fk_rails_1ecb262096 FOREIGN KEY (reference_account_id) REFERENCES accounts(id);' + execute <<~SQL.squish + ALTER TABLE canonical_email_blocks + DROP CONSTRAINT fk_rails_1ecb262096, + ADD CONSTRAINT fk_rails_1ecb262096 + FOREIGN KEY (reference_account_id) + REFERENCES accounts(id) + SQL end end end diff --git a/db/migrate/20220309213005_fix_reblog_deleted_at.rb b/db/migrate/20220309213005_fix_reblog_deleted_at.rb index e3474beeb1eb31..7fb9bff26c625a 100644 --- a/db/migrate/20220309213005_fix_reblog_deleted_at.rb +++ b/db/migrate/20220309213005_fix_reblog_deleted_at.rb @@ -4,7 +4,16 @@ class FixReblogDeletedAt < ActiveRecord::Migration[6.1] disable_ddl_transaction! def up - safety_assured { execute 'UPDATE statuses s SET deleted_at = r.deleted_at FROM statuses r WHERE s.reblog_of_id = r.id AND r.deleted_at IS NOT NULL' } + safety_assured do + execute <<~SQL.squish + UPDATE statuses s + SET deleted_at = r.deleted_at + FROM statuses r + WHERE + s.reblog_of_id = r.id + AND r.deleted_at IS NOT NULL + SQL + end end def down; end From 7ee93b74317c0b51516146fbe32e72cd9bbb151c Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 6 Feb 2024 18:10:17 +0100 Subject: [PATCH 30/53] Change `source` attribute of `Suggestion` entity in `/api/v2/suggestions` back to a string (#29108) --- .../components/inline_follow_suggestions.jsx | 8 ++++---- app/models/account_suggestions.rb | 4 ++-- app/models/account_suggestions/suggestion.rb | 2 +- app/serializers/rest/suggestion_serializer.rb | 15 +++++++++++++- spec/requests/api/v2/suggestions_spec.rb | 20 ++++++++++++++++++- .../rest/suggestion_serializer_spec.rb | 2 +- 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/app/javascript/mastodon/features/home_timeline/components/inline_follow_suggestions.jsx b/app/javascript/mastodon/features/home_timeline/components/inline_follow_suggestions.jsx index ac414d04d6a810..f76526e04502e2 100644 --- a/app/javascript/mastodon/features/home_timeline/components/inline_follow_suggestions.jsx +++ b/app/javascript/mastodon/features/home_timeline/components/inline_follow_suggestions.jsx @@ -59,7 +59,7 @@ Source.propTypes = { id: PropTypes.oneOf(['friends_of_friends', 'similar_to_recently_followed', 'featured', 'most_followed', 'most_interactions']), }; -const Card = ({ id, source }) => { +const Card = ({ id, sources }) => { const intl = useIntl(); const account = useSelector(state => state.getIn(['accounts', id])); const relationship = useSelector(state => state.getIn(['relationships', id])); @@ -89,7 +89,7 @@ const Card = ({ id, source }) => {
- {firstVerifiedField ? : } + {firstVerifiedField ? : }