Skip to content

Commit

Permalink
Wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kmycode committed Feb 28, 2024
1 parent 8292e20 commit 25683ec
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 3 deletions.
5 changes: 5 additions & 0 deletions app/models/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -298,14 +298,19 @@ def unsuspend!
end

def approve_remote!
return unless remote_pending

update!(remote_pending: false)
unsuspend!
ActivateRemoteAccountWorker.perform_async(id)
end

def reject_remote!
return unless remote_pending

update!(remote_pending: false, suspension_origin: :local)
pending_follow_requests.destroy_all
pending_statuses.destroy_all
suspend!
end

Expand Down
5 changes: 5 additions & 0 deletions app/models/concerns/account/associations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ module Account::Associations
has_many :account_warnings, dependent: :destroy, inverse_of: :account
has_many :strikes, class_name: 'AccountWarning', foreign_key: :target_account_id, dependent: :destroy, inverse_of: :target_account

# Remote pendings
has_many :pending_follow_requests, dependent: :destroy
has_many :pending_statuses, dependent: :destroy
has_many :fetchable_pending_statuses, class_name: 'PendingStatus', foreign_key: :fetch_account_id, dependent: :destroy, inverse_of: :fetch_account

# Antennas (that the account is on, not owned by the account)
has_many :antenna_accounts, inverse_of: :account, dependent: :destroy
has_many :joined_antennas, class_name: 'Antenna', through: :antenna_accounts, source: :antenna
Expand Down
1 change: 0 additions & 1 deletion app/models/concerns/account/interactions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ def follow_mapping(query, field)
included do
# Follow relations
has_many :follow_requests, dependent: :destroy
has_many :pending_follow_requests, dependent: :destroy

with_options class_name: 'Follow', dependent: :destroy do
has_many :active_relationships, foreign_key: 'account_id', inverse_of: :account
Expand Down
4 changes: 3 additions & 1 deletion app/services/activate_remote_statuses_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ def call(account)
def approve_status!(pending)
account_id = pending.account_id
fetch_account_id = pending.fetch_account_id
fetch_account = pending.fetch_account
uri = pending.uri
pending.destroy!

return if fetch_account.suspended?
return if ActivityPub::TagManager.instance.uri_to_resource(uri, Status).present?

FetchRemoteStatusWorker.perform_async(uri, account_id, fetch_account_id)
ActivityPub::FetchRemoteStatusWorker.perform_async(uri, account_id, fetch_account_id)
end
end
4 changes: 4 additions & 0 deletions app/services/delete_account_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class DeleteAccountService < BaseService
devices
domain_blocks
featured_tags
fetchable_pending_statuses
follow_requests
list_accounts
migrations
Expand All @@ -29,6 +30,7 @@ class DeleteAccountService < BaseService
owned_lists
passive_relationships
pending_follow_requests
pending_statuses
report_notes
scheduled_statuses
scheduled_expiration_statuses
Expand All @@ -51,6 +53,7 @@ class DeleteAccountService < BaseService
devices
domain_blocks
featured_tags
fetchable_pending_statuses
follow_requests
list_accounts
migrations
Expand All @@ -59,6 +62,7 @@ class DeleteAccountService < BaseService
notifications
owned_lists
pending_follow_requests
pending_statuses
scheduled_statuses
scheduled_expiration_statuses
status_pins
Expand Down
2 changes: 1 addition & 1 deletion app/workers/activitypub/fetch_remote_status_worker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def perform(uri, author_account_id, on_behalf_of_account_id)
author = Account.find(author_account_id)
on_behalf_of = on_behalf_of_account_id.present? ? Account.find(on_behalf_of_account_id) : nil

ActivityPub::FetchRemoteStatusService.new.call(uri, on_behalf_of: on_behalf_of, expected_actor_uri: author, request_id: uri)
ActivityPub::FetchRemoteStatusService.new.call(uri, on_behalf_of: on_behalf_of, expected_actor_uri: ActivityPub::TagManager.instance.uri_for(author), request_id: uri)
rescue ActiveRecord::RecordNotFound, Mastodon::RaceConditionError
true
end
Expand Down
7 changes: 7 additions & 0 deletions spec/fabricators/pending_status_fabricator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

Fabricator(:pending_status) do
account { Fabricate.build(:account) }
fetch_account { Fabricate.build(:account) }
uri { "https://example.com/#{Time.now.utc.nsec}" }
end
12 changes: 12 additions & 0 deletions spec/models/account_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,18 @@
end
end

