From 138fee197cda1058b484b5ee9fc371b9c44e5479 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Fri, 24 May 2024 11:44:15 +0200 Subject: [PATCH] Don't update non unique usernames on remote domains --- app/lib/activitypub/activity/update.rb | 14 +++++- spec/lib/activitypub/activity/update_spec.rb | 48 +++++++++++++++++++- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/app/lib/activitypub/activity/update.rb b/app/lib/activitypub/activity/update.rb index 71b6ba5ca41..5e190c227c4 100644 --- a/app/lib/activitypub/activity/update.rb +++ b/app/lib/activitypub/activity/update.rb @@ -20,7 +20,19 @@ class ActivityPub::Activity::Update < ActivityPub::Activity def update_account return reject_payload! if @account.uri != object_uri - ActivityPub::ProcessAccountService.new.call(@account.username, @account.domain, @object, signed_with_known_key: true, request_id: @options[:request_id], allow_username_update: true) + opts = { + signed_with_known_key: true, + request_id: @options[:request_id], + } + + if @account.username != @object['preferredUsername'] + account_proxy = @account.dup + account_proxy.username = @object['preferredUsername'] + UniqueUsernameValidator.new.validate(account_proxy) + opts[:allow_username_update] = true if account_proxy.errors.blank? + end + + ActivityPub::ProcessAccountService.new.call(@account.username, @account.domain, @object, opts) end def update_status diff --git a/spec/lib/activitypub/activity/update_spec.rb b/spec/lib/activitypub/activity/update_spec.rb index 87e96d2d1b1..5393e69bd9b 100644 --- a/spec/lib/activitypub/activity/update_spec.rb +++ b/spec/lib/activitypub/activity/update_spec.rb @@ -55,13 +55,57 @@ RSpec.describe ActivityPub::Activity::Update do stub_request(:get, actor_json[:following]).to_return(status: 404) stub_request(:get, actor_json[:featured]).to_return(status: 404) stub_request(:get, actor_json[:featuredTags]).to_return(status: 404) - - subject.perform end it 'updates profile' do + subject.perform expect(sender.reload.display_name).to eq 'Totally modified now' end + + context 'when Actor username changes' do + let!(:original_username) { sender.username } + let!(:updated_username) { 'updated_username' } + let(:updated_username_json) { actor_json.merge(preferredUsername: updated_username) } + let(:json) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: 'foo', + type: 'Update', + actor: sender.uri, + object: updated_username_json, + }.with_indifferent_access + end + + it 'updates profile' do + subject.perform + expect(sender.reload.display_name).to eq 'Totally modified now' + end + + it 'updates username' do + subject.perform + expect(sender.reload.username).to eq updated_username + end + + context 'when updated username is not unique for domain' do + before do + Fabricate(:account, + username: updated_username, + domain: 'example.com', + inbox_url: "https://example.com/#{updated_username}/inbox", + outbox_url: "https://example.com/#{updated_username}/outbox") + end + + it 'updates profile' do + subject.perform + expect(sender.reload.display_name).to eq 'Totally modified now' + end + + it 'does not update username' do + subject.perform + expect(sender.reload.username).to eq original_username + end + end + end end context 'with a Question object' do