Merge pull request #2771 from ClearlyClaire/glitch-soc/merge-upstream

Merge upstream changes up to 967505ee9b
pull/2772/head
Claire 2024-07-09 23:20:17 +02:00 committed by GitHub
commit 56e347d149
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 112 additions and 36 deletions

View File

@ -8,7 +8,7 @@ class Api::V1::Polls::VotesController < Api::BaseController
before_action :set_poll
def create
VoteService.new.call(current_account, @poll, vote_params[:choices])
VoteService.new.call(current_account, @poll, vote_params)
render json: @poll, serializer: REST::PollSerializer
end
@ -22,6 +22,6 @@ class Api::V1::Polls::VotesController < Api::BaseController
end
def vote_params
params.permit(choices: [])
params.require(:choices)
end
end

View File

@ -3,6 +3,8 @@
"about.contact": "Контакт:",
"about.disclaimer": "Mastodon є задарьнов проґрамов из удпертым кодом тай торговов значков Mastodon gGmbH.",
"about.domain_blocks.no_reason_available": "Причины не ясні",
"about.domain_blocks.preamble": "Майбульш Mastodon поволят вам позирати контент тай комуніковати из хосновачами из другых федерованых серверув. Туй лиш уняткы учинені про сись конкретный сервер.",
"about.domain_blocks.silenced.explanation": "Вы майбульш не будете видіти профілі тай контент из сього сервера, кидь не будете го самі глядати авадь пудпишете ся на нього.",
"about.domain_blocks.silenced.title": "Обмежено",
"about.domain_blocks.suspended.explanation": "Ниякі податкы из сього сервера не будут уброблені, усокочені ци поміняні, што чинит невозможнов хоть-яку інтеракцію ци зязок из хосновачами из сього сервера.",
"about.domain_blocks.suspended.title": "Заблоковано",
@ -20,6 +22,7 @@
"account.browse_more_on_origin_server": "Позирайте бульше на ориґіналнум профілю",
"account.cancel_follow_request": "Удмінити пудписку",
"account.copy": "Зкопіровати удкликованя на профіл",
"account.direct": "Пошептати @{name}",
"account.disable_notifications": "Бульше не сповіщати ми коли {name} пише",
"account.domain_blocked": "Домен заблокованый",
"account.edit_profile": "Управити профіл",
@ -39,8 +42,10 @@
"account.joined_short": "Датум прикапчованя",
"account.languages": "Поміняти убрані языкы",
"account.link_verified_on": "Властность сього удкликованя было звірено {date}",
"account.locked_info": "Сись профіл є замкнутый. Ґазда акаунта буде ручно провіряти тко го може зафоловити.",
"account.media": "Медіа",
"account.moved_to": "Хосновач {name} указав, ож новый профіл йим є:",
"account.mention": "Спомянути @{name}",
"account.moved_to": "Хосновач {name} указав, ож новый профіл му є:",
"account.mute": "Стишити {name}",
"account.mute_notifications_short": "Стишити голошіня",
"account.mute_short": "Стишити",
@ -60,9 +65,12 @@
"account.unblock_short": "Розблоковати",
"account.unendorse": "Не указовати на профілови",
"account.unfollow": "Удписати ся",
"account.unmute": "Указовати {name}",
"account.unmute_notifications_short": "Указовати голошіня",
"account.unmute_short": "Указовати",
"account_note.placeholder": "Клопкніт обы додати примітку",
"admin.dashboard.retention.average": "Середньоє",
"admin.dashboard.retention.cohort": "Місяць прикапчованя",
"admin.dashboard.retention.cohort_size": "Нові хосновачі",
"admin.impact_report.instance_accounts": "Профілі из акаунтув, котрі ся удалят",
"admin.impact_report.instance_followers": "Пудписникы, котрых стратят наші хосновачі",
@ -70,11 +78,38 @@
"admin.impact_report.title": "Вплыв цілком",
"alert.rate_limited.message": "Попробуйте зась по {retry_time, time, medium}.",
"alert.rate_limited.title": "Частота обмежена",
"alert.unexpected.message": "Стала ся нечекана хыба.",
"alert.unexpected.title": "Ийой!",
"announcement.announcement": "Голошіня",
"audio.hide": "Зпрятати звук",
"block_modal.show_less": "Указати менше",
"block_modal.show_more": "Указати бульше",
"block_modal.they_cant_mention": "Они не можут вас споминати авадь слідовати.",
"block_modal.they_cant_see_posts": "Они не можут видіти ваші публикації, тай наспак — вы йихні.",
"block_modal.they_will_know": "Они видят, ож сут заблоковані.",
"block_modal.title": "Заблоковати хосновача?",
"block_modal.you_wont_see_mentions": "Не будете видіти публикації тай споминкы сього хосновача.",
"boost_modal.combo": "Можете клынцнути {combo} другый раз обы сесе пропустити",
"bundle_column_error.copy_stacktrace": "Укопіровати звіт за хыбу",
"bundle_column_error.error.body": "Не годни сьме указати зажадану сторунку. Годно быти спозад хыбы у нашум сістемі, авадь проблемы зумісности бравзера.",
"bundle_column_error.error.title": "Ийой!",
"bundle_column_error.network.body": "Стала ся хыба як сьме пробовали напаровати сторунку. Годно ся йсе было стати спозад слабого споєня вашого інтернета, авадь сервера.",
"bundle_column_error.network.title": "Хыба споєня",
"bundle_column_error.retry": "Попробуйте зась",
"bundle_column_error.return": "Вернути ся на головну",
"bundle_column_error.routing.body": "Не можеме найти сяку сторунку. Бизувні сьте, ож URL у адресному шорикови є добрый?",
"bundle_column_error.routing.title": "404",
"bundle_modal_error.close": "Заперти",
"bundle_modal_error.message": "Штось ся показило, закидь сьме ладовали сись компонент.",
"bundle_modal_error.retry": "Попробовати зась",
"closed_registrations.other_server_instructions": "Mastodon є децентралізованов платформов, можете си учинити профіл и на другому серверови тай комуніковати из сим."
"closed_registrations.other_server_instructions": "Mastodon є децентралізованов платформов, можете си учинити профіл и на другому серверови тай комуніковати из сим.",
"closed_registrations_modal.description": "Раз не мож учинити профіл на {domain}, айбо не мусите мати профіл ипен на серверови {domain} обы хосновати Mastodon.",
"closed_registrations_modal.find_another_server": "Найти другый сервер",
"column.about": "За сайт",
"column.blocks": "Заблоковані хосновачі",
"column.bookmarks": "Усокоченоє",
"column.direct": "Шептаня",
"column.directory": "Никати профілі",
"column.domain_blocks": "Заблоковані домены",
"column.favourites": "Убраноє"
}

