Merge tag 'v4.0.10'

This commit is contained in:
Mike Barnes 2023-09-20 05:42:47 +10:00
commit 04a0f875a3
19 changed files with 126 additions and 249 deletions

View file

@ -1,225 +0,0 @@
version: 2.1
orbs:
ruby: circleci/ruby@1.4.1
node: circleci/node@5.0.1
executors:
default:
parameters:
ruby-version:
type: string
docker:
- image: cimg/ruby:<< parameters.ruby-version >>
environment:
BUNDLE_JOBS: 3
BUNDLE_RETRY: 3
CONTINUOUS_INTEGRATION: true
DB_HOST: localhost
DB_USER: root
DISABLE_SIMPLECOV: true
RAILS_ENV: test
- image: cimg/postgres:14.0
environment:
POSTGRES_USER: root
POSTGRES_HOST_AUTH_METHOD: trust
- image: cimg/redis:6.2
commands:
install-system-dependencies:
steps:
- run:
name: Install system dependencies
command: |
sudo apt-get update
sudo apt-get install -y libicu-dev libidn11-dev
install-ruby-dependencies:
parameters:
ruby-version:
type: string
steps:
- run:
command: |
bundle config clean 'true'
bundle config frozen 'true'
bundle config without 'development production'
name: Set bundler settings
- ruby/install-deps:
bundler-version: '2.3.8'
key: ruby<< parameters.ruby-version >>-gems-v1
wait-db:
steps:
- run:
command: dockerize -wait tcp://localhost:5432 -wait tcp://localhost:6379 -timeout 1m
name: Wait for PostgreSQL and Redis
jobs:
build:
docker:
- image: cimg/ruby:3.0-node
environment:
RAILS_ENV: test
steps:
- checkout
- install-system-dependencies
- install-ruby-dependencies:
ruby-version: '3.0'
- node/install-packages:
cache-version: v1
pkg-manager: yarn
- run:
command: |
export NODE_OPTIONS=--openssl-legacy-provider
./bin/rails assets:precompile
name: Precompile assets
- persist_to_workspace:
paths:
- public/assets
- public/packs-test
root: .
test:
parameters:
ruby-version:
type: string
executor:
name: default
ruby-version: << parameters.ruby-version >>
environment:
ALLOW_NOPAM: true
PAM_ENABLED: true
PAM_DEFAULT_SERVICE: pam_test
PAM_CONTROLLED_SERVICE: pam_test_controlled
parallelism: 4
steps:
- checkout
- install-system-dependencies
- run:
command: sudo apt-get install -y ffmpeg imagemagick libpam-dev
name: Install additional system dependencies
- run:
command: bundle config with 'pam_authentication'
name: Enable PAM authentication
- install-ruby-dependencies:
ruby-version: << parameters.ruby-version >>
- attach_workspace:
at: .
- wait-db
- run:
command: ./bin/rails db:create db:schema:load db:seed
name: Load database schema
- ruby/rspec-test
test-migrations:
executor:
name: default
ruby-version: '3.0'
steps:
- checkout
- install-system-dependencies
- install-ruby-dependencies:
ruby-version: '3.0'
- wait-db
- run:
command: ./bin/rails db:create
name: Create database
- run:
command: ./bin/rails db:migrate VERSION=20171010025614
name: Run migrations up to v2.0.0
- run:
command: ./bin/rails tests:migrations:populate_v2
name: Populate database with test data
- run:
command: ./bin/rails db:migrate VERSION=20180514140000
name: Run migrations up to v2.4.0
- run:
command: ./bin/rails tests:migrations:populate_v2_4
name: Populate database with test data
- run:
command: ./bin/rails db:migrate VERSION=20180707154237
name: Run migrations up to v2.4.3
- run:
command: ./bin/rails tests:migrations:populate_v2_4_3
name: Populate database with test data
- run:
command: ./bin/rails db:migrate
name: Run all remaining migrations
- run:
command: ./bin/rails tests:migrations:check_database
name: Check migration result
test-two-step-migrations:
executor:
name: default
ruby-version: '3.0'
steps:
- checkout
- install-system-dependencies
- install-ruby-dependencies:
ruby-version: '3.0'
- wait-db
- run:
command: ./bin/rails db:create
name: Create database
- run:
command: ./bin/rails db:migrate VERSION=20171010025614
name: Run migrations up to v2.0.0
- run:
command: ./bin/rails tests:migrations:populate_v2
name: Populate database with test data
- run:
command: ./bin/rails db:migrate VERSION=20180514140000
name: Run pre-deployment migrations up to v2.4.0
environment:
SKIP_POST_DEPLOYMENT_MIGRATIONS: true
- run:
command: ./bin/rails tests:migrations:populate_v2_4
name: Populate database with test data
- run:
command: ./bin/rails db:migrate VERSION=20180707154237
name: Run migrations up to v2.4.3
environment:
SKIP_POST_DEPLOYMENT_MIGRATIONS: true
- run:
command: ./bin/rails tests:migrations:populate_v2_4_3
name: Populate database with test data
- run:
command: ./bin/rails db:migrate
name: Run all remaining pre-deployment migrations
environment:
SKIP_POST_DEPLOYMENT_MIGRATIONS: true
- run:
command: ./bin/rails db:migrate
name: Run all post-deployment migrations
- run:
command: ./bin/rails tests:migrations:check_database
name: Check migration result
workflows:
version: 2
build-and-test:
jobs:
- build
- test:
matrix:
parameters:
ruby-version:
- '2.7'
- '3.0'
name: test-ruby<< matrix.ruby-version >>
requires:
- build
- test-migrations:
requires:
- build
- test-two-step-migrations:
requires:
- build
- node/run:
cache-version: v1
name: test-webui
pkg-manager: yarn
requires:
- build
version: lts
yarn-run: test:jest

