mirror of
https://github.com/mastodon/mastodon.git
synced 2026-08-20 14:14:28 -05:00
Merge commit from fork
* Fix GHSA-7jvv-fhmg-wpfw * Fix GHSA-vwhj-3g83-v276 * Bump version to v4.4.21
This commit is contained in:
19
CHANGELOG.md
19
CHANGELOG.md
@@ -2,6 +2,25 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [4.4.21] - 2026-07-27
|
||||
|
||||
### Security
|
||||
|
||||
- Fix incorrect permission enforcement ([GHSA-7jvv-fhmg-wpfw](https://github.com/mastodon/mastodon/security/advisories/GHSA-7jvv-fhmg-wpfw))
|
||||
- Fix SSRF protection bypass via IPv4-compatible IPv6 addresses ([GHSA-vwhj-3g83-v276](https://github.com/mastodon/mastodon/security/advisories/GHSA-vwhj-3g83-v276))
|
||||
- Update dependencies
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix performance of user-focused queries in admin dashboard (#39929 by @ClearlyClaire)
|
||||
- Fix Web Push subscription deletion endpoint incorrectly expecting anti-CSRF tokens (#39918 by @ClearlyClaire)
|
||||
- Fix `ActivityPub::Activity::Create` trying to re-create known statuses when author changes (#39916 by @ClearlyClaire)
|
||||
- Fix lax relevancy check in inbound activity processing (#39892 by @ClearlyClaire)
|
||||
- Fix `Account::Merging` concern not supporting Quotes, refactor it (#39884 by @ClearlyClaire)
|
||||
- Fix suspended accounts not being removed from follow request count in `/api/v1/accounts/verify_credentials` (#39858 by @ClearlyClaire)
|
||||
- Fix followed tags not being properly cleaned up when an account is deleted (#39824 by @shleeable)
|
||||
- Fix autofollow option being ignored in invite moderation interface (#39819 by @shleeable)
|
||||
|
||||
## [4.4.20] - 2026-06-25
|
||||
|
||||
### Security
|
||||
|
||||
@@ -17,9 +17,9 @@ class Api::V1::Admin::MeasuresController < Api::BaseController
|
||||
|
||||
def set_measures
|
||||
@measures = Admin::Metrics::Measure.retrieve(
|
||||
params[:keys],
|
||||
params[:start_at],
|
||||
params[:end_at],
|
||||
params.require(:keys),
|
||||
params.require(:start_at),
|
||||
params.require(:end_at),
|
||||
params
|
||||
)
|
||||
end
|
||||
|
||||
@@ -4,22 +4,22 @@ class Api::V1::Admin::RetentionController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||
before_action :set_cohorts
|
||||
before_action :set_retention
|
||||
|
||||
after_action :verify_authorized
|
||||
|
||||
def create
|
||||
authorize :dashboard, :index?
|
||||
render json: @cohorts, each_serializer: REST::Admin::CohortSerializer
|
||||
render json: @retention.cohorts, each_serializer: REST::Admin::CohortSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_cohorts
|
||||
@cohorts = Admin::Metrics::Retention.new(
|
||||
params[:start_at],
|
||||
params[:end_at],
|
||||
def set_retention
|
||||
@retention = Admin::Metrics::Retention.new(
|
||||
params.require(:start_at),
|
||||
params.require(:end_at),
|
||||
params[:frequency]
|
||||
).cohorts
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,6 +17,8 @@ class Admin::Metrics::Dimension::BaseDimension
|
||||
@limit = limit&.to_i
|
||||
@params = params
|
||||
@loaded = false
|
||||
|
||||
@start_at = [@start_at, @end_at - 2.years].max if @start_at.present? && @end_at.present?
|
||||
end
|
||||
|
||||
def key
|
||||
|
||||
@@ -12,10 +12,12 @@ class Admin::Metrics::Measure::BaseMeasure
|
||||
alias loaded? loaded
|
||||
|
||||
def initialize(start_at, end_at, params)
|
||||
@start_at = start_at&.to_datetime
|
||||
@end_at = end_at&.to_datetime
|
||||
@start_at = start_at.to_datetime
|
||||
@end_at = end_at.to_datetime
|
||||
@params = params
|
||||
@loaded = false
|
||||
|
||||
@start_at = [@start_at, @end_at - 2.years].max
|
||||
end
|
||||
|
||||
def cache_key
|
||||
|
||||
@@ -16,10 +16,13 @@ class Admin::Metrics::Retention
|
||||
alias loaded? loaded
|
||||
|
||||
def initialize(start_at, end_at, frequency)
|
||||
@start_at = start_at&.to_date
|
||||
@end_at = end_at&.to_date
|
||||
@start_at = start_at.to_date
|
||||
@end_at = end_at.to_date
|
||||
|
||||
@frequency = %w(day month).include?(frequency) ? frequency : 'day'
|
||||
@loaded = false
|
||||
|
||||
@start_at = [@start_at, @end_at - (@frequency == 'day' ? 31.days : 12.months)].max
|
||||
end
|
||||
|
||||
def cache_key
|
||||
|
||||
@@ -34,7 +34,7 @@ module PrivateAddressCheck
|
||||
module_function
|
||||
|
||||
def private_address?(address)
|
||||
address = address.native if address.ipv6? && address.ipv4_mapped?
|
||||
address = address.native if address.ipv6? && (address.ipv4_mapped? || address.ipv4_compat?)
|
||||
address.private? || address.loopback? || address.link_local? || CIDR_LIST.any? { |cidr| cidr.include?(address) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -59,7 +59,7 @@ services:
|
||||
web:
|
||||
# You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes
|
||||
# build: .
|
||||
image: ghcr.io/mastodon/mastodon:v4.4.20
|
||||
image: ghcr.io/mastodon/mastodon:v4.4.21
|
||||
restart: always
|
||||
env_file: .env.production
|
||||
command: bundle exec puma -C config/puma.rb
|
||||
@@ -83,7 +83,7 @@ services:
|
||||
# build:
|
||||
# dockerfile: ./streaming/Dockerfile
|
||||
# context: .
|
||||
image: ghcr.io/mastodon/mastodon-streaming:v4.4.20
|
||||
image: ghcr.io/mastodon/mastodon-streaming:v4.4.21
|
||||
restart: always
|
||||
env_file: .env.production
|
||||
command: node ./streaming/index.js
|
||||
@@ -102,7 +102,7 @@ services:
|
||||
sidekiq:
|
||||
# You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes
|
||||
# build: .
|
||||
image: ghcr.io/mastodon/mastodon:v4.4.20
|
||||
image: ghcr.io/mastodon/mastodon:v4.4.21
|
||||
restart: always
|
||||
env_file: .env.production
|
||||
command: bundle exec sidekiq
|
||||
|
||||
@@ -13,7 +13,7 @@ module Mastodon
|
||||
end
|
||||
|
||||
def patch
|
||||
20
|
||||
21
|
||||
end
|
||||
|
||||
def default_prerelease
|
||||
|
||||
@@ -22,6 +22,8 @@ RSpec.describe 'Admin Measures' do
|
||||
domain: 'mastodon.social',
|
||||
include_subdomains: true,
|
||||
},
|
||||
start_at: '2026-01-01',
|
||||
end_at: '2026-07-01',
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ RSpec.describe 'Admin Retention' do
|
||||
describe 'GET /api/v1/admin/retention' do
|
||||
context 'when not authorized' do
|
||||
it 'returns http forbidden' do
|
||||
post '/api/v1/admin/retention', params: { account_id: account.id, limit: 2 }
|
||||
post '/api/v1/admin/retention', params: { start_at: '2025-01-04', end_at: '2025-07-05', frequency: 'month' }
|
||||
|
||||
expect(response)
|
||||
.to have_http_status(403)
|
||||
@@ -24,7 +24,7 @@ RSpec.describe 'Admin Retention' do
|
||||
let(:scopes) { 'admin:read' }
|
||||
|
||||
it 'returns http success and status json' do
|
||||
post '/api/v1/admin/retention', params: { account_id: account.id, limit: 2 }, headers: headers
|
||||
post '/api/v1/admin/retention', params: { start_at: '2025-01-04', end_at: '2025-07-05', frequency: 'month' }, headers: headers
|
||||
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
|
||||
Reference in New Issue
Block a user