View File

@ -46,6 +46,11 @@ class PreviewCard < ApplicationRecord
y_comp: 4,
}.freeze
# URL size limit to safely store in PosgreSQL's unique indexes
# Technically this is a byte-size limit but we use it as a
# character limit to work with length validation
URL_CHARACTER_LIMIT = 2692
self.inheritance_column = false
enum :type, { link: 0, photo: 1, video: 2, rich: 3 }
@ -63,7 +68,7 @@ class PreviewCard < ApplicationRecord
convert_options: { all: '-quality 90 +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' },
validate_media_type: false
validates :url, presence: true, uniqueness: true, url: true
validates :url, presence: true, uniqueness: true, url: true, length: { maximum: URL_CHARACTER_LIMIT }
validates_attachment_content_type :image, content_type: IMAGE_MIME_TYPES
validates_attachment_size :image, less_than: LIMIT
remotable_attachment :image, LIMIT

View File

@ -15,9 +15,6 @@ class FetchLinkCardService < BaseService
)
}iox
# URL size limit to safely store in PosgreSQL's unique indexes
BYTESIZE_LIMIT = 2692
def call(status)
@status = status
@original_url = parse_urls
@ -32,7 +29,7 @@ class FetchLinkCardService < BaseService
end
attach_card if @card&.persisted?
rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, EncodingError => e
rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, EncodingError, ActiveRecord::RecordInvalid => e
Rails.logger.debug { "Error fetching link #{@original_url}: #{e}" }
nil
end
@ -88,7 +85,7 @@ class FetchLinkCardService < BaseService
def bad_url?(uri)
# Avoid local instance URLs and invalid URLs
uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme) || uri.to_s.bytesize > BYTESIZE_LIMIT
uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme)
end
def mention_link?(anchor)