View file

@ -4,6 +4,9 @@ on:
platforms: platforms:
required: true required: true
type: string type: string
cache:
type: boolean
default: true
use_native_arm64_builder: use_native_arm64_builder:
type: boolean type: boolean
push_to_images: push_to_images:
@ -85,5 +88,5 @@ jobs:
push: ${{ inputs.push_to_images != '' }} push: ${{ inputs.push_to_images != '' }}
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha cache-from: ${{ inputs.cache && 'type=gha' || '' }}
cache-to: type=gha,mode=max cache-to: ${{ inputs.cache && 'type=gha,mode=max' || '' }}

View file

@ -17,6 +17,8 @@ jobs:
push_to_images: | push_to_images: |
tootsuite/mastodon tootsuite/mastodon
ghcr.io/mastodon/mastodon ghcr.io/mastodon/mastodon
# Do not use cache when building releases, so apt update is always ran and the release always contain the latest packages
cache: false
flavor: | flavor: |
latest=false latest=false
tags: | tags: |

15
.github/workflows/test-image-build.yml vendored Normal file
View file

@ -0,0 +1,15 @@
name: Test container image build
on:
pull_request:
permissions:
contents: read
jobs:
build-image:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
uses: ./.github/workflows/build-container-image.yml
with:
platforms: linux/amd64 # Testing only on native platform so it is performant

View file

