mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-13 07:49:29 +00:00
Merge pull request #3232 from ClearlyClaire/glitch-soc/merge-4.4
Merge upstream changes up to d7f4eca801 into stable-4.4
This commit is contained in:
22
CHANGELOG.md
22
CHANGELOG.md
@@ -2,6 +2,28 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [4.4.6] - 2025-10-13
|
||||
|
||||
### Security
|
||||
|
||||
- Update dependencies `rack` and `uri`
|
||||
- Fix streaming server connection not being closed on user suspension (by @ThisIsMissEm, [GHSA-r2fh-jr9c-9pxh](https://github.com/mastodon/mastodon/security/advisories/GHSA-r2fh-jr9c-9pxh))
|
||||
- Fix password change through admin CLI not invalidating existing sessions and access tokens (by @ThisIsMissEm, [GHSA-f3q3-rmf7-9655](https://github.com/mastodon/mastodon/security/advisories/GHSA-f3q3-rmf7-9655))
|
||||
- Fix streaming server allowing access to public timelines even without the `read` or `read:statuses` OAuth scopes (by @ThisIsMissEm, [GHSA-7gwh-mw97-qjgp](https://github.com/mastodon/mastodon/security/advisories/GHSA-7gwh-mw97-qjgp))
|
||||
|
||||
### Added
|
||||
|
||||
- Add support for processing quotes of deleted posts signaled through a `Tombstone` (#36381 by @ClearlyClaire)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix quote post state sometimes not being updated through streaming server (#36408 by @ClearlyClaire)
|
||||
- Fix inconsistent “pending tags” count on admin dashboard (#36404 by @mjankowski)
|
||||
- Fix JSON payload being potentially mutated when processing interaction policies (#36392 by @ClearlyClaire)
|
||||
- Fix quotes not being displayed in email notifications (#36379 by @diondiondion)
|
||||
- Fix redirect to external object when URL is missing or malformed (#36347 by @ClearlyClaire)
|
||||
- Fix quotes not being displayed in the featured carousel (#36335 by @diondiondion)
|
||||
|
||||
## [4.4.5] - 2025-09-23
|
||||
|
||||
### Security
|
||||
|
||||
@@ -494,7 +494,7 @@ GEM
|
||||
tzinfo
|
||||
validate_url
|
||||
webfinger (~> 2.0)
|
||||
openssl (3.3.0)
|
||||
openssl (3.3.1)
|
||||
openssl-signature_algorithm (1.3.0)
|
||||
openssl (> 2.0)
|
||||
opentelemetry-api (1.5.0)
|
||||
@@ -642,7 +642,7 @@ GEM
|
||||
activesupport (>= 3.0.0)
|
||||
raabro (1.4.0)
|
||||
racc (1.8.1)
|
||||
rack (3.1.17)
|
||||
rack (3.1.18)
|
||||
rack-attack (6.7.0)
|
||||
rack (>= 1.0, < 4)
|
||||
rack-cors (3.0.0)
|
||||
|
||||
@@ -32,6 +32,10 @@ module Account::Suspensions
|
||||
update!(suspended_at: date, suspension_origin: origin)
|
||||
create_canonical_email_block! if block_email
|
||||
end
|
||||
|
||||
# This terminates all connections for the given account with the streaming
|
||||
# server:
|
||||
redis.publish("timeline:system:#{id}", Oj.dump(event: :kill)) if local?
|
||||
end
|
||||
|
||||
def unsuspend!
|
||||
|
||||
@@ -197,6 +197,10 @@ class User < ApplicationRecord
|
||||
|
||||
def disable!
|
||||
update!(disabled: true)
|
||||
|
||||
# This terminates all connections for the given account with the streaming
|
||||
# server:
|
||||
redis.publish("timeline:system:#{account.id}", Oj.dump(event: :kill))
|
||||
end
|
||||
|
||||
def enable!
|
||||
@@ -389,17 +393,22 @@ class User < ApplicationRecord
|
||||
end
|
||||
|
||||
def reset_password!
|
||||
# First, change password to something random, this revokes sessions and on-going access:
|
||||
change_password!(SecureRandom.hex)
|
||||
|
||||
# Finally, send a reset password prompt to the user
|
||||
send_reset_password_instructions
|
||||
end
|
||||
|
||||
def change_password!(new_password)
|
||||
# First, change password to something random and deactivate all sessions
|
||||
transaction do
|
||||
update(password: SecureRandom.hex)
|
||||
update(password: new_password)
|
||||
session_activations.destroy_all
|
||||
end
|
||||
|
||||
# Then, remove all authorized applications and connected push subscriptions
|
||||
revoke_access!
|
||||
|
||||
# Finally, send a reset password prompt to the user
|
||||
send_reset_password_instructions
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
@@ -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/glitch-soc/mastodon:v4.4.5
|
||||
image: ghcr.io/glitch-soc/mastodon:v4.4.6
|
||||
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/glitch-soc/mastodon-streaming:v4.4.5
|
||||
image: ghcr.io/glitch-soc/mastodon-streaming:v4.4.6
|
||||
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/glitch-soc/mastodon:v4.4.5
|
||||
image: ghcr.io/glitch-soc/mastodon:v4.4.6
|
||||
restart: always
|
||||
env_file: .env.production
|
||||
command: bundle exec sidekiq
|
||||
|
||||
@@ -165,14 +165,17 @@ module Mastodon::CLI
|
||||
user.role_id = nil
|
||||
end
|
||||
|
||||
password = SecureRandom.hex if options[:reset_password]
|
||||
user.password = password if options[:reset_password]
|
||||
user.email = options[:email] if options[:email]
|
||||
user.disabled = false if options[:enable]
|
||||
user.disabled = true if options[:disable]
|
||||
user.approved = true if options[:approve]
|
||||
user.disable_two_factor! if options[:disable_2fa]
|
||||
|
||||
# Password changes are a little different, as we also need to ensure
|
||||
# sessions, subscriptions, and access tokens are revoked after changing:
|
||||
password = SecureRandom.hex if options[:reset_password]
|
||||
user.change_password!(password) if options[:reset_password]
|
||||
|
||||
if user.save
|
||||
user.confirm if options[:confirm]
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ module Mastodon
|
||||
end
|
||||
|
||||
def patch
|
||||
5
|
||||
6
|
||||
end
|
||||
|
||||
def default_prerelease
|
||||
|
||||
@@ -361,11 +361,20 @@ RSpec.describe Mastodon::CLI::Accounts do
|
||||
context 'with --reset-password option' do
|
||||
let(:options) { { reset_password: true } }
|
||||
|
||||
let(:user) { Fabricate(:user, password: original_password) }
|
||||
let(:original_password) { 'foobar12345' }
|
||||
let(:new_password) { 'new_password12345' }
|
||||
|
||||
it 'returns a new password for the user' do
|
||||
allow(SecureRandom).to receive(:hex).and_return('new_password')
|
||||
allow(SecureRandom).to receive(:hex).and_return(new_password)
|
||||
allow(Account).to receive(:find_local).and_return(user.account)
|
||||
allow(user).to receive(:change_password!).and_call_original
|
||||
|
||||
expect { subject }
|
||||
.to output_results('new_password')
|
||||
.to output_results(new_password)
|
||||
|
||||
expect(user).to have_received(:change_password!).with(new_password)
|
||||
expect(user.reload).to_not be_external_or_valid_password(original_password)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -476,12 +476,15 @@ RSpec.describe User do
|
||||
|
||||
let(:current_sign_in_at) { Time.zone.now }
|
||||
|
||||
before do
|
||||
user.disable!
|
||||
end
|
||||
|
||||
it 'disables user' do
|
||||
allow(redis).to receive(:publish)
|
||||
|
||||
user.disable!
|
||||
|
||||
expect(user).to have_attributes(disabled: true)
|
||||
|
||||
expect(redis)
|
||||
.to have_received(:publish).with("timeline:system:#{user.account.id}", Oj.dump(event: :kill)).once
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -74,4 +74,52 @@ RSpec.describe 'Streaming', :inline_jobs, :streaming do
|
||||
expect(streaming_client.open?).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a disabled user account' do
|
||||
before do
|
||||
user.disable!
|
||||
end
|
||||
|
||||
it 'receives an 401 unauthorized error when trying to connect' do
|
||||
streaming_client.connect
|
||||
|
||||
expect(streaming_client.status).to eq(401)
|
||||
expect(streaming_client.open?).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user account is disabled whilst connected' do
|
||||
it 'terminates the connection for the user' do
|
||||
streaming_client.connect
|
||||
|
||||
user.disable!
|
||||
|
||||
expect(streaming_client.wait_for(:closed).code).to be(1000)
|
||||
expect(streaming_client.open?).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a suspended user account' do
|
||||
before do
|
||||
user.account.suspend!
|
||||
end
|
||||
|
||||
it 'receives an 401 unauthorized error when trying to connect' do
|
||||
streaming_client.connect
|
||||
|
||||
expect(streaming_client.status).to eq(401)
|
||||
expect(streaming_client.open?).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user account is suspended whilst connected' do
|
||||
it 'terminates the connection for the user' do
|
||||
streaming_client.connect
|
||||
|
||||
user.account.suspend!
|
||||
|
||||
expect(streaming_client.wait_for(:closed).code).to be(1000)
|
||||
expect(streaming_client.open?).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
1097
streaming/index.js
1097
streaming/index.js
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user