View File

@ -2,9 +2,21 @@
require_relative '../../lib/mastodon/sidekiq_middleware'
SIDEKIQ_WILL_PROCESSES_JOBS_FILE = Rails.root.join('tmp', 'sidekiq_process_has_started_and_will_begin_processing_jobs').freeze
Sidekiq.configure_server do |config|
config.redis = REDIS_SIDEKIQ_PARAMS
# This is used in Kubernetes setups, to signal that the Sidekiq process has started and will begin processing jobs
# This comes from https://github.com/sidekiq/sidekiq/wiki/Kubernetes#sidekiq
config.on(:startup) do
FileUtils.touch(SIDEKIQ_WILL_PROCESSES_JOBS_FILE)
end
config.on(:shutdown) do
FileUtils.rm_f(SIDEKIQ_WILL_PROCESSES_JOBS_FILE)
end
config.server_middleware do |chain|
chain.add Mastodon::SidekiqMiddleware
end

View File

@ -64,12 +64,16 @@ Rails.application.routes.draw do
tokens: 'oauth/tokens'
end
get '.well-known/oauth-authorization-server', to: 'well_known/oauth_metadata#show', as: :oauth_metadata, defaults: { format: 'json' }
get '.well-known/host-meta', to: 'well_known/host_meta#show', as: :host_meta, defaults: { format: 'xml' }
get '.well-known/nodeinfo', to: 'well_known/node_info#index', as: :nodeinfo, defaults: { format: 'json' }
get '.well-known/webfinger', to: 'well_known/webfinger#show', as: :webfinger
get '.well-known/change-password', to: redirect('/auth/edit')
get '.well-known/proxy', to: redirect { |_, request| "/authorize_interaction?#{request.params.to_query}" }
scope path: '.well-known' do
scope module: :well_known do
get 'oauth-authorization-server', to: 'oauth_metadata#show', as: :oauth_metadata, defaults: { format: 'json' }
get 'host-meta', to: 'host_meta#show', as: :host_meta, defaults: { format: 'xml' }
get 'nodeinfo', to: 'node_info#index', as: :nodeinfo, defaults: { format: 'json' }
get 'webfinger', to: 'webfinger#show', as: :webfinger
end
get 'change-password', to: redirect('/auth/edit'), as: nil
get 'proxy', to: redirect { |_, request| "/authorize_interaction?#{request.params.to_query}" }, as: nil
end
get '/nodeinfo/2.0', to: 'well_known/node_info#show', as: :nodeinfo_schema
@ -95,7 +99,7 @@ Rails.application.routes.draw do
namespace :auth do
resource :setup, only: [:show, :update], controller: :setup
resource :challenge, only: [:create], controller: :challenges
resource :challenge, only: [:create]
get 'sessions/security_key_options', to: 'sessions#webauthn_options'
post 'captcha_confirmation', to: 'confirmations#confirm_captcha', as: :captcha_confirmation
end

View File

@ -26,9 +26,9 @@ namespace :settings do
resources :follows, only: :index, controller: :following_accounts
resources :blocks, only: :index, controller: :blocked_accounts
resources :mutes, only: :index, controller: :muted_accounts
resources :lists, only: :index, controller: :lists
resources :lists, only: :index
resources :domain_blocks, only: :index, controller: :blocked_domains
resources :bookmarks, only: :index, controller: :bookmarks
resources :bookmarks, only: :index
end
resources :two_factor_authentication_methods, only: [:index] do

