From 1fc14e324bf103e379cf73ffceebbf46472cccde Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 10:41:54 +0200 Subject: [PATCH 01/19] New Crowdin Translations (automated) (#30890) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/en-GB.json | 8 ++++++++ app/javascript/mastodon/locales/sk.json | 3 +++ config/locales/doorkeeper.en-GB.yml | 2 ++ config/locales/en-GB.yml | 3 +++ 4 files changed, 16 insertions(+) diff --git a/app/javascript/mastodon/locales/en-GB.json b/app/javascript/mastodon/locales/en-GB.json index c4f401d86d..94d7defc7e 100644 --- a/app/javascript/mastodon/locales/en-GB.json +++ b/app/javascript/mastodon/locales/en-GB.json @@ -35,7 +35,9 @@ "account.follow_back": "Follow back", "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", + "account.followers_counter": "{count, plural, one {{counter} follower} other {{counter} followers}}", "account.following": "Following", + "account.following_counter": "{count, plural, one {{counter} following} other {{counter} following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.go_to_profile": "Go to profile", "account.hide_reblogs": "Hide boosts from @{name}", @@ -61,6 +63,7 @@ "account.requested_follow": "{name} has requested to follow you", "account.share": "Share @{name}'s profile", "account.show_reblogs": "Show boosts from @{name}", + "account.statuses_counter": "{count, plural, one {{counter} post} other {{counter} posts}}", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unblock domain {domain}", "account.unblock_short": "Unblock", @@ -411,6 +414,8 @@ "limited_account_hint.action": "Show profile anyway", "limited_account_hint.title": "This profile has been hidden by the moderators of {domain}.", "link_preview.author": "By {name}", + "link_preview.more_from_author": "More from {name}", + "link_preview.shares": "{count, plural, one {{counter} post} other {{counter} posts}}", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -691,8 +696,11 @@ "server_banner.about_active_users": "People using this server during the last 30 days (Monthly Active Users)", "server_banner.active_users": "active users", "server_banner.administered_by": "Administered by:", + "server_banner.is_one_of_many": "{domain} is one of the many independent Mastodon servers you can use to participate in the fediverse.", "server_banner.server_stats": "Server stats:", "sign_in_banner.create_account": "Create account", + "sign_in_banner.follow_anyone": "Follow anyone across the fediverse and see it all in chronological order. No algorithms, ads, or clickbait in sight.", + "sign_in_banner.mastodon_is": "Mastodon is the best way to keep up with what's happening.", "sign_in_banner.sign_in": "Sign in", "sign_in_banner.sso_redirect": "Login or Register", "status.admin_account": "Open moderation interface for @{name}", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index ed9c0de604..ed877f7667 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -88,7 +88,10 @@ "audio.hide": "Skryť zvuk", "block_modal.show_less": "Zobraziť menej", "block_modal.show_more": "Zobraziť viac", + "block_modal.they_cant_mention": "Nemôžu ťa spomenúť, alebo nasledovať.", + "block_modal.they_will_know": "Môžu vidieť, že sú zablokovaní/ý.", "block_modal.title": "Blokovať užívateľa?", + "block_modal.you_wont_see_mentions": "Neuvidíš príspevky, ktoré ich spomínajú.", "boost_modal.combo": "Nabudúce môžete preskočiť stlačením {combo}", "bundle_column_error.copy_stacktrace": "Kopírovať chybovú hlášku", "bundle_column_error.error.body": "Požadovanú stránku nebolo možné vykresliť. Môže to byť spôsobené chybou v našom kóde alebo problémom s kompatibilitou prehliadača.", diff --git a/config/locales/doorkeeper.en-GB.yml b/config/locales/doorkeeper.en-GB.yml index b3ceffb13f..f254825b1b 100644 --- a/config/locales/doorkeeper.en-GB.yml +++ b/config/locales/doorkeeper.en-GB.yml @@ -135,6 +135,7 @@ en-GB: media: Media attachments mutes: Mutes notifications: Notifications + profile: Your Mastodon profile push: Push notifications reports: Reports search: Search @@ -165,6 +166,7 @@ en-GB: admin:write:reports: perform moderation actions on reports crypto: use end-to-end encryption follow: modify account relationships + profile: read only your account's profile information push: receive your push notifications read: read all your account's data read:accounts: see accounts information diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index 07eb84ebbe..928823b995 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -285,6 +285,7 @@ en-GB: update_custom_emoji_html: "%{name} updated emoji %{target}" update_domain_block_html: "%{name} updated domain block for %{target}" update_ip_block_html: "%{name} changed rule for IP %{target}" + update_report_html: "%{name} updated report %{target}" update_status_html: "%{name} updated post by %{target}" update_user_role_html: "%{name} changed %{target} role" deleted_account: deleted account @@ -292,6 +293,7 @@ en-GB: filter_by_action: Filter by action filter_by_user: Filter by user title: Audit log + unavailable_instance: "(domain name unavailable)" announcements: destroyed_msg: Announcement successfully deleted! edit: @@ -950,6 +952,7 @@ en-GB: delete: Delete edit_preset: Edit warning preset empty: You haven't defined any warning presets yet. + title: Warning presets webhooks: add_new: Add endpoint delete: Delete From ebd8e1bbb6465c78f6542fe7f09938fdb768dbb7 Mon Sep 17 00:00:00 2001 From: David Roetzel Date: Wed, 3 Jul 2024 09:19:54 +0200 Subject: [PATCH 02/19] Add system check for missing database indexes (#30888) --- Gemfile | 1 + Gemfile.lock | 2 + app/lib/admin/db/schema_parser.rb | 92 +++++++++++++++++++ app/lib/admin/system_check.rb | 1 + .../system_check/missing_indexes_check.rb | 36 ++++++++ config/locales/en.yml | 2 + spec/lib/admin/db/schema_parser_spec.rb | 49 ++++++++++ .../missing_indexes_check_spec.rb | 65 +++++++++++++ 8 files changed, 248 insertions(+) create mode 100644 app/lib/admin/db/schema_parser.rb create mode 100644 app/lib/admin/system_check/missing_indexes_check.rb create mode 100644 spec/lib/admin/db/schema_parser_spec.rb create mode 100644 spec/lib/admin/system_check/missing_indexes_check_spec.rb diff --git a/Gemfile b/Gemfile index be3f9e6f98..0d6cc4c4e1 100644 --- a/Gemfile +++ b/Gemfile @@ -229,3 +229,4 @@ gem 'rubyzip', '~> 2.3' gem 'hcaptcha', '~> 7.1' gem 'mail', '~> 2.8' +gem 'prism' diff --git a/Gemfile.lock b/Gemfile.lock index 42cc0e1986..969d18493a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -600,6 +600,7 @@ GEM actionmailer (>= 3) net-smtp premailer (~> 1.7, >= 1.7.9) + prism (0.30.0) propshaft (0.9.0) actionpack (>= 7.0.0) activesupport (>= 7.0.0) @@ -1003,6 +1004,7 @@ DEPENDENCIES pg (~> 1.5) pghero premailer-rails + prism propshaft public_suffix (~> 6.0) puma (~> 6.3) diff --git a/app/lib/admin/db/schema_parser.rb b/app/lib/admin/db/schema_parser.rb new file mode 100644 index 0000000000..e61a2281ee --- /dev/null +++ b/app/lib/admin/db/schema_parser.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +class Admin::Db::SchemaParser + class Index + attr_reader :name, :table_name, :columns, :options + + def initialize(name:, table_name:, columns:, options:) + @name = name + @table_name = table_name + @columns = columns + @options = options + end + end + + attr_reader :indexes_by_table + + def initialize(source) + parse(source) + end + + private + + def parse(source) + @indexes_by_table = {} + queue = [Prism.parse(source).value] + while (node = queue.shift) + if node.type == :call_node && node.name == :create_table + parse_create_table(node) + elsif node.type == :call_node && node.name == :add_index + parse_add_index(node) + else + queue.concat(node.compact_child_nodes) + end + end + end + + def parse_create_table(node) + table_name = parse_arguments(node).first + queue = node.compact_child_nodes + while (node = queue.shift) + if node.type == :call_node && node.name == :index + parse_index(node, table_name:) + else + queue.concat(node.compact_child_nodes) + end + end + end + + def parse_index(node, table_name:) + arguments = parse_arguments(node) + save_index( + name: arguments.last[:name], + table_name: table_name, + columns: arguments.first, + options: arguments.last + ) + end + + def parse_add_index(node) + arguments = parse_arguments(node) + save_index( + name: arguments.last[:name], + table_name: arguments.first, + columns: arguments[1], + options: arguments.last + ) + end + + def parse_arguments(node) + node.arguments.arguments.map { |a| parse_argument(a) } + end + + def parse_argument(argument) + case argument + when Prism::StringNode + argument.unescaped + when Prism::SymbolNode + argument.unescaped.to_sym + when Prism::ArrayNode + argument.elements.map { |e| parse_argument(e) } + when Prism::KeywordHashNode + argument.elements.to_h do |element| + [element.key.unescaped.to_sym, parse_argument(element.value)] + end + end + end + + def save_index(name:, table_name:, columns:, options:) + @indexes_by_table[table_name] ||= [] + @indexes_by_table[table_name] << Index.new(name:, table_name:, columns:, options:) + end +end diff --git a/app/lib/admin/system_check.rb b/app/lib/admin/system_check.rb index 25c88341a4..453011f7a6 100644 --- a/app/lib/admin/system_check.rb +++ b/app/lib/admin/system_check.rb @@ -8,6 +8,7 @@ class Admin::SystemCheck Admin::SystemCheck::SidekiqProcessCheck, Admin::SystemCheck::RulesCheck, Admin::SystemCheck::ElasticsearchCheck, + Admin::SystemCheck::MissingIndexesCheck, ].freeze def self.perform(current_user) diff --git a/app/lib/admin/system_check/missing_indexes_check.rb b/app/lib/admin/system_check/missing_indexes_check.rb new file mode 100644 index 0000000000..b7eecbb067 --- /dev/null +++ b/app/lib/admin/system_check/missing_indexes_check.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +class Admin::SystemCheck::MissingIndexesCheck < Admin::SystemCheck::BaseCheck + def skip? + !current_user.can?(:view_devops) + end + + def pass? + missing_indexes.none? + end + + def message + Admin::SystemCheck::Message.new(:missing_indexes_check, missing_indexes.join(', ')) + end + + private + + def missing_indexes + @missing_indexes ||= begin + expected_indexes_by_table.flat_map do |table, indexes| + expected_indexes = indexes.map(&:name) + expected_indexes - existing_indexes_for(table) + end + end + end + + def expected_indexes_by_table + schema_rb = Rails.root.join('db', 'schema.rb').read + schema_parser = Admin::Db::SchemaParser.new(schema_rb) + schema_parser.indexes_by_table + end + + def existing_indexes_for(table) + ActiveRecord::Base.connection.indexes(table).map(&:name) + end +end diff --git a/config/locales/en.yml b/config/locales/en.yml index 20df80c272..270382dd11 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -862,6 +862,8 @@ en: elasticsearch_version_check: message_html: 'Incompatible Elasticsearch version: %{value}' version_comparison: Elasticsearch %{running_version} is running while %{required_version} is required + missing_indexes_check: + message_html: 'The following indexes are missing from the database and should be recreated: %{value}.
Missing indexes may lead to severely reduced performance and data inconsistencies.' rules_check: action: Manage server rules message_html: You haven't defined any server rules. diff --git a/spec/lib/admin/db/schema_parser_spec.rb b/spec/lib/admin/db/schema_parser_spec.rb new file mode 100644 index 0000000000..e28d5c1f97 --- /dev/null +++ b/spec/lib/admin/db/schema_parser_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Admin::Db::SchemaParser do + let(:dummy_schema) do + <<~SCHEMA + # Comment + ActiveRecord::Schema[7.1].define(version: 23) do + create_table "people", force: :cascade do |t| + t.string "name" + end + + create_table "posts", force: :cascade do |t| + t.string "title", null: false + t.bigint "size", null: false + t.string "description" + # t.index ["size", "title"], name: "index_posts_on_size_and_title" + t.index ["title"], name: "index_posts_on_title", unique: true + t.index ["size"], name: "index_posts_on_size" + end + + # add_index "people", ["name"], name: "commented_out_index" + add_index "people", ["name"], name: "index_people_on_name" + end + SCHEMA + end + let(:schema_parser) { described_class.new(dummy_schema) } + + describe '#indexes_by_table' do + subject { schema_parser.indexes_by_table } + + it 'returns index info for all affected tables' do + expect(subject.keys).to match_array(%w(people posts)) + end + + it 'returns all index information for the `people` table' do + people_info = subject['people'] + expect(people_info.map(&:name)).to contain_exactly('index_people_on_name') + end + + it 'returns all index information for the `posts` table' do + posts_info = subject['posts'] + expect(posts_info.map(&:name)).to contain_exactly( + 'index_posts_on_title', 'index_posts_on_size' + ) + end + end +end diff --git a/spec/lib/admin/system_check/missing_indexes_check_spec.rb b/spec/lib/admin/system_check/missing_indexes_check_spec.rb new file mode 100644 index 0000000000..e183be5620 --- /dev/null +++ b/spec/lib/admin/system_check/missing_indexes_check_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Admin::SystemCheck::MissingIndexesCheck do + subject(:check) { described_class.new(user) } + + let(:user) { Fabricate(:user) } + let(:schema_parser) do + instance_double(Admin::Db::SchemaParser, indexes_by_table: index_info) + end + let(:index_info) do + { + 'users' => [instance_double(Admin::Db::SchemaParser::Index, name: 'index_users_on_profile_id')], + 'posts' => [instance_double(Admin::Db::SchemaParser::Index, name: 'index_posts_on_user_id')], + } + end + let(:posts_indexes) { [] } + let(:users_indexes) { [] } + + before do + allow(Admin::Db::SchemaParser).to receive(:new).and_return(schema_parser) + allow(ActiveRecord::Base.connection).to receive(:indexes).with('posts').and_return(posts_indexes) + allow(ActiveRecord::Base.connection).to receive(:indexes).with('users').and_return(users_indexes) + end + + it_behaves_like 'a check available to devops users' + + describe '#pass?' do + context 'when indexes are missing' do + let(:posts_indexes) do + [instance_double(ActiveRecord::ConnectionAdapters::IndexDefinition, name: 'index_posts_on_user_id')] + end + + it 'returns false' do + expect(check.pass?).to be false + end + end + + context 'when all expected indexes are present' do + let(:posts_indexes) do + [instance_double(ActiveRecord::ConnectionAdapters::IndexDefinition, name: 'index_posts_on_user_id')] + end + let(:users_indexes) do + [instance_double(ActiveRecord::ConnectionAdapters::IndexDefinition, name: 'index_users_on_profile_id')] + end + + it 'returns true' do + expect(check.pass?).to be true + end + end + end + + describe '#message' do + subject { check.message } + + it 'sets the class name as the message key' do + expect(subject.key).to eq(:missing_indexes_check) + end + + it 'sets a list of missing indexes as message value' do + expect(subject.value).to eq('index_users_on_profile_id, index_posts_on_user_id') + end + end +end From 2e295bd5e7d3e7fefd4d4f03279f0dd0f3e5427d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 07:20:48 +0000 Subject: [PATCH 03/19] chore(deps): update dependency aws-sdk-s3 to v1.156.0 (#30899) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 969d18493a..d855c05f43 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -100,19 +100,19 @@ GEM attr_required (1.0.2) awrence (1.2.1) aws-eventstream (1.3.0) - aws-partitions (1.949.0) - aws-sdk-core (3.200.0) + aws-partitions (1.950.0) + aws-sdk-core (3.201.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.87.0) - aws-sdk-core (~> 3, >= 3.199.0) - aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.155.0) - aws-sdk-core (~> 3, >= 3.199.0) + aws-sdk-kms (1.88.0) + aws-sdk-core (~> 3, >= 3.201.0) + aws-sigv4 (~> 1.5) + aws-sdk-s3 (1.156.0) + aws-sdk-core (~> 3, >= 3.201.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.8) + aws-sigv4 (~> 1.5) aws-sigv4 (1.8.0) aws-eventstream (~> 1, >= 1.0.2) azure-storage-blob (2.0.3) From ba7e7a6368f4e6097a7c6ee7145c5ff43e906517 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 09:21:05 +0200 Subject: [PATCH 04/19] chore(deps): update opentelemetry-ruby (non-major) (#30898) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile | 2 +- Gemfile.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 0d6cc4c4e1..d1a8c2c5a4 100644 --- a/Gemfile +++ b/Gemfile @@ -114,7 +114,7 @@ group :opentelemetry do gem 'opentelemetry-instrumentation-net_http', '~> 0.22.4', require: false gem 'opentelemetry-instrumentation-pg', '~> 0.27.1', require: false gem 'opentelemetry-instrumentation-rack', '~> 0.24.1', require: false - gem 'opentelemetry-instrumentation-rails', '~> 0.30.0', require: false + gem 'opentelemetry-instrumentation-rails', '~> 0.31.0', require: false gem 'opentelemetry-instrumentation-redis', '~> 0.25.3', require: false gem 'opentelemetry-instrumentation-sidekiq', '~> 0.25.2', require: false gem 'opentelemetry-sdk', '~> 1.4', require: false diff --git a/Gemfile.lock b/Gemfile.lock index d855c05f43..e66077ff03 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -525,7 +525,7 @@ GEM opentelemetry-instrumentation-active_record (0.7.2) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-active_support (0.5.1) + opentelemetry-instrumentation-active_support (0.6.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-base (0.22.3) @@ -556,14 +556,14 @@ GEM opentelemetry-instrumentation-rack (0.24.5) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-rails (0.30.2) + opentelemetry-instrumentation-rails (0.31.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-action_mailer (~> 0.1.0) opentelemetry-instrumentation-action_pack (~> 0.9.0) opentelemetry-instrumentation-action_view (~> 0.7.0) opentelemetry-instrumentation-active_job (~> 0.7.0) opentelemetry-instrumentation-active_record (~> 0.7.0) - opentelemetry-instrumentation-active_support (~> 0.5.0) + opentelemetry-instrumentation-active_support (~> 0.6.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-redis (0.25.6) opentelemetry-api (~> 1.0) @@ -995,7 +995,7 @@ DEPENDENCIES opentelemetry-instrumentation-net_http (~> 0.22.4) opentelemetry-instrumentation-pg (~> 0.27.1) opentelemetry-instrumentation-rack (~> 0.24.1) - opentelemetry-instrumentation-rails (~> 0.30.0) + opentelemetry-instrumentation-rails (~> 0.31.0) opentelemetry-instrumentation-redis (~> 0.25.3) opentelemetry-instrumentation-sidekiq (~> 0.25.2) opentelemetry-sdk (~> 1.4) From dd85e3bcc5e04a11775cbdd9cb1f7d3577ddd9d7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 07:30:30 +0000 Subject: [PATCH 05/19] New Crowdin Translations (automated) (#30901) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/uk.json | 5 +++++ config/locales/cs.yml | 2 +- config/locales/simple_form.cs.yml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 338b650617..150b808f89 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -35,7 +35,9 @@ "account.follow_back": "Підписатися взаємно", "account.followers": "Підписники", "account.followers.empty": "Ніхто ще не підписаний на цього користувача.", + "account.followers_counter": "{count, plural, one {{counter} підписник} few {{counter} підписники} many {{counter} підписників} other {{counter} підписники}}", "account.following": "Ви стежите", + "account.following_counter": "{count, plural, one {{counter} підписка} few {{counter} підписки} many {{counter} підписок} other {{counter} підписки}}", "account.follows.empty": "Цей користувач ще ні на кого не підписався.", "account.go_to_profile": "Перейти до профілю", "account.hide_reblogs": "Сховати поширення від @{name}", @@ -61,6 +63,7 @@ "account.requested_follow": "{name} надсилає запит на стеження", "account.share": "Поділитися профілем @{name}", "account.show_reblogs": "Показати поширення від @{name}", + "account.statuses_counter": "{count, plural, one {{counter} допис} few {{counter} дописи} many {{counter} дописів} other {{counter} допис}}", "account.unblock": "Розблокувати @{name}", "account.unblock_domain": "Розблокувати {domain}", "account.unblock_short": "Розблокувати", @@ -412,6 +415,7 @@ "limited_account_hint.title": "Цей профіль сховали модератори {domain}.", "link_preview.author": "Від {name}", "link_preview.more_from_author": "Більше від {name}", + "link_preview.shares": "{count, plural, one {{counter} допис} few {{counter} дописи} many {{counter} дописів} other {{counter} допис}}", "lists.account.add": "Додати до списку", "lists.account.remove": "Вилучити зі списку", "lists.delete": "Видалити список", @@ -695,6 +699,7 @@ "server_banner.is_one_of_many": "{domain} - один з багатьох незалежних серверів Mastodon, які ви можете використати, щоб брати участь у федівері.", "server_banner.server_stats": "Статистика сервера:", "sign_in_banner.create_account": "Створити обліковий запис", + "sign_in_banner.follow_anyone": "Слідкуйте за ким завгодно у всьому fediverse і дивіться все це в хронологічному порядку. Немає алгоритмів, реклами чи наживок для натискань при перегляді.", "sign_in_banner.mastodon_is": "Мастодон - найкращий спосіб продовжувати свою справу.", "sign_in_banner.sign_in": "Увійти", "sign_in_banner.sso_redirect": "Увійдіть або зареєструйтесь", diff --git a/config/locales/cs.yml b/config/locales/cs.yml index f3b8f27d80..20e7e4d46b 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -81,7 +81,7 @@ cs: invite_request_text: Důvody založení invited_by: Pozván uživatelem ip: IP adresa - joined: Uživatel založen + joined: Uživatelem od location: all: Všechny local: Místní diff --git a/config/locales/simple_form.cs.yml b/config/locales/simple_form.cs.yml index 0b1a34e1b9..f8422102f1 100644 --- a/config/locales/simple_form.cs.yml +++ b/config/locales/simple_form.cs.yml @@ -59,7 +59,7 @@ cs: setting_display_media_default: Skrývat média označená jako citlivá setting_display_media_hide_all: Vždy skrývat média setting_display_media_show_all: Vždy zobrazovat média - setting_use_blurhash: Gradienty jsou založeny na barvách skryté grafiky, ale zakrývají jakékoliv detaily + setting_use_blurhash: Gradienty jsou vytvořeny na základě barvev skrytých médií, ale zakrývají veškeré detaily setting_use_pending_items: Aktualizovat časovou osu až po kliknutí namísto automatického rolování kanálu username: Pouze písmena, číslice a podtržítka whole_word: Je-li klíčové slovo či fráze pouze alfanumerická, bude aplikován pouze, pokud se shoduje s celým slovem From 5651c16d11a3bb35e44c260b0c18afcd451fd5aa Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 3 Jul 2024 03:47:40 -0400 Subject: [PATCH 06/19] Limit `browser` version to enforce ruby 3.1 support (#30766) --- Gemfile | 2 +- Gemfile.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index d1a8c2c5a4..769f834f46 100644 --- a/Gemfile +++ b/Gemfile @@ -25,7 +25,7 @@ gem 'ruby-vips', '~> 2.2', require: false gem 'active_model_serializers', '~> 0.10' gem 'addressable', '~> 2.8' gem 'bootsnap', '~> 1.18.0', require: false -gem 'browser' +gem 'browser', '< 6' # https://github.com/fnando/browser/issues/543 gem 'charlock_holmes', '~> 0.7.7' gem 'chewy', '~> 7.3' gem 'devise', '~> 4.9' diff --git a/Gemfile.lock b/Gemfile.lock index e66077ff03..aafad69ed7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -917,7 +917,7 @@ DEPENDENCIES blurhash (~> 0.1) bootsnap (~> 1.18.0) brakeman (~> 6.0) - browser + browser (< 6) bundler-audit (~> 0.9) capybara (~> 3.39) charlock_holmes (~> 0.7.7) From 1dbffc30f12d20f3c5f038c72b06967480f82129 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 08:04:38 +0000 Subject: [PATCH 07/19] chore(deps): update opentelemetry-ruby (non-major) (#30903) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index aafad69ed7..30835adef7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -516,7 +516,7 @@ GEM opentelemetry-api (~> 1.0) opentelemetry-instrumentation-active_support (~> 0.1) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-active_job (0.7.1) + opentelemetry-instrumentation-active_job (0.7.2) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-active_model_serializers (0.20.1) @@ -568,7 +568,7 @@ GEM opentelemetry-instrumentation-redis (0.25.6) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-sidekiq (0.25.5) + opentelemetry-instrumentation-sidekiq (0.25.6) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-registry (0.3.1) From 6270281037c1f0991bfbf8d195280be3f5733bf3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 08:05:19 +0000 Subject: [PATCH 08/19] chore(deps): update dependency doorkeeper to v5.7.1 (#30053) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 30835adef7..6444e46876 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -208,7 +208,7 @@ GEM activerecord (>= 4.2, < 8) docile (1.4.0) domain_name (0.6.20240107) - doorkeeper (5.6.9) + doorkeeper (5.7.1) railties (>= 5) dotenv (3.1.2) drb (2.2.1) @@ -431,7 +431,7 @@ GEM mime-types-data (3.2024.0604) mini_mime (1.1.5) mini_portile2 (2.8.7) - minitest (5.23.1) + minitest (5.24.1) msgpack (1.7.2) multi_json (1.15.0) multipart-post (2.4.0) From f99159d1eb671d72138edc42d11cd58472c33aec Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:46:51 +0200 Subject: [PATCH 09/19] fix(deps): update dependency webpack-merge to v6 (#30891) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 0379c7a5f5..404c4f486f 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "webpack-assets-manifest": "^4.0.6", "webpack-bundle-analyzer": "^4.8.0", "webpack-cli": "^3.3.12", - "webpack-merge": "^5.9.0", + "webpack-merge": "^6.0.0", "wicg-inert": "^3.1.2", "workbox-expiration": "^7.0.0", "workbox-precaching": "^7.0.0", diff --git a/yarn.lock b/yarn.lock index 9d19cb837e..8e72138a15 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2901,7 +2901,7 @@ __metadata: webpack-bundle-analyzer: "npm:^4.8.0" webpack-cli: "npm:^3.3.12" webpack-dev-server: "npm:^3.11.3" - webpack-merge: "npm:^5.9.0" + webpack-merge: "npm:^6.0.0" wicg-inert: "npm:^3.1.2" workbox-expiration: "npm:^7.0.0" workbox-precaching: "npm:^7.0.0" @@ -17928,14 +17928,14 @@ __metadata: languageName: node linkType: hard -"webpack-merge@npm:^5.9.0": - version: 5.10.0 - resolution: "webpack-merge@npm:5.10.0" +"webpack-merge@npm:^6.0.0": + version: 6.0.1 + resolution: "webpack-merge@npm:6.0.1" dependencies: clone-deep: "npm:^4.0.1" flat: "npm:^5.0.2" - wildcard: "npm:^2.0.0" - checksum: 10c0/b607c84cabaf74689f965420051a55a08722d897bdd6c29cb0b2263b451c090f962d41ecf8c9bf56b0ab3de56e65476ace0a8ecda4f4a4663684243d90e0512b + wildcard: "npm:^2.0.1" + checksum: 10c0/bf1429567858b353641801b8a2696ca0aac270fc8c55d4de8a7b586fe07d27fdcfc83099a98ab47e6162383db8dd63bb8cc25b1beb2ec82150422eec843b0dc0 languageName: node linkType: hard @@ -18183,7 +18183,7 @@ __metadata: languageName: node linkType: hard -"wildcard@npm:^2.0.0": +"wildcard@npm:^2.0.1": version: 2.0.1 resolution: "wildcard@npm:2.0.1" checksum: 10c0/08f70cd97dd9a20aea280847a1fe8148e17cae7d231640e41eb26d2388697cbe65b67fd9e68715251c39b080c5ae4f76d71a9a69fa101d897273efdfb1b58bf7 From 20c749bd45286fbf0aca5610562e5dc6f2c616dd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 11:14:15 +0200 Subject: [PATCH 10/19] chore(deps): update dependency rubocop-rspec to v3.0.2 (#30902) 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 6444e46876..ca36c8cf95 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -757,7 +757,7 @@ GEM rack (>= 1.1) rubocop (>= 1.33.0, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rspec (3.0.1) + rubocop-rspec (3.0.2) rubocop (~> 1.61) rubocop-rspec_rails (2.30.0) rubocop (~> 1.61) From 9be77fc0dbb01c1a8a54cd3da97e16c7941df367 Mon Sep 17 00:00:00 2001 From: David Roetzel Date: Wed, 3 Jul 2024 15:36:42 +0200 Subject: [PATCH 11/19] Revert "Add system check for missing database indexes" (#30909) --- Gemfile | 1 - Gemfile.lock | 2 - app/lib/admin/db/schema_parser.rb | 92 ------------------- app/lib/admin/system_check.rb | 1 - .../system_check/missing_indexes_check.rb | 36 -------- config/locales/en.yml | 2 - spec/lib/admin/db/schema_parser_spec.rb | 49 ---------- .../missing_indexes_check_spec.rb | 65 ------------- 8 files changed, 248 deletions(-) delete mode 100644 app/lib/admin/db/schema_parser.rb delete mode 100644 app/lib/admin/system_check/missing_indexes_check.rb delete mode 100644 spec/lib/admin/db/schema_parser_spec.rb delete mode 100644 spec/lib/admin/system_check/missing_indexes_check_spec.rb diff --git a/Gemfile b/Gemfile index 769f834f46..ef52d50cac 100644 --- a/Gemfile +++ b/Gemfile @@ -229,4 +229,3 @@ gem 'rubyzip', '~> 2.3' gem 'hcaptcha', '~> 7.1' gem 'mail', '~> 2.8' -gem 'prism' diff --git a/Gemfile.lock b/Gemfile.lock index ca36c8cf95..eb6720e454 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -600,7 +600,6 @@ GEM actionmailer (>= 3) net-smtp premailer (~> 1.7, >= 1.7.9) - prism (0.30.0) propshaft (0.9.0) actionpack (>= 7.0.0) activesupport (>= 7.0.0) @@ -1004,7 +1003,6 @@ DEPENDENCIES pg (~> 1.5) pghero premailer-rails - prism propshaft public_suffix (~> 6.0) puma (~> 6.3) diff --git a/app/lib/admin/db/schema_parser.rb b/app/lib/admin/db/schema_parser.rb deleted file mode 100644 index e61a2281ee..0000000000 --- a/app/lib/admin/db/schema_parser.rb +++ /dev/null @@ -1,92 +0,0 @@ -# frozen_string_literal: true - -class Admin::Db::SchemaParser - class Index - attr_reader :name, :table_name, :columns, :options - - def initialize(name:, table_name:, columns:, options:) - @name = name - @table_name = table_name - @columns = columns - @options = options - end - end - - attr_reader :indexes_by_table - - def initialize(source) - parse(source) - end - - private - - def parse(source) - @indexes_by_table = {} - queue = [Prism.parse(source).value] - while (node = queue.shift) - if node.type == :call_node && node.name == :create_table - parse_create_table(node) - elsif node.type == :call_node && node.name == :add_index - parse_add_index(node) - else - queue.concat(node.compact_child_nodes) - end - end - end - - def parse_create_table(node) - table_name = parse_arguments(node).first - queue = node.compact_child_nodes - while (node = queue.shift) - if node.type == :call_node && node.name == :index - parse_index(node, table_name:) - else - queue.concat(node.compact_child_nodes) - end - end - end - - def parse_index(node, table_name:) - arguments = parse_arguments(node) - save_index( - name: arguments.last[:name], - table_name: table_name, - columns: arguments.first, - options: arguments.last - ) - end - - def parse_add_index(node) - arguments = parse_arguments(node) - save_index( - name: arguments.last[:name], - table_name: arguments.first, - columns: arguments[1], - options: arguments.last - ) - end - - def parse_arguments(node) - node.arguments.arguments.map { |a| parse_argument(a) } - end - - def parse_argument(argument) - case argument - when Prism::StringNode - argument.unescaped - when Prism::SymbolNode - argument.unescaped.to_sym - when Prism::ArrayNode - argument.elements.map { |e| parse_argument(e) } - when Prism::KeywordHashNode - argument.elements.to_h do |element| - [element.key.unescaped.to_sym, parse_argument(element.value)] - end - end - end - - def save_index(name:, table_name:, columns:, options:) - @indexes_by_table[table_name] ||= [] - @indexes_by_table[table_name] << Index.new(name:, table_name:, columns:, options:) - end -end diff --git a/app/lib/admin/system_check.rb b/app/lib/admin/system_check.rb index 453011f7a6..25c88341a4 100644 --- a/app/lib/admin/system_check.rb +++ b/app/lib/admin/system_check.rb @@ -8,7 +8,6 @@ class Admin::SystemCheck Admin::SystemCheck::SidekiqProcessCheck, Admin::SystemCheck::RulesCheck, Admin::SystemCheck::ElasticsearchCheck, - Admin::SystemCheck::MissingIndexesCheck, ].freeze def self.perform(current_user) diff --git a/app/lib/admin/system_check/missing_indexes_check.rb b/app/lib/admin/system_check/missing_indexes_check.rb deleted file mode 100644 index b7eecbb067..0000000000 --- a/app/lib/admin/system_check/missing_indexes_check.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -class Admin::SystemCheck::MissingIndexesCheck < Admin::SystemCheck::BaseCheck - def skip? - !current_user.can?(:view_devops) - end - - def pass? - missing_indexes.none? - end - - def message - Admin::SystemCheck::Message.new(:missing_indexes_check, missing_indexes.join(', ')) - end - - private - - def missing_indexes - @missing_indexes ||= begin - expected_indexes_by_table.flat_map do |table, indexes| - expected_indexes = indexes.map(&:name) - expected_indexes - existing_indexes_for(table) - end - end - end - - def expected_indexes_by_table - schema_rb = Rails.root.join('db', 'schema.rb').read - schema_parser = Admin::Db::SchemaParser.new(schema_rb) - schema_parser.indexes_by_table - end - - def existing_indexes_for(table) - ActiveRecord::Base.connection.indexes(table).map(&:name) - end -end diff --git a/config/locales/en.yml b/config/locales/en.yml index 270382dd11..20df80c272 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -862,8 +862,6 @@ en: elasticsearch_version_check: message_html: 'Incompatible Elasticsearch version: %{value}' version_comparison: Elasticsearch %{running_version} is running while %{required_version} is required - missing_indexes_check: - message_html: 'The following indexes are missing from the database and should be recreated: %{value}.
Missing indexes may lead to severely reduced performance and data inconsistencies.' rules_check: action: Manage server rules message_html: You haven't defined any server rules. diff --git a/spec/lib/admin/db/schema_parser_spec.rb b/spec/lib/admin/db/schema_parser_spec.rb deleted file mode 100644 index e28d5c1f97..0000000000 --- a/spec/lib/admin/db/schema_parser_spec.rb +++ /dev/null @@ -1,49 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe Admin::Db::SchemaParser do - let(:dummy_schema) do - <<~SCHEMA - # Comment - ActiveRecord::Schema[7.1].define(version: 23) do - create_table "people", force: :cascade do |t| - t.string "name" - end - - create_table "posts", force: :cascade do |t| - t.string "title", null: false - t.bigint "size", null: false - t.string "description" - # t.index ["size", "title"], name: "index_posts_on_size_and_title" - t.index ["title"], name: "index_posts_on_title", unique: true - t.index ["size"], name: "index_posts_on_size" - end - - # add_index "people", ["name"], name: "commented_out_index" - add_index "people", ["name"], name: "index_people_on_name" - end - SCHEMA - end - let(:schema_parser) { described_class.new(dummy_schema) } - - describe '#indexes_by_table' do - subject { schema_parser.indexes_by_table } - - it 'returns index info for all affected tables' do - expect(subject.keys).to match_array(%w(people posts)) - end - - it 'returns all index information for the `people` table' do - people_info = subject['people'] - expect(people_info.map(&:name)).to contain_exactly('index_people_on_name') - end - - it 'returns all index information for the `posts` table' do - posts_info = subject['posts'] - expect(posts_info.map(&:name)).to contain_exactly( - 'index_posts_on_title', 'index_posts_on_size' - ) - end - end -end diff --git a/spec/lib/admin/system_check/missing_indexes_check_spec.rb b/spec/lib/admin/system_check/missing_indexes_check_spec.rb deleted file mode 100644 index e183be5620..0000000000 --- a/spec/lib/admin/system_check/missing_indexes_check_spec.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe Admin::SystemCheck::MissingIndexesCheck do - subject(:check) { described_class.new(user) } - - let(:user) { Fabricate(:user) } - let(:schema_parser) do - instance_double(Admin::Db::SchemaParser, indexes_by_table: index_info) - end - let(:index_info) do - { - 'users' => [instance_double(Admin::Db::SchemaParser::Index, name: 'index_users_on_profile_id')], - 'posts' => [instance_double(Admin::Db::SchemaParser::Index, name: 'index_posts_on_user_id')], - } - end - let(:posts_indexes) { [] } - let(:users_indexes) { [] } - - before do - allow(Admin::Db::SchemaParser).to receive(:new).and_return(schema_parser) - allow(ActiveRecord::Base.connection).to receive(:indexes).with('posts').and_return(posts_indexes) - allow(ActiveRecord::Base.connection).to receive(:indexes).with('users').and_return(users_indexes) - end - - it_behaves_like 'a check available to devops users' - - describe '#pass?' do - context 'when indexes are missing' do - let(:posts_indexes) do - [instance_double(ActiveRecord::ConnectionAdapters::IndexDefinition, name: 'index_posts_on_user_id')] - end - - it 'returns false' do - expect(check.pass?).to be false - end - end - - context 'when all expected indexes are present' do - let(:posts_indexes) do - [instance_double(ActiveRecord::ConnectionAdapters::IndexDefinition, name: 'index_posts_on_user_id')] - end - let(:users_indexes) do - [instance_double(ActiveRecord::ConnectionAdapters::IndexDefinition, name: 'index_users_on_profile_id')] - end - - it 'returns true' do - expect(check.pass?).to be true - end - end - end - - describe '#message' do - subject { check.message } - - it 'sets the class name as the message key' do - expect(subject.key).to eq(:missing_indexes_check) - end - - it 'sets a list of missing indexes as message value' do - expect(subject.value).to eq('index_users_on_profile_id, index_posts_on_user_id') - end - end -end From 47f0faebc9cb197ea7b4cf8d191df0a1ec926f59 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Wed, 3 Jul 2024 22:05:59 +0200 Subject: [PATCH 12/19] Implement HTML ruby tags for east-asian languages (#30897) --- lib/sanitize_ext/sanitize_config.rb | 2 +- spec/lib/html_aware_formatter_spec.rb | 8 ++++++++ spec/lib/plain_text_formatter_spec.rb | 8 ++++++++ spec/lib/sanitize/config_spec.rb | 4 ++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/sanitize_ext/sanitize_config.rb b/lib/sanitize_ext/sanitize_config.rb index 70efe7c1ae..3379823cb7 100644 --- a/lib/sanitize_ext/sanitize_config.rb +++ b/lib/sanitize_ext/sanitize_config.rb @@ -65,7 +65,7 @@ class Sanitize end MASTODON_STRICT = freeze_config( - elements: %w(p br span a del pre blockquote code b strong u i em ul ol li), + elements: %w(p br span a del pre blockquote code b strong u i em ul ol li ruby rt rp), attributes: { 'a' => %w(href rel class translate), diff --git a/spec/lib/html_aware_formatter_spec.rb b/spec/lib/html_aware_formatter_spec.rb index a20902d4f9..b75ccb06e7 100644 --- a/spec/lib/html_aware_formatter_spec.rb +++ b/spec/lib/html_aware_formatter_spec.rb @@ -41,6 +41,14 @@ RSpec.describe HtmlAwareFormatter do expect(subject).to_not include 'status__content__spoiler-link' end end + + context 'when given text containing ruby tags for east-asian languages' do + let(:text) { '明日 (Ashita)' } + + it 'keeps the ruby tags' do + expect(subject).to eq '明日 (Ashita)' + end + end end end end diff --git a/spec/lib/plain_text_formatter_spec.rb b/spec/lib/plain_text_formatter_spec.rb index 80b3c331a6..b22f473d0c 100644 --- a/spec/lib/plain_text_formatter_spec.rb +++ b/spec/lib/plain_text_formatter_spec.rb @@ -72,6 +72,14 @@ RSpec.describe PlainTextFormatter do expect(subject).to eq 'Lorem ipsum' end end + + context 'when text contains HTML ruby tags' do + let(:status) { Fabricate(:status, account: remote_account, text: '

Lorem 明日 (Ashita) ipsum

') } + + it 'strips the comment' do + expect(subject).to eq 'Lorem 明日 (Ashita) ipsum' + end + end end end end diff --git a/spec/lib/sanitize/config_spec.rb b/spec/lib/sanitize/config_spec.rb index 2d8dc2f63b..fe0b272c0a 100644 --- a/spec/lib/sanitize/config_spec.rb +++ b/spec/lib/sanitize/config_spec.rb @@ -18,6 +18,10 @@ describe Sanitize::Config do expect(Sanitize.fragment('

Check out:

  1. Foo
  2. Bar
', subject)).to eq '

Check out:

  1. Foo
  2. Bar
' end + it 'keeps ruby tags' do + expect(Sanitize.fragment('

明日 (Ashita)

', subject)).to eq '

明日 (Ashita)

' + end + it 'removes a without href' do expect(Sanitize.fragment('Test', subject)).to eq 'Test' end From 8331f9e379220847020aed9cd0a8a1d6ab0e7d43 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 4 Jul 2024 10:46:27 +0200 Subject: [PATCH 13/19] New Crowdin Translations (automated) (#30916) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/gl.json | 2 +- app/javascript/mastodon/locales/he.json | 8 +++++++- app/javascript/mastodon/locales/ia.json | 4 ++-- app/javascript/mastodon/locales/sr-Latn.json | 3 +++ app/javascript/mastodon/locales/sr.json | 3 +++ config/locales/ia.yml | 8 ++++---- config/locales/simple_form.ja.yml | 2 +- 7 files changed, 21 insertions(+), 9 deletions(-) diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index fae48ed06b..03287c7e52 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -224,7 +224,7 @@ "domain_pill.their_server": "O seu fogar dixital, onde están as súas publicacións.", "domain_pill.their_username": "O seu identificador único no seu servidor. É posible atopar usuarias co mesmo nome de usuaria en diferentes servidores.", "domain_pill.username": "Nome de usuaria", - "domain_pill.whats_in_a_handle": "Que é o alcume?", + "domain_pill.whats_in_a_handle": "As partes do alcume?", "domain_pill.who_they_are": "O alcume dinos quen é esa persoa e onde está, para que poidas interactuar con ela en toda a web social de .", "domain_pill.who_you_are": "Como o teu alcume informa de quen es e onde estás, as persoas poden interactuar contigo desde toda a web social de .", "domain_pill.your_handle": "O teu alcume:", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index e022eac110..8111a56e89 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -35,7 +35,9 @@ "account.follow_back": "לעקוב בחזרה", "account.followers": "עוקבים", "account.followers.empty": "אף אחד לא עוקב אחר המשתמש הזה עדיין.", + "account.followers_counter": "{count, plural,one {עוקב אחד} other {{count} עוקבים}}", "account.following": "נעקבים", + "account.following_counter": "{count, plural,one {עוקב אחרי {count}}other {עוקב אחרי {count}}}", "account.follows.empty": "משתמש זה עדיין לא עוקב אחרי אף אחד.", "account.go_to_profile": "מעבר לפרופיל", "account.hide_reblogs": "להסתיר הידהודים מאת @{name}", @@ -61,6 +63,7 @@ "account.requested_follow": "{name} ביקשו לעקוב אחריך", "account.share": "שתף את הפרופיל של @{name}", "account.show_reblogs": "הצג הדהודים מאת @{name}", + "account.statuses_counter": "{count, plural, one {הודעה אחת} two {הודעותיים} many {{count} הודעות} other {{count} הודעות}}", "account.unblock": "להסיר חסימה ל- @{name}", "account.unblock_domain": "הסירי את החסימה של קהילת {domain}", "account.unblock_short": "הסר חסימה", @@ -693,8 +696,11 @@ "server_banner.about_active_users": "משתמשים פעילים בשרת ב־30 הימים האחרונים (משתמשים פעילים חודשיים)", "server_banner.active_users": "משתמשים פעילים", "server_banner.administered_by": "מנוהל ע\"י:", + "server_banner.is_one_of_many": "{domain} הוא שרת אחד משרתי מסטודון עצמאיים רבים שדרגם תוכלו להשתתף בפדיוורס (רשת חברתית מבוזרת).", "server_banner.server_stats": "סטטיסטיקות שרת:", "sign_in_banner.create_account": "יצירת חשבון", + "sign_in_banner.follow_anyone": "תוכלו לעקוב אחרי כל משמתמש בפדיוורס ולקרוא הכל לפי סדר הפרסום בציר הזמן. אין אלגוריתמים, פרסומות, או קליקבייט מטעם בעלי הרשת.", + "sign_in_banner.mastodon_is": "מסטודון הוא הדרך הטובה ביותר לעקוב אחרי מה שקורה.", "sign_in_banner.sign_in": "התחברות", "sign_in_banner.sso_redirect": "התחברות/הרשמה", "status.admin_account": "פתח/י ממשק ניהול עבור @{name}", @@ -771,7 +777,7 @@ "timeline_hint.resources.followers": "עוקבים", "timeline_hint.resources.follows": "נעקבים", "timeline_hint.resources.statuses": "הודעות ישנות יותר", - "trends.counter_by_accounts": "{count, plural, one {אדם {count}} other {{count} א.נשים}} {days, plural, one {מאז אתמול} two {ביומיים האחרונים} other {במשך {days} הימים האחרונים}}", + "trends.counter_by_accounts": "{count, plural, one {אדם אחד} other {{count} א.נשים}} {days, plural, one {מאז אתמול} two {ביומיים האחרונים} other {במשך {days} הימים האחרונים}}", "trends.trending_now": "נושאים חמים", "ui.beforeunload": "הטיוטא תאבד אם תעזבו את מסטודון.", "units.short.billion": "{count} מליארד", diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index a2e64c10f1..ace6402ee1 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -354,7 +354,7 @@ "home.pending_critical_update.link": "Vider actualisationes", "home.pending_critical_update.title": "Actualisation de securitate critic disponibile!", "home.show_announcements": "Monstrar annuncios", - "interaction_modal.description.favourite": "Con un conto sur Mastodon, tu pote marcar iste message como favorite pro informar le autor que tu lo apprecia e salveguarda pro plus tarde.", + "interaction_modal.description.favourite": "Con un conto sur Mastodon, tu pote marcar iste message como favorite pro informar le autor que tu lo apprecia e lo salva pro plus tarde.", "interaction_modal.description.follow": "Con un conto sur Mastodon, tu pote sequer {name} e reciper su messages in tu fluxo de initio.", "interaction_modal.description.reblog": "Con un conto sur Mastodon, tu pote impulsar iste message pro condivider lo con tu proprie sequitores.", "interaction_modal.description.reply": "Con un conto sur Mastodon, tu pote responder a iste message.", @@ -764,7 +764,7 @@ "status.unmute_conversation": "Non plus silentiar conversation", "status.unpin": "Disfixar del profilo", "subscribed_languages.lead": "Solmente le messages in le linguas seligite apparera in tu chronologias de initio e de listas post le cambiamento. Selige necun pro reciper messages in tote le linguas.", - "subscribed_languages.save": "Salveguardar le cambiamentos", + "subscribed_languages.save": "Salvar le cambiamentos", "subscribed_languages.target": "Cambiar le linguas subscribite pro {target}", "tabs_bar.home": "Initio", "tabs_bar.notifications": "Notificationes", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index 93c3b8fe2e..71b69d428a 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -35,7 +35,9 @@ "account.follow_back": "Uzvrati praćenje", "account.followers": "Pratioci", "account.followers.empty": "Još uvek niko ne prati ovog korisnika.", + "account.followers_counter": "{count, plural, one {{counter} pratilac} few {{counter} pratioca} other {{counter} pratilaca}}", "account.following": "Prati", + "account.following_counter": "{count, plural, one {{counter} prati} few {{counter} prati} other {{counter} prati}}", "account.follows.empty": "Ovaj korisnik još uvek nikog ne prati.", "account.go_to_profile": "Idi na profil", "account.hide_reblogs": "Sakrij podržavanja @{name}", @@ -61,6 +63,7 @@ "account.requested_follow": "{name} je zatražio da vas prati", "account.share": "Podeli profil korisnika @{name}", "account.show_reblogs": "Prikaži podržavanja od korisnika @{name}", + "account.statuses_counter": "{count, plural, one {{counter} objava} few {{counter} objave} other {{counter} objava}}", "account.unblock": "Odblokiraj korisnika @{name}", "account.unblock_domain": "Odblokiraj domen {domain}", "account.unblock_short": "Odblokiraj", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index 0273002b37..2c4649f9d0 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -35,7 +35,9 @@ "account.follow_back": "Узврати праћење", "account.followers": "Пратиоци", "account.followers.empty": "Још увек нико не прати овог корисника.", + "account.followers_counter": "{count, plural, one {{counter} пратилац} few {{counter} пратиоца} other {{counter} пратилаца}}", "account.following": "Прати", + "account.following_counter": "{count, plural, one {{counter} прати} few {{counter} прати} other {{counter} прати}}", "account.follows.empty": "Овај корисник још увек никог не прати.", "account.go_to_profile": "Иди на профил", "account.hide_reblogs": "Сакриј подржавања од @{name}", @@ -61,6 +63,7 @@ "account.requested_follow": "{name} је затражио да вас прати", "account.share": "Подели профил корисника @{name}", "account.show_reblogs": "Прикажи подржавања од корисника @{name}", + "account.statuses_counter": "{count, plural, one {{counter} објава} few {{counter} објаве} other {{counter} објава}}", "account.unblock": "Одблокирај корисника @{name}", "account.unblock_domain": "Одблокирај домен {domain}", "account.unblock_short": "Одблокирај", diff --git a/config/locales/ia.yml b/config/locales/ia.yml index 4932d42acf..7350ffceeb 100644 --- a/config/locales/ia.yml +++ b/config/locales/ia.yml @@ -574,7 +574,7 @@ ia: enabled: Activate inbox_url: URL del repetitor pending: Attende le approbation del repetitor - save_and_enable: Salveguardar e activar + save_and_enable: Salvar e activar setup: Crear un connexion con un repetitor signatures_not_enabled: Le repetitores pote non functionar correctemente durante que le modo secur o le modo de federation limitate es activate status: Stato @@ -1276,7 +1276,7 @@ ia: other: "%{count} messages individual celate" title: Filtros new: - save: Salveguardar nove filtro + save: Salvar nove filtro title: Adder nove filtro statuses: back_to_filter: Retro al filtro @@ -1294,14 +1294,14 @@ ia: one: "%{count} elemento correspondente al recerca es seligite." other: Tote le %{count} elementos correspondente al recerca es seligite. cancel: Cancellar - changes_saved_msg: Cambios salveguardate con successo! + changes_saved_msg: Le cambiamentos ha essite salvate! confirm: Confirmar copy: Copiar delete: Deler deselect: Deseliger toto none: Necun order_by: Ordinar per - save_changes: Salvar le cambios + save_changes: Salvar le cambiamentos select_all_matching_items: one: Selige %{count} elemento correspondente a tu recerca. other: Selige %{count} elementos correspondente a tu recerca. diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index c0698c3f7a..664082dabc 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -81,7 +81,7 @@ ja: backups_retention_period: ユーザーには、後でダウンロードするために投稿のアーカイブを生成する機能があります。正の値に設定すると、これらのアーカイブは指定された日数後に自動的にストレージから削除されます。 bootstrap_timeline_accounts: これらのアカウントは、新しいユーザー向けのおすすめユーザーの一番上にピン留めされます。 closed_registrations_message: アカウント作成を停止している時に表示されます - content_cache_retention_period: 他のサーバーからのすべての投稿(ブーストや返信を含む)は、指定された日数が経過すると、ローカルユーザーとのやりとりに関係なく削除されます。これには、ローカルユーザーがブックマークやお気に入りとして登録した投稿も含まれます。異なるサーバーのユーザー間の非公開な変身も失われ、復元することは不可能です。この設定の使用は特別な目的のインスタンスのためのものであり、一般的な目的のサーバーで使用するした場合、多くのユーザーの期待を裏切ることになります。 + content_cache_retention_period: 他のサーバーからのすべての投稿(ブーストや返信を含む)は、指定された日数が経過すると、ローカルユーザーとのやりとりに関係なく削除されます。これには、ローカルユーザーがブックマークやお気に入りとして登録した投稿も含まれます。異なるサーバーのユーザー間の非公開な返信も失われ、復元することは不可能です。この設定の使用は特別な目的のインスタンスのためのものであり、一般的な目的のサーバーで使用した場合、多くのユーザーの期待を裏切ることになります。 custom_css: ウェブ版のMastodonでカスタムスタイルを適用できます。 favicon: デフォルトのMastodonのブックマークアイコンを独自のアイコンで上書きします。WEBP、PNG、GIF、JPGが利用可能です。 mascot: 上級者向けWebインターフェースのイラストを上書きします。 From 528661a091bbef5b5359bfacd1478231a1cb7d10 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:46:08 +0200 Subject: [PATCH 14/19] fix(deps): update dependency pino-http to v10.2.0 (#30913) 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 8e72138a15..52a8fff72f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13139,14 +13139,14 @@ __metadata: linkType: hard "pino-http@npm:^10.0.0": - version: 10.1.0 - resolution: "pino-http@npm:10.1.0" + version: 10.2.0 + resolution: "pino-http@npm:10.2.0" dependencies: get-caller-file: "npm:^2.0.5" pino: "npm:^9.0.0" pino-std-serializers: "npm:^7.0.0" process-warning: "npm:^3.0.0" - checksum: 10c0/d97691f2ee248b0aca0e49169d0c7ca0d4c604ee57b63ae264a6f9914fc7277cace74686d5088a876f8152a8d5b8211af904b2d24a516728a662de0e9cc79e9f + checksum: 10c0/0b79cd3602531ee5043693e2a3ccf9d955bd93759e80c0b3a458b95b241f36ca8ebc72c8050b395e9d8fcb9581ebc18ecd6b7dc136526bebe924bc5c5079374d languageName: node linkType: hard From b73014761807f3171b7ecb46052e9aa618b9c029 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:46:14 +0200 Subject: [PATCH 15/19] fix(deps): update dependency ws to v8.18.0 (#30914) 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 52a8fff72f..d61ef41632 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18491,8 +18491,8 @@ __metadata: linkType: hard "ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.17.0": - version: 8.17.1 - resolution: "ws@npm:8.17.1" + version: 8.18.0 + resolution: "ws@npm:8.18.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -18501,7 +18501,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 10c0/f4a49064afae4500be772abdc2211c8518f39e1c959640457dcee15d4488628620625c783902a52af2dd02f68558da2868fd06e6fd0e67ebcd09e6881b1b5bfe + checksum: 10c0/25eb33aff17edcb90721ed6b0eb250976328533ad3cd1a28a274bd263682e7296a6591ff1436d6cbc50fa67463158b062f9d1122013b361cec99a05f84680e06 languageName: node linkType: hard From 395f17ca17b27f9e722425a4d76ef1b02bcebea8 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 4 Jul 2024 16:11:28 +0200 Subject: [PATCH 16/19] Merge pull request from GHSA-vp5r-5pgw-jwqx * Fix streaming sessions not being closed when revoking access to an app * Add tests for GHSA-7w3c-p9j8-mq3x --- .../oauth/authorized_applications_controller.rb | 1 + app/lib/application_extension.rb | 8 +++++--- .../oauth/authorized_applications_controller_spec.rb | 6 ++++++ .../settings/applications_controller_spec.rb | 10 +++++++++- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index 8440df6b7e..7bb22453ca 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -17,6 +17,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio def destroy Web::PushSubscription.unsubscribe_for(params[:id], current_resource_owner) + Doorkeeper::Application.find_by(id: params[:id])&.close_streaming_sessions(current_resource_owner) super end diff --git a/app/lib/application_extension.rb b/app/lib/application_extension.rb index 2fea1057cb..d7aaeba5bd 100644 --- a/app/lib/application_extension.rb +++ b/app/lib/application_extension.rb @@ -16,7 +16,7 @@ module ApplicationExtension # dependent: delete_all, which means the ActiveRecord callback in # AccessTokenExtension is not run, so instead we manually announce to # streaming that these tokens are being deleted. - before_destroy :push_to_streaming_api, prepend: true + before_destroy :close_streaming_sessions, prepend: true end def confirmation_redirect_uri @@ -29,10 +29,12 @@ module ApplicationExtension redirect_uri.split end - def push_to_streaming_api + def close_streaming_sessions(resource_owner = nil) # TODO: #28793 Combine into a single topic payload = Oj.dump(event: :kill) - access_tokens.in_batches do |tokens| + scope = access_tokens + scope = scope.where(resource_owner_id: resource_owner.id) unless resource_owner.nil? + scope.in_batches do |tokens| redis.pipelined do |pipeline| tokens.ids.each do |id| pipeline.publish("timeline:access_token:#{id}", payload) diff --git a/spec/controllers/oauth/authorized_applications_controller_spec.rb b/spec/controllers/oauth/authorized_applications_controller_spec.rb index b46b944d0e..3fd9f9499f 100644 --- a/spec/controllers/oauth/authorized_applications_controller_spec.rb +++ b/spec/controllers/oauth/authorized_applications_controller_spec.rb @@ -50,9 +50,11 @@ describe Oauth::AuthorizedApplicationsController do let!(:application) { Fabricate(:application) } let!(:access_token) { Fabricate(:accessible_access_token, application: application, resource_owner_id: user.id) } let!(:web_push_subscription) { Fabricate(:web_push_subscription, user: user, access_token: access_token) } + let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) } before do sign_in user, scope: :user + allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub) post :destroy, params: { id: application.id } end @@ -67,5 +69,9 @@ describe Oauth::AuthorizedApplicationsController do it 'removes the web_push_subscription' do expect { web_push_subscription.reload }.to raise_error(ActiveRecord::RecordNotFound) end + + it 'sends a session kill payload to the streaming server' do + expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}') + end end end diff --git a/spec/controllers/settings/applications_controller_spec.rb b/spec/controllers/settings/applications_controller_spec.rb index ccbb634911..ce2e0749a7 100644 --- a/spec/controllers/settings/applications_controller_spec.rb +++ b/spec/controllers/settings/applications_controller_spec.rb @@ -147,14 +147,22 @@ describe Settings::ApplicationsController do end describe 'destroy' do + let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) } + let!(:access_token) { Fabricate(:accessible_access_token, application: app) } + before do + allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub) post :destroy, params: { id: app.id } end - it 'redirects back to applications page and removes the app' do + it 'redirects back to applications page removes the app' do expect(response).to redirect_to(settings_applications_path) expect(Doorkeeper::Application.find_by(id: app.id)).to be_nil end + + it 'sends a session kill payload to the streaming server' do + expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}') + end end describe 'regenerate' do From 502cf75b160c76f963a179d46498e3ea1a9fefca Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 4 Jul 2024 16:26:49 +0200 Subject: [PATCH 17/19] Merge pull request from GHSA-58x8-3qxw-6hm7 * Fix insufficient permission checking for public timeline endpoints Note that this changes unauthenticated access failure code from 401 to 422 * Add more tests for public timelines * Require user token in `/api/v1/statuses/:id/translate` and `/api/v1/scheduled_statuses` --- .../api/v1/scheduled_statuses_controller.rb | 1 + .../v1/statuses/translations_controller.rb | 1 + .../api/v1/timelines/base_controller.rb | 6 +++++ .../api/v1/timelines/link_controller.rb | 6 +---- .../api/v1/timelines/public_controller.rb | 6 +---- .../api/v1/timelines/tag_controller.rb | 2 +- spec/requests/api/v1/scheduled_status_spec.rb | 11 ++++++++ .../api/v1/statuses/translations_spec.rb | 16 ++++++++++++ spec/requests/api/v1/timelines/link_spec.rb | 20 +++++++++++--- spec/requests/api/v1/timelines/public_spec.rb | 26 ++++++++++++++----- spec/requests/api/v1/timelines/tag_spec.rb | 10 ++++--- 11 files changed, 82 insertions(+), 23 deletions(-) diff --git a/app/controllers/api/v1/scheduled_statuses_controller.rb b/app/controllers/api/v1/scheduled_statuses_controller.rb index 45ee586518..c62305d711 100644 --- a/app/controllers/api/v1/scheduled_statuses_controller.rb +++ b/app/controllers/api/v1/scheduled_statuses_controller.rb @@ -6,6 +6,7 @@ class Api::V1::ScheduledStatusesController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, except: [:update, :destroy] before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:update, :destroy] + before_action :require_user! before_action :set_statuses, only: :index before_action :set_status, except: :index diff --git a/app/controllers/api/v1/statuses/translations_controller.rb b/app/controllers/api/v1/statuses/translations_controller.rb index 7d406b0a36..8cf495f78a 100644 --- a/app/controllers/api/v1/statuses/translations_controller.rb +++ b/app/controllers/api/v1/statuses/translations_controller.rb @@ -2,6 +2,7 @@ class Api::V1::Statuses::TranslationsController < Api::V1::Statuses::BaseController before_action -> { doorkeeper_authorize! :read, :'read:statuses' } + before_action :require_user! before_action :set_translation rescue_from TranslationService::NotConfiguredError, with: :not_found diff --git a/app/controllers/api/v1/timelines/base_controller.rb b/app/controllers/api/v1/timelines/base_controller.rb index e79eba79ee..1dba4a5bb2 100644 --- a/app/controllers/api/v1/timelines/base_controller.rb +++ b/app/controllers/api/v1/timelines/base_controller.rb @@ -3,8 +3,14 @@ class Api::V1::Timelines::BaseController < Api::BaseController after_action :insert_pagination_headers, unless: -> { @statuses.empty? } + before_action :require_user!, if: :require_auth? + private + def require_auth? + !Setting.timeline_preview + end + def pagination_collection @statuses end diff --git a/app/controllers/api/v1/timelines/link_controller.rb b/app/controllers/api/v1/timelines/link_controller.rb index af962c430f..37ed084f06 100644 --- a/app/controllers/api/v1/timelines/link_controller.rb +++ b/app/controllers/api/v1/timelines/link_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Api::V1::Timelines::LinkController < Api::V1::Timelines::BaseController - before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :show, if: :require_auth? + before_action -> { authorize_if_got_token! :read, :'read:statuses' } before_action :set_preview_card before_action :set_statuses @@ -17,10 +17,6 @@ class Api::V1::Timelines::LinkController < Api::V1::Timelines::BaseController private - def require_auth? - !Setting.timeline_preview - end - def set_preview_card @preview_card = PreviewCard.joins(:trend).merge(PreviewCardTrend.allowed).find_by!(url: params[:url]) end diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb index d164854d6a..029e8fc2c1 100644 --- a/app/controllers/api/v1/timelines/public_controller.rb +++ b/app/controllers/api/v1/timelines/public_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController - before_action :require_user!, only: [:show], if: :require_auth? + before_action -> { authorize_if_got_token! :read, :'read:statuses' } PERMITTED_PARAMS = %i(local remote limit only_media).freeze @@ -13,10 +13,6 @@ class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController private - def require_auth? - !Setting.timeline_preview - end - def load_statuses preloaded_public_statuses_page end diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb index 3bf8f374e1..2b097aab0f 100644 --- a/app/controllers/api/v1/timelines/tag_controller.rb +++ b/app/controllers/api/v1/timelines/tag_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController - before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :show, if: :require_auth? + before_action -> { authorize_if_got_token! :read, :'read:statuses' } before_action :load_tag PERMITTED_PARAMS = %i(local limit only_media).freeze diff --git a/spec/requests/api/v1/scheduled_status_spec.rb b/spec/requests/api/v1/scheduled_status_spec.rb index 49ccde275c..f4612410bf 100644 --- a/spec/requests/api/v1/scheduled_status_spec.rb +++ b/spec/requests/api/v1/scheduled_status_spec.rb @@ -25,6 +25,17 @@ describe 'Scheduled Statuses' do it_behaves_like 'forbidden for wrong scope', 'write write:statuses' end + context 'with an application token' do + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: 'read:statuses') } + + it 'returns http unprocessable entity' do + get api_v1_scheduled_statuses_path, headers: headers + + expect(response) + .to have_http_status(422) + end + end + context 'with correct scope' do let(:scopes) { 'read:statuses' } diff --git a/spec/requests/api/v1/statuses/translations_spec.rb b/spec/requests/api/v1/statuses/translations_spec.rb index 5b0a994561..e2ab5d0b80 100644 --- a/spec/requests/api/v1/statuses/translations_spec.rb +++ b/spec/requests/api/v1/statuses/translations_spec.rb @@ -8,6 +8,22 @@ describe 'API V1 Statuses Translations' do let(:scopes) { 'read:statuses' } let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } + context 'with an application token' do + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: scopes) } + + describe 'POST /api/v1/statuses/:status_id/translate' do + let(:status) { Fabricate(:status, account: user.account, text: 'Hola', language: 'es') } + + before do + post "/api/v1/statuses/#{status.id}/translate", headers: headers + end + + it 'returns http unprocessable entity' do + expect(response).to have_http_status(422) + end + end + end + context 'with an oauth token' do describe 'POST /api/v1/statuses/:status_id/translate' do let(:status) { Fabricate(:status, account: user.account, text: 'Hola', language: 'es') } diff --git a/spec/requests/api/v1/timelines/link_spec.rb b/spec/requests/api/v1/timelines/link_spec.rb index a219c9bcdd..e1c914ab81 100644 --- a/spec/requests/api/v1/timelines/link_spec.rb +++ b/spec/requests/api/v1/timelines/link_spec.rb @@ -41,6 +41,8 @@ describe 'Link' do end end + it_behaves_like 'forbidden for wrong scope', 'profile' + context 'when there is no preview card' do let(:preview_card) { nil } @@ -80,13 +82,25 @@ describe 'Link' do Form::AdminSettings.new(timeline_preview: false).save end - context 'when the user is not authenticated' do + it_behaves_like 'forbidden for wrong scope', 'profile' + + context 'without an authentication token' do let(:headers) { {} } - it 'returns http unauthorized' do + it 'returns http unprocessable entity' do subject - expect(response).to have_http_status(401) + expect(response).to have_http_status(422) + end + end + + context 'with an application access token, not bound to a user' do + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: scopes) } + + it 'returns http unprocessable entity' do + subject + + expect(response).to have_http_status(422) end end diff --git a/spec/requests/api/v1/timelines/public_spec.rb b/spec/requests/api/v1/timelines/public_spec.rb index 364e48d3d2..100f6c1bfc 100644 --- a/spec/requests/api/v1/timelines/public_spec.rb +++ b/spec/requests/api/v1/timelines/public_spec.rb @@ -34,6 +34,8 @@ describe 'Public' do context 'when the instance allows public preview' do let(:expected_statuses) { [local_status, remote_status, media_status] } + it_behaves_like 'forbidden for wrong scope', 'profile' + context 'with an authorized user' do it_behaves_like 'a successful request to the public timeline' end @@ -99,13 +101,9 @@ describe 'Public' do Form::AdminSettings.new(timeline_preview: false).save end - context 'with an authenticated user' do - let(:expected_statuses) { [local_status, remote_status, media_status] } + it_behaves_like 'forbidden for wrong scope', 'profile' - it_behaves_like 'a successful request to the public timeline' - end - - context 'with an unauthenticated user' do + context 'without an authentication token' do let(:headers) { {} } it 'returns http unprocessable entity' do @@ -114,6 +112,22 @@ describe 'Public' do expect(response).to have_http_status(422) end end + + context 'with an application access token, not bound to a user' do + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: scopes) } + + it 'returns http unprocessable entity' do + subject + + expect(response).to have_http_status(422) + end + end + + context 'with an authenticated user' do + let(:expected_statuses) { [local_status, remote_status, media_status] } + + it_behaves_like 'a successful request to the public timeline' + end end end end diff --git a/spec/requests/api/v1/timelines/tag_spec.rb b/spec/requests/api/v1/timelines/tag_spec.rb index 8611341702..5e1415bb1a 100644 --- a/spec/requests/api/v1/timelines/tag_spec.rb +++ b/spec/requests/api/v1/timelines/tag_spec.rb @@ -30,6 +30,8 @@ RSpec.describe 'Tag' do let(:params) { {} } let(:hashtag) { 'life' } + it_behaves_like 'forbidden for wrong scope', 'profile' + context 'when given only one hashtag' do let(:expected_statuses) { [life_status] } @@ -93,13 +95,15 @@ RSpec.describe 'Tag' do Form::AdminSettings.new(timeline_preview: false).save end - context 'when the user is not authenticated' do + it_behaves_like 'forbidden for wrong scope', 'profile' + + context 'without an authentication token' do let(:headers) { {} } - it 'returns http unauthorized' do + it 'returns http unprocessable entity' do subject - expect(response).to have_http_status(401) + expect(response).to have_http_status(422) end end From d3a056adfd0eca4fff57dde65ee9d95ce7c9bb3e Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 4 Jul 2024 16:45:52 +0200 Subject: [PATCH 18/19] Merge pull request from GHSA-xjvf-fm67-4qc3 --- app/lib/activitypub/activity/create.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 7ec7e84bd1..5d700b4961 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -104,7 +104,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def find_existing_status status = status_from_uri(object_uri) status ||= Status.find_by(uri: @object['atomUri']) if @object['atomUri'].present? - status + status if status&.account_id == @account.id end def process_status_params From df9e26158d9787859b24bdc276af478abf05e1af Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 4 Jul 2024 16:59:54 +0200 Subject: [PATCH 19/19] Bump version to v4.3.0-alpha.5 (#30920) --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ docker-compose.yml | 6 +++--- lib/mastodon/version.rb | 2 +- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9b24d6f15..7c3d96ba4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,37 @@ All notable changes to this project will be documented in this file. +## [4.2.10] - 2024-07-04 + +### Security + +- Fix incorrect permission checking on multiple API endpoints ([GHSA-58x8-3qxw-6hm7](https://github.com/mastodon/mastodon/security/advisories/GHSA-58x8-3qxw-6hm7)) +- Fix incorrect authorship checking when processing some activities (CVE-2024-37903, [GHSA-xjvf-fm67-4qc3](https://github.com/mastodon/mastodon/security/advisories/GHSA-xjvf-fm67-4qc3)) +- Fix ongoing streaming sessions not being invalidated when application tokens get revoked ([GHSA-vp5r-5pgw-jwqx](https://github.com/mastodon/mastodon/security/advisories/GHSA-vp5r-5pgw-jwqx)) +- Update dependencies + +### Added + +- Add yarn version specification to avoid confusion with Yarn 3 and Yarn 4 + +### Changed + +- Change preview cards generation to skip unusually long URLs ([oneiros](https://github.com/mastodon/mastodon/pull/30854)) +- Change search modifiers to be case-insensitive ([Gargron](https://github.com/mastodon/mastodon/pull/30865)) +- Change `STATSD_ADDR` handling to emit a warning rather than crashing if the address is unreachable ([timothyjrogers](https://github.com/mastodon/mastodon/pull/30691)) +- Change PWA start URL from `/home` to `/` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27377)) + +### Removed + +- Removed dependency on `posix-spawn` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18559)) + +### Fixed + +- Fix scheduled statuses scheduled in less than 5 minutes being immediately published ([danielmbrasil](https://github.com/mastodon/mastodon/pull/30584)) +- Fix encoding detection for link cards ([oneiros](https://github.com/mastodon/mastodon/pull/30780)) +- Fix `/admin/accounts/:account_id/statuses/:id` for edited posts with media attachments ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/30819)) +- Fix duplicate `@context` attribute in user archive export ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/30653)) + ## [4.2.9] - 2024-05-30 ### Security diff --git a/docker-compose.yml b/docker-compose.yml index 7089b0d14f..7a6f9be509 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -58,7 +58,7 @@ services: web: build: . - image: ghcr.io/mastodon/mastodon:v4.2.9 + image: ghcr.io/mastodon/mastodon:v4.2.10 restart: always env_file: .env.production command: bundle exec puma -C config/puma.rb @@ -79,7 +79,7 @@ services: streaming: build: . - image: ghcr.io/mastodon/mastodon:v4.2.9 + image: ghcr.io/mastodon/mastodon:v4.2.10 restart: always env_file: .env.production command: node ./streaming @@ -97,7 +97,7 @@ services: sidekiq: build: . - image: ghcr.io/mastodon/mastodon:v4.2.9 + image: ghcr.io/mastodon/mastodon:v4.2.10 restart: always env_file: .env.production command: bundle exec sidekiq diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 03972ba938..96ad409281 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -17,7 +17,7 @@ module Mastodon end def default_prerelease - 'alpha.4' + 'alpha.5' end def prerelease