@ -8,6 +8,21 @@ All notable changes to this project will be documented in this file.
**The 4.0.x branch will not receive any update after 2023-10-31.** **The 4.0.x branch will not receive any update after 2023-10-31.**
This means that no security fix will be made available for this branch after this date, and you will need to update to a more recent version (such as the 4.1.x branch) to receive security fixes. This means that no security fix will be made available for this branch after this date, and you will need to update to a more recent version (such as the 4.1.x branch) to receive security fixes.
## [4.0.10] - 2023-09-19
### Fixed
- Fix moderator rights inconsistencies ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26729))
- Fix crash when encountering invalid URL ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26814))
- Fix cached posts including stale stats ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26409))
- Fix uploading of video files for which `ffprobe` reports `0/0` average framerate ([NicolaiSoeborg](https://github.com/mastodon/mastodon/pull/26500))
- Fix unexpected audio stream transcoding when uploaded video is eligible to passthrough ([yufushiro](https://github.com/mastodon/mastodon/pull/26608))
### Security
- Fix missing HTML sanitization in translation API (CVE-2023-42452)
- Fix incorrect domain name normalization (CVE-2023-42451)
## [4.0.9] - 2023-09-05 ## [4.0.9] - 2023-09-05
### Changed ### Changed

View file

@ -19,6 +19,7 @@ RUN ARCH= && \
esac && \ esac && \
echo "Etc/UTC" > /etc/localtime && \ echo "Etc/UTC" > /etc/localtime && \
apt-get update && \ apt-get update && \
apt-get -yq dist-upgrade && \
apt-get install -y --no-install-recommends ca-certificates wget python3 apt-utils && \ apt-get install -y --no-install-recommends ca-certificates wget python3 apt-utils && \
cd ~ && \ cd ~ && \
wget -q https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && \ wget -q https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && \

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class Admin::AccountStatusesFilter < AccountStatusesFilter
private
def blocked?
false
end
end

View file

@ -7,18 +7,18 @@ class TagManager
include RoutingHelper include RoutingHelper
def web_domain?(domain) def web_domain?(domain)
domain.nil? || domain.gsub(/[\/]/, '').casecmp(Rails.configuration.x.web_domain).zero? domain.nil? || domain.delete_suffix('/').casecmp(Rails.configuration.x.web_domain).zero?
end end
def local_domain?(domain) def local_domain?(domain)
domain.nil? || domain.gsub(/[\/]/, '').casecmp(Rails.configuration.x.local_domain).zero? domain.nil? || domain.delete_suffix('/').casecmp(Rails.configuration.x.local_domain).zero?
end end
def normalize_domain(domain) def normalize_domain(domain)
return if domain.nil? return if domain.nil?
uri = Addressable::URI.new uri = Addressable::URI.new
uri.host = domain.gsub(/[\/]/, '') uri.host = domain.delete_suffix('/')
uri.normalized_host uri.normalized_host
end end
@ -28,7 +28,7 @@ class TagManager
domain = uri.host + (uri.port ? ":#{uri.port}" : '') domain = uri.host + (uri.port ? ":#{uri.port}" : '')
TagManager.instance.web_domain?(domain) TagManager.instance.web_domain?(domain)
rescue Addressable::URI::InvalidURIError rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError
false false
end end
end end

View file

@ -43,6 +43,9 @@ class VideoMetadataExtractor
@height = video_stream[:height] @height = video_stream[:height]
@frame_rate = video_stream[:avg_frame_rate] == '0/0' ? nil : Rational(video_stream[:avg_frame_rate]) @frame_rate = video_stream[:avg_frame_rate] == '0/0' ? nil : Rational(video_stream[:avg_frame_rate])
@r_frame_rate = video_stream[:r_frame_rate] == '0/0' ? nil : Rational(video_stream[:r_frame_rate]) @r_frame_rate = video_stream[:r_frame_rate] == '0/0' ? nil : Rational(video_stream[:r_frame_rate])
# For some video streams the frame_rate reported by `ffprobe` will be 0/0, but for these streams we
# should use `r_frame_rate` instead. Video screencast generated by Gnome Screencast have this issue.
@frame_rate ||= @r_frame_rate
end end
if (audio_stream = audio_streams.first) if (audio_stream = audio_streams.first)

View file

@ -137,6 +137,6 @@ class Admin::StatusBatchAction
end end
def allowed_status_ids def allowed_status_ids
AccountStatusesFilter.new(@report.target_account, current_account).results.with_discarded.where(id: status_ids).pluck(:id) Admin::AccountStatusesFilter.new(@report.target_account, current_account).results.with_discarded.where(id: status_ids).pluck(:id)
end end
end end

View file

@ -353,13 +353,25 @@ class Status < ApplicationRecord
account_ids.uniq! account_ids.uniq!
status_ids = cached_items.map { |item| item.reblog? ? item.reblog_of_id : item.id }.uniq
return if account_ids.empty? return if account_ids.empty?
accounts = Account.where(id: account_ids).includes(:account_stat, :user).index_by(&:id) accounts = Account.where(id: account_ids).includes(:account_stat, :user).index_by(&:id)
status_stats = StatusStat.where(status_id: status_ids).index_by(&:status_id)
cached_items.each do |item| cached_items.each do |item|
item.account = accounts[item.account_id] item.account = accounts[item.account_id]
item.reblog.account = accounts[item.reblog.account_id] if item.reblog? item.reblog.account = accounts[item.reblog.account_id] if item.reblog?
if item.reblog?
status_stat = status_stats[item.reblog.id]
item.reblog.status_stat = status_stat if status_stat.present?
else
status_stat = status_stats[item.id]
item.status_stat = status_stat if status_stat.present?
end
end end
end end

View file

@ -12,7 +12,7 @@ class Admin::StatusPolicy < ApplicationPolicy
end end
def show? def show?
role.can?(:manage_reports, :manage_users) && (record.public_visibility? || record.unlisted_visibility? || record.reported?) role.can?(:manage_reports, :manage_users) && (record.public_visibility? || record.unlisted_visibility? || record.reported? || viewable_through_normal_policy?)
end end
def destroy? def destroy?
@ -26,4 +26,10 @@ class Admin::StatusPolicy < ApplicationPolicy
def review? def review?
role.can?(:manage_taxonomies) role.can?(:manage_taxonomies)
end end
private
def viewable_through_normal_policy?
StatusPolicy.new(current_account, record, @preloaded_relations).show?
end
end end

View file

@ -12,7 +12,9 @@ class TranslateStatusService < BaseService
@content = status_content_format(@status) @content = status_content_format(@status)
@target_language = target_language @target_language = target_language
Rails.cache.fetch("translations/#{@status.language}/#{@target_language}/#{content_hash}", expires_in: CACHE_TTL) { translation_backend.translate(@content, @status.language, @target_language) } Rails.cache.fetch("translations/#{@status.language}/#{@target_language}/#{content_hash}", expires_in: CACHE_TTL) do
Sanitize.fragment(translation_backend.translate(@content, @status.language, @target_language), Sanitize::Config::MASTODON_STRICT)
end
end end
private private

View file

@ -56,7 +56,7 @@ services:
web: web:
build: . build: .
image: ghcr.io/mastodon/mastodon:v4.0.9 image: ghcr.io/mastodon/mastodon:v4.0.10
restart: always restart: always
env_file: .env.production env_file: .env.production
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000" command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
@ -77,7 +77,7 @@ services:
streaming: streaming:
build: . build: .
image: ghcr.io/mastodon/mastodon:v4.0.9 image: ghcr.io/mastodon/mastodon:v4.0.10
restart: always restart: always
env_file: .env.production env_file: .env.production
command: node ./streaming command: node ./streaming
@ -95,7 +95,7 @@ services:
sidekiq: sidekiq:
build: . build: .
image: ghcr.io/mastodon/mastodon:v4.0.9 image: ghcr.io/mastodon/mastodon:v4.0.10
restart: always restart: always
env_file: .env.production env_file: .env.production
command: bundle exec sidekiq command: bundle exec sidekiq

View file

@ -13,7 +13,7 @@ module Mastodon
end end
def patch def patch
9 10
end end
def flags def flags

View file

@ -37,14 +37,16 @@ module Paperclip
@output_options['f'] = 'image2' @output_options['f'] = 'image2'
@output_options['vframes'] = 1 @output_options['vframes'] = 1
when 'mp4' when 'mp4'
unless eligible_to_passthrough?(metadata)
@output_options['acodec'] = 'aac' @output_options['acodec'] = 'aac'
@output_options['strict'] = 'experimental' @output_options['strict'] = 'experimental'
if high_vfr?(metadata) && !eligible_to_passthrough?(metadata) if high_vfr?(metadata)
@output_options['vsync'] = 'vfr' @output_options['vsync'] = 'vfr'
@output_options['r'] = @vfr_threshold @output_options['r'] = @vfr_threshold
end end
end end
end
command_arguments, interpolations = prepare_command(destination) command_arguments, interpolations = prepare_command(destination)

View file

@ -40,24 +40,36 @@ describe Admin::StatusesController do
end end
describe 'POST #batch' do describe 'POST #batch' do
before do subject { post :batch, params: { :account_id => account.id, action => '', :admin_status_batch_action => { status_ids: status_ids } } }
post :batch, params: { :account_id => account.id, action => '', :admin_status_batch_action => { status_ids: status_ids } }
end
let(:status_ids) { [media_attached_status.id] } let(:status_ids) { [media_attached_status.id] }
context 'when action is report' do shared_examples 'when action is report' do
let(:action) { 'report' } let(:action) { 'report' }
it 'creates a report' do it 'creates a report' do
subject
report = Report.last report = Report.last
expect(report.target_account_id).to eq account.id expect(report.target_account_id).to eq account.id
expect(report.status_ids).to eq status_ids expect(report.status_ids).to eq status_ids
end end
it 'redirects to report page' do it 'redirects to report page' do
subject
expect(response).to redirect_to(admin_report_path(Report.last.id)) expect(response).to redirect_to(admin_report_path(Report.last.id))
end end
end end
it_behaves_like 'when action is report'
context 'when the moderator is blocked by the author' do
before do
account.block!(user.account)
end
it_behaves_like 'when action is report'
end
end end
end end

View file

@ -13,12 +13,17 @@ RSpec.describe CacheConcern, type: :controller do
def empty_relation def empty_relation
render plain: cache_collection(Status.none, Status).size render plain: cache_collection(Status.none, Status).size
end end
def account_statuses_favourites
render plain: cache_collection(Status.where(account_id: params[:id]), Status).map(&:favourites_count)
end
end end
before do before do
routes.draw do routes.draw do
get 'empty_array' => 'anonymous#empty_array' get 'empty_array' => 'anonymous#empty_array'
post 'empty_relation' => 'anonymous#empty_relation' get 'empty_relation' => 'anonymous#empty_relation'
get 'account_statuses_favourites' => 'anonymous#account_statuses_favourites'
end end
end end
@ -36,5 +41,20 @@ RSpec.describe CacheConcern, type: :controller do
expect(response.body).to eq '0' expect(response.body).to eq '0'
end end
end end
context 'when given a collection of statuses' do
let!(:account) { Fabricate(:account) }
let!(:status) { Fabricate(:status, account: account) }
it 'correctly updates with new interactions' do
get :account_statuses_favourites, params: { id: account.id }
expect(response.body).to eq '[0]'
FavouriteService.new.call(account, status)
get :account_statuses_favourites, params: { id: account.id }
expect(response.body).to eq '[1]'
end
end
end end
end end