describe '#approve_remote!' do
it 'calls worker' do
account = Fabricate(:account, suspended_at: Time.now.utc, suspension_origin: :local, remote_pending: true)
allow(ActivateRemoteAccountWorker).to receive(:perform_async)

account.approve_remote!
expect(account.remote_pending).to be false
expect(account.suspended?).to be false
expect(ActivateRemoteAccountWorker).to have_received(:perform_async).with(account.id)
end
end

describe '#favourited?' do
subject { Fabricate(:account) }

Expand Down
67 changes: 67 additions & 0 deletions spec/services/activate_remote_statuses_service_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe ActivateRemoteStatusesService, type: :service do
subject { described_class.new.call(sender) }

let(:sender) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor') }
let(:alice) { Fabricate(:account) }
let!(:pending_status) { Fabricate(:pending_status, account: sender, fetch_account: alice, uri: 'https://example.com/note') }

let(:payload) do
{
'@context': 'https://www.w3.org/ns/activitystreams',
id: pending_status.uri,
attributedTo: sender.uri,
type: 'Note',
content: 'Lorem ipsum',
to: 'https://www.w3.org/ns/activitystreams#Public',
tag: [
{
type: 'Mention',
href: ActivityPub::TagManager.instance.uri_for(alice),
},
],
}
end
let(:json) { Oj.dump(payload) }

before do
stub_request(:get, 'https://example.com/note').to_return(status: 200, body: json, headers: { 'Content-Type': 'application/activity+json' })
end

context 'when has a pending status' do
before do
subject
end

it 'original status is fetched', :sidekiq_inline do
status = sender.statuses.first

expect(status).to_not be_nil
expect(status.text).to eq 'Lorem ipsum'
end

it 'pending request is removed' do
expect { pending_status.reload }.to raise_error ActiveRecord::RecordNotFound
end
end

context 'when target_account is suspended' do
before do
alice.suspend!
subject
end

it 'original status is not fetched', :sidekiq_inline do
status = sender.statuses.first

expect(status).to be_nil
end

it 'pending request is removed' do
expect { pending_status.reload }.to raise_error ActiveRecord::RecordNotFound
end
end
end
6 changes: 6 additions & 0 deletions spec/services/delete_account_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
let!(:account_note) { Fabricate(:account_note, account: account) }

let!(:ng_rule_history) { Fabricate(:ng_rule_history, account: account) }
let!(:pending_follow_request) { Fabricate(:pending_follow_request, account: account) }
let!(:pending_status) { Fabricate(:pending_status, account: account, uri: 'https://example.com/note1') }
let!(:fetchable_pending_status) { Fabricate(:pending_status, fetch_account: account, uri: 'https://example.com/note2') }

it 'deletes associated owned and target records and target notifications' do
subject
Expand Down Expand Up @@ -77,6 +80,9 @@
expect { circle_account.reload }.to raise_error(ActiveRecord::RecordNotFound)
expect { circle_status.reload }.to raise_error(ActiveRecord::RecordNotFound)
expect { bookmark_category_status.reload }.to raise_error(ActiveRecord::RecordNotFound)
expect { pending_follow_request.reload }.to raise_error(ActiveRecord::RecordNotFound)
expect { pending_status.reload }.to raise_error(ActiveRecord::RecordNotFound)
expect { fetchable_pending_status.reload }.to raise_error(ActiveRecord::RecordNotFound)
end

def expect_deletion_of_associated_owned_records
Expand Down
41 changes: 41 additions & 0 deletions spec/workers/activitypub/fetch_remote_status_worker_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# frozen_string_literal: true

require 'rails_helper'

describe ActivityPub::FetchRemoteStatusWorker do
subject { described_class.new }

let(:sender) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor') }
let(:payload) do
{
'@context': 'https://www.w3.org/ns/activitystreams',
id: 'https://example.com/note',
attributedTo: sender.uri,
type: 'Note',
content: 'Lorem ipsum',
to: 'https://www.w3.org/ns/activitystreams#Public',
tag: [
{
type: 'Mention',
href: ActivityPub::TagManager.instance.uri_for(Fabricate(:account)),
},
],
}
end
let(:json) { Oj.dump(payload) }

before do
stub_request(:get, 'https://example.com/note').to_return(status: 200, body: json, headers: { 'Content-Type': 'application/activity+json' })
end

describe '#perform' do
it 'original status is fetched' do
subject.perform('https://example.com/note', sender.id, Fabricate(:account).id)

status = sender.statuses.first

expect(status).to_not be_nil
expect(status.text).to eq 'Lorem ipsum'
end
end
end

0 comments on commit 25683ec

Please sign in to comment.