View File

@ -0,0 +1,18 @@
HTTP/1.1 200 OK
server: nginx
date: Thu, 13 Jun 2024 14:33:13 GMT
content-type: text/html; charset=utf-8
content-length: 3225
accept-ranges: bytes
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="canonical" href="https://example.com/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa">
<title>Very long canonical URL</title>
</head>
<body>
<h2>We have very long URLs</h2>
</body>
</html>

View File

@ -10,9 +10,10 @@ RSpec.describe 'API V1 Polls Votes' do
describe 'POST /api/v1/polls/:poll_id/votes' do
let(:poll) { Fabricate(:poll) }
let(:params) { { choices: %w(1) } }
before do
post "/api/v1/polls/#{poll.id}/votes", params: { choices: %w(1) }, headers: headers
post "/api/v1/polls/#{poll.id}/votes", params: params, headers: headers
end
it 'creates a vote', :aggregate_failures do
@ -24,6 +25,14 @@ RSpec.describe 'API V1 Polls Votes' do
expect(poll.reload.cached_tallies).to eq [0, 1]
end
context 'when the required choices param is not provided' do
let(:params) { {} }
it 'returns http bad request' do
expect(response).to have_http_status(400)
end
end
private
def vote

View File

@ -31,6 +31,7 @@ RSpec.describe FetchLinkCardService do
stub_request(:get, 'http://example.com/latin1_posing_as_utf8_recoverable').to_return(request_fixture('latin1_posing_as_utf8_recoverable.txt'))
stub_request(:get, 'http://example.com/aergerliche-umlaute').to_return(request_fixture('redirect_with_utf8_url.txt'))
stub_request(:get, 'http://example.com/page_without_title').to_return(request_fixture('page_without_title.txt'))
stub_request(:get, 'http://example.com/long_canonical_url').to_return(request_fixture('long_canonical_url.txt'))
Rails.cache.write('oembed_endpoint:example.com', oembed_cache) if oembed_cache
@ -233,19 +234,6 @@ RSpec.describe FetchLinkCardService do
end
end
context 'with an URL too long for PostgreSQL unique indexes' do
let(:url) { "http://example.com/#{'a' * 2674}" }
let(:status) { Fabricate(:status, text: url) }
it 'does not fetch the URL' do
expect(a_request(:get, url)).to_not have_been_made
end
it 'does not create a preview card' do
expect(status.preview_card).to be_nil
end
end
context 'with a URL of a page with oEmbed support' do
let(:html) { '<!doctype html><title>Hello world</title><link rel="alternate" type="application/json+oembed" href="http://example.com/oembed?url=http://example.com/html">' }
let(:status) { Fabricate(:status, text: 'http://example.com/html') }
@ -296,6 +284,14 @@ RSpec.describe FetchLinkCardService do
end
end
end
context 'with a URL of a page that includes a canonical URL too long for PostgreSQL unique indexes' do
let(:status) { Fabricate(:status, text: 'test http://example.com/long_canonical_url') }
it 'does not create a preview card' do
expect(status.preview_card).to be_nil
end
end
end
context 'with a remote status' do

View File

@ -9033,8 +9033,8 @@ __metadata:
linkType: hard
"glob@npm:^10.2.2, glob@npm:^10.2.6, glob@npm:^10.3.10":
version: 10.4.3
resolution: "glob@npm:10.4.3"
version: 10.4.5
resolution: "glob@npm:10.4.5"
dependencies:
foreground-child: "npm:^3.1.0"
jackspeak: "npm:^3.1.2"
@ -9044,7 +9044,7 @@ __metadata:
path-scurry: "npm:^1.11.1"
bin:
glob: dist/esm/bin.mjs
checksum: 10c0/bea148e5dae96c17e2764f4764c72376a6ab7072b27a21e861ae4af6f97f3e810d79d67f64de52f63ce1d7fdb73b7306f61c65b48d0f61ca7c8647ce8acaf9a7
checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e
languageName: node
linkType: hard