Merge tag 'v4.3.0-rc.1'
This commit is contained in:
commit
26c9b9ba39
3459 changed files with 130932 additions and 69993 deletions
|
|
@ -50,7 +50,7 @@ RSpec.describe ActivityPub::Activity::Add do
|
|||
end
|
||||
|
||||
it 'fetches the status and pins it' do
|
||||
allow(service_stub).to receive(:call) do |uri, id: true, on_behalf_of: nil, request_id: nil| # rubocop:disable Lint/UnusedBlockArgument
|
||||
allow(service_stub).to receive(:call) do |uri, id: true, on_behalf_of: nil, **|
|
||||
expect(uri).to eq 'https://example.com/unknown'
|
||||
expect(id).to be true
|
||||
expect(on_behalf_of&.following?(sender)).to be true
|
||||
|
|
@ -64,7 +64,7 @@ RSpec.describe ActivityPub::Activity::Add do
|
|||
|
||||
context 'when there is no local follower' do
|
||||
it 'tries to fetch the status' do
|
||||
allow(service_stub).to receive(:call) do |uri, id: true, on_behalf_of: nil, request_id: nil| # rubocop:disable Lint/UnusedBlockArgument
|
||||
allow(service_stub).to receive(:call) do |uri, id: true, on_behalf_of: nil, **|
|
||||
expect(uri).to eq 'https://example.com/unknown'
|
||||
expect(id).to be true
|
||||
expect(on_behalf_of).to be_nil
|
||||
|
|
|
|||
|
|
@ -77,13 +77,6 @@ RSpec.describe ActivityPub::Activity::Create do
|
|||
follower.follow!(sender)
|
||||
end
|
||||
|
||||
around do |example|
|
||||
Sidekiq::Testing.fake! do
|
||||
example.run
|
||||
Sidekiq::Worker.clear_all
|
||||
end
|
||||
end
|
||||
|
||||
it 'correctly processes posts and inserts them in timelines', :aggregate_failures do
|
||||
# Simulate a temporary failure preventing from fetching the parent post
|
||||
stub_request(:get, object_json[:id]).to_return(status: 500)
|
||||
|
|
@ -539,15 +532,21 @@ RSpec.describe ActivityPub::Activity::Create do
|
|||
mediaType: 'image/png',
|
||||
url: 'http://example.com/attachment.png',
|
||||
},
|
||||
{
|
||||
type: 'Document',
|
||||
mediaType: 'image/png',
|
||||
url: 'http://example.com/emoji.png',
|
||||
},
|
||||
],
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates status' do
|
||||
it 'creates status with correctly-ordered media attachments' do
|
||||
status = sender.statuses.first
|
||||
|
||||
expect(status).to_not be_nil
|
||||
expect(status.media_attachments.map(&:remote_url)).to include('http://example.com/attachment.png')
|
||||
expect(status.ordered_media_attachments.map(&:remote_url)).to eq ['http://example.com/attachment.png', 'http://example.com/emoji.png']
|
||||
expect(status.ordered_media_attachment_ids).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -894,58 +893,46 @@ RSpec.describe ActivityPub::Activity::Create do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with an encrypted message' do
|
||||
subject { described_class.new(json, sender, delivery: true, delivered_to_account_id: recipient.id) }
|
||||
context 'when object URI uses bearcaps' do
|
||||
subject { described_class.new(json, sender) }
|
||||
|
||||
let(:token) { 'foo' }
|
||||
|
||||
let(:json) do
|
||||
{
|
||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||
id: [ActivityPub::TagManager.instance.uri_for(sender), '#foo'].join,
|
||||
type: 'Create',
|
||||
actor: ActivityPub::TagManager.instance.uri_for(sender),
|
||||
object: Addressable::URI.new(scheme: 'bear', query_values: { t: token, u: object_json[:id] }).to_s,
|
||||
}.with_indifferent_access
|
||||
end
|
||||
|
||||
let(:recipient) { Fabricate(:account) }
|
||||
let(:object_json) do
|
||||
{
|
||||
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
||||
type: 'EncryptedMessage',
|
||||
attributedTo: {
|
||||
type: 'Device',
|
||||
deviceId: '1234',
|
||||
},
|
||||
to: {
|
||||
type: 'Device',
|
||||
deviceId: target_device.device_id,
|
||||
},
|
||||
messageType: 1,
|
||||
cipherText: 'Foo',
|
||||
messageFranking: 'Baz678',
|
||||
digest: {
|
||||
digestAlgorithm: 'Bar456',
|
||||
digestValue: 'Foo123',
|
||||
},
|
||||
type: 'Note',
|
||||
content: 'Lorem ipsum',
|
||||
to: 'https://www.w3.org/ns/activitystreams#Public',
|
||||
}
|
||||
end
|
||||
let(:target_device) { Fabricate(:device, account: recipient) }
|
||||
|
||||
before do
|
||||
stub_request(:get, object_json[:id])
|
||||
.with(headers: { Authorization: "Bearer #{token}" })
|
||||
.to_return(body: Oj.dump(object_json), headers: { 'Content-Type': 'application/activity+json' })
|
||||
|
||||
subject.perform
|
||||
end
|
||||
|
||||
it 'creates an encrypted message' do
|
||||
encrypted_message = target_device.encrypted_messages.reload.first
|
||||
it 'creates status' do
|
||||
status = sender.statuses.first
|
||||
|
||||
expect(encrypted_message).to_not be_nil
|
||||
expect(encrypted_message.from_device_id).to eq '1234'
|
||||
expect(encrypted_message.from_account).to eq sender
|
||||
expect(encrypted_message.type).to eq 1
|
||||
expect(encrypted_message.body).to eq 'Foo'
|
||||
expect(encrypted_message.digest).to eq 'Foo123'
|
||||
end
|
||||
|
||||
it 'creates a message franking' do
|
||||
encrypted_message = target_device.encrypted_messages.reload.first
|
||||
message_franking = encrypted_message.message_franking
|
||||
|
||||
crypt = ActiveSupport::MessageEncryptor.new(SystemKey.current_key, serializer: Oj)
|
||||
json = crypt.decrypt_and_verify(message_franking)
|
||||
|
||||
expect(json['source_account_id']).to eq sender.id
|
||||
expect(json['target_account_id']).to eq recipient.id
|
||||
expect(json['original_franking']).to eq 'Baz678'
|
||||
expect(status).to_not be_nil
|
||||
expect(status).to have_attributes(
|
||||
visibility: 'public',
|
||||
text: 'Lorem ipsum'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -47,9 +47,13 @@ RSpec.describe ActivityPub::Activity::Delete do
|
|||
expect(Status.find_by(id: status.id)).to be_nil
|
||||
end
|
||||
|
||||
it 'sends delete activity to followers of rebloggers' do
|
||||
it 'sends delete activity to followers of rebloggers', :inline_jobs do
|
||||
expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once
|
||||
end
|
||||
|
||||
it 'deletes the reblog' do
|
||||
expect { reblog.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ RSpec.describe ActivityPub::Activity::Flag do
|
|||
expect(report).to_not be_nil
|
||||
expect(report.comment).to eq 'Boo!!'
|
||||
expect(report.status_ids).to eq [status.id]
|
||||
expect(report.application).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ RSpec.describe ActivityPub::Activity::Flag do
|
|||
}.with_indifferent_access, sender)
|
||||
end
|
||||
|
||||
let(:long_comment) { Faker::Lorem.characters(number: 6000) }
|
||||
let(:long_comment) { 'a' * described_class::COMMENT_SIZE_LIMIT * 2 }
|
||||
|
||||
before do
|
||||
subject.perform
|
||||
|
|
@ -63,10 +64,12 @@ RSpec.describe ActivityPub::Activity::Flag do
|
|||
it 'creates a report but with a truncated comment' do
|
||||
report = Report.find_by(account: sender, target_account: flagged)
|
||||
|
||||
expect(report).to_not be_nil
|
||||
expect(report.comment.length).to eq 5000
|
||||
expect(report.comment).to eq long_comment[0...5000]
|
||||
expect(report.status_ids).to eq [status.id]
|
||||
expect(report)
|
||||
.to be_present
|
||||
.and have_attributes(status_ids: [status.id])
|
||||
expect(report.comment)
|
||||
.to have_attributes(length: described_class::COMMENT_SIZE_LIMIT)
|
||||
.and eq(long_comment[0...described_class::COMMENT_SIZE_LIMIT])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::Activity::Move do
|
||||
RSpec::Matchers.define_negated_matcher :not_be_following, :be_following
|
||||
RSpec::Matchers.define_negated_matcher :not_be_requested, :be_requested
|
||||
|
||||
let(:follower) { Fabricate(:account) }
|
||||
let(:old_account) { Fabricate(:account, uri: 'https://example.org/alice', domain: 'example.org', protocol: :activitypub, inbox_url: 'https://example.org/inbox') }
|
||||
let(:new_account) { Fabricate(:account, uri: 'https://example.com/alice', domain: 'example.com', protocol: :activitypub, inbox_url: 'https://example.com/inbox', also_known_as: also_known_as) }
|
||||
|
|
@ -38,49 +41,37 @@ RSpec.describe ActivityPub::Activity::Move do
|
|||
subject.perform
|
||||
end
|
||||
|
||||
context 'when all conditions are met' do
|
||||
it 'sets moved account on old account' do
|
||||
expect(old_account.reload.moved_to_account_id).to eq new_account.id
|
||||
end
|
||||
|
||||
it 'makes followers unfollow old account' do
|
||||
expect(follower.following?(old_account)).to be false
|
||||
end
|
||||
|
||||
it 'makes followers follow-request the new account' do
|
||||
expect(follower.requested?(new_account)).to be true
|
||||
context 'when all conditions are met', :inline_jobs do
|
||||
it 'sets moved on old account, followers unfollow old account, followers request the new account' do
|
||||
expect(old_account.reload.moved_to_account_id)
|
||||
.to eq new_account.id
|
||||
expect(follower)
|
||||
.to not_be_following(old_account)
|
||||
.and be_requested(new_account)
|
||||
end
|
||||
end
|
||||
|
||||
context "when the new account can't be resolved" do
|
||||
let(:returned_account) { nil }
|
||||
|
||||
it 'does not set moved account on old account' do
|
||||
expect(old_account.reload.moved_to_account_id).to be_nil
|
||||
end
|
||||
|
||||
it 'does not make followers unfollow old account' do
|
||||
expect(follower.following?(old_account)).to be true
|
||||
end
|
||||
|
||||
it 'does not make followers follow-request the new account' do
|
||||
expect(follower.requested?(new_account)).to be false
|
||||
it 'does not set moved on old account, does not unfollow old, does not follow request new' do
|
||||
expect(old_account.reload.moved_to_account_id)
|
||||
.to be_nil
|
||||
expect(follower)
|
||||
.to be_following(old_account)
|
||||
.and not_be_requested(new_account)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the new account does not references the old account' do
|
||||
let(:also_known_as) { [] }
|
||||
|
||||
it 'does not set moved account on old account' do
|
||||
expect(old_account.reload.moved_to_account_id).to be_nil
|
||||
end
|
||||
|
||||
it 'does not make followers unfollow old account' do
|
||||
expect(follower.following?(old_account)).to be true
|
||||
end
|
||||
|
||||
it 'does not make followers follow-request the new account' do
|
||||
expect(follower.requested?(new_account)).to be false
|
||||
it 'does not set moved on old account, does not unfollow old, does not follow request new' do
|
||||
expect(old_account.reload.moved_to_account_id)
|
||||
.to be_nil
|
||||
expect(follower)
|
||||
.to be_following(old_account)
|
||||
.and not_be_requested(new_account)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -91,16 +82,12 @@ RSpec.describe ActivityPub::Activity::Move do
|
|||
redis.del("move_in_progress:#{old_account.id}")
|
||||
end
|
||||
|
||||
it 'does not set moved account on old account' do
|
||||
expect(old_account.reload.moved_to_account_id).to be_nil
|
||||
end
|
||||
|
||||
it 'does not make followers unfollow old account' do
|
||||
expect(follower.following?(old_account)).to be true
|
||||
end
|
||||
|
||||
it 'does not make followers follow-request the new account' do
|
||||
expect(follower.requested?(new_account)).to be false
|
||||
it 'does not set moved on old account, does not unfollow old, does not follow request new' do
|
||||
expect(old_account.reload.moved_to_account_id)
|
||||
.to be_nil
|
||||
expect(follower)
|
||||
.to be_following(old_account)
|
||||
.and not_be_requested(new_account)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ RSpec.describe ActivityPub::Adapter do
|
|||
describe '#serializable_hash' do
|
||||
subject { ActiveModelSerializers::SerializableResource.new(TestObject.new(foo: 'bar'), serializer: serializer_class, adapter: described_class).as_json }
|
||||
|
||||
let(:serializer_class) {}
|
||||
let(:serializer_class) { nil }
|
||||
|
||||
context 'when serializer defines no context' do
|
||||
let(:serializer_class) { TestWithBasicContextSerializer }
|
||||
|
|
|
|||
|
|
@ -18,10 +18,6 @@ RSpec.describe ActivityPub::LinkedDataSignature do
|
|||
|
||||
let(:json) { raw_json.merge('signature' => signature) }
|
||||
|
||||
before do
|
||||
stub_jsonld_contexts!
|
||||
end
|
||||
|
||||
describe '#verify_actor!' do
|
||||
context 'when signature matches' do
|
||||
let(:raw_signature) do
|
||||
|
|
@ -99,16 +95,11 @@ RSpec.describe ActivityPub::LinkedDataSignature do
|
|||
describe '#sign!' do
|
||||
subject { described_class.new(raw_json).sign!(sender) }
|
||||
|
||||
it 'returns a hash' do
|
||||
it 'returns a hash with a signature, the expected context, and the signature can be verified', :aggregate_failures do
|
||||
expect(subject).to be_a Hash
|
||||
end
|
||||
|
||||
it 'contains signature' do
|
||||
expect(subject['signature']).to be_a Hash
|
||||
expect(subject['signature']['signatureValue']).to be_present
|
||||
end
|
||||
|
||||
it 'can be verified again' do
|
||||
expect(Array(subject['@context'])).to include('https://w3id.org/security/v1')
|
||||
expect(described_class.new(subject).verify_actor!).to eq sender
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -52,20 +52,27 @@ RSpec.describe ActivityPub::TagManager do
|
|||
expect(subject.to(status)).to include(subject.followers_uri_for(mentioned))
|
||||
end
|
||||
|
||||
it "returns URIs of mentions for direct silenced author's status only if they are followers or requesting to be" do
|
||||
bob = Fabricate(:account, username: 'bob')
|
||||
alice = Fabricate(:account, username: 'alice')
|
||||
foo = Fabricate(:account)
|
||||
author = Fabricate(:account, username: 'author', silenced: true)
|
||||
status = Fabricate(:status, visibility: :direct, account: author)
|
||||
bob.follow!(author)
|
||||
FollowRequest.create!(account: foo, target_account: author)
|
||||
status.mentions.create(account: alice)
|
||||
status.mentions.create(account: bob)
|
||||
status.mentions.create(account: foo)
|
||||
expect(subject.to(status)).to include(subject.uri_for(bob))
|
||||
expect(subject.to(status)).to include(subject.uri_for(foo))
|
||||
expect(subject.to(status)).to_not include(subject.uri_for(alice))
|
||||
context 'with followers and requested followers' do
|
||||
let!(:bob) { Fabricate(:account, username: 'bob') }
|
||||
let!(:alice) { Fabricate(:account, username: 'alice') }
|
||||
let!(:foo) { Fabricate(:account) }
|
||||
let!(:author) { Fabricate(:account, username: 'author', silenced: true) }
|
||||
let!(:status) { Fabricate(:status, visibility: :direct, account: author) }
|
||||
|
||||
before do
|
||||
bob.follow!(author)
|
||||
FollowRequest.create!(account: foo, target_account: author)
|
||||
status.mentions.create(account: alice)
|
||||
status.mentions.create(account: bob)
|
||||
status.mentions.create(account: foo)
|
||||
end
|
||||
|
||||
it "returns URIs of mentions for direct silenced author's status only if they are followers or requesting to be" do
|
||||
expect(subject.to(status))
|
||||
.to include(subject.uri_for(bob))
|
||||
.and include(subject.uri_for(foo))
|
||||
.and not_include(subject.uri_for(alice))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -97,20 +104,35 @@ RSpec.describe ActivityPub::TagManager do
|
|||
expect(subject.cc(status)).to include(subject.uri_for(mentioned))
|
||||
end
|
||||
|
||||
it "returns URIs of mentions for silenced author's non-direct status only if they are followers or requesting to be" do
|
||||
bob = Fabricate(:account, username: 'bob')
|
||||
context 'with followers and requested followers' do
|
||||
let!(:bob) { Fabricate(:account, username: 'bob') }
|
||||
let!(:alice) { Fabricate(:account, username: 'alice') }
|
||||
let!(:foo) { Fabricate(:account) }
|
||||
let!(:author) { Fabricate(:account, username: 'author', silenced: true) }
|
||||
let!(:status) { Fabricate(:status, visibility: :public, account: author) }
|
||||
|
||||
before do
|
||||
bob.follow!(author)
|
||||
FollowRequest.create!(account: foo, target_account: author)
|
||||
status.mentions.create(account: alice)
|
||||
status.mentions.create(account: bob)
|
||||
status.mentions.create(account: foo)
|
||||
end
|
||||
|
||||
it "returns URIs of mentions for silenced author's non-direct status only if they are followers or requesting to be" do
|
||||
expect(subject.cc(status))
|
||||
.to include(subject.uri_for(bob))
|
||||
.and include(subject.uri_for(foo))
|
||||
.and not_include(subject.uri_for(alice))
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns poster of reblogged post, if reblog' do
|
||||
bob = Fabricate(:account, username: 'bob', domain: 'example.com', inbox_url: 'http://example.com/bob')
|
||||
alice = Fabricate(:account, username: 'alice')
|
||||
foo = Fabricate(:account)
|
||||
author = Fabricate(:account, username: 'author', silenced: true)
|
||||
status = Fabricate(:status, visibility: :public, account: author)
|
||||
bob.follow!(author)
|
||||
FollowRequest.create!(account: foo, target_account: author)
|
||||
status.mentions.create(account: alice)
|
||||
status.mentions.create(account: bob)
|
||||
status.mentions.create(account: foo)
|
||||
expect(subject.cc(status)).to include(subject.uri_for(bob))
|
||||
expect(subject.cc(status)).to include(subject.uri_for(foo))
|
||||
expect(subject.cc(status)).to_not include(subject.uri_for(alice))
|
||||
status = Fabricate(:status, visibility: :public, account: bob)
|
||||
reblog = Fabricate(:status, visibility: :public, account: alice, reblog: status)
|
||||
expect(subject.cc(reblog)).to include(subject.uri_for(bob))
|
||||
end
|
||||
|
||||
it 'returns poster of reblogged post, if reblog' do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue