diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 7febce7645..8551238911 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -514,7 +514,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity note = @account&.note return nil if note.blank? - searchability_bio = note.scan(SCAN_SEARCHABILITY_RE).first || note.scan(SCAN_SEARCHABILITY_FEDIBIRD_RE).first + searchability_bio = note.scan(SCAN_SEARCHABILITY_FEDIBIRD_RE).first || note.scan(SCAN_SEARCHABILITY_RE).first return nil unless searchability_bio searchability = searchability_bio[0] diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index 24a68a8c21..563fa5aa07 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -269,9 +269,11 @@ class ActivityPub::ProcessAccountService < BaseService if audience_searchable_by.any? { |uri| ActivityPub::TagManager.instance.public_collection?(uri) } :public elsif audience_searchable_by.include?(@account.followers_url) - :private # Followers only in kmyblue (generics: private) + :private + elsif audience_searchable_by.include?('as:Limited') + :limited else - :direct # Reaction only in kmyblue (generics: direct) + :direct end end @@ -279,7 +281,7 @@ class ActivityPub::ProcessAccountService < BaseService note = @json['summary'] || '' return nil if note.blank? - searchability_bio = note.scan(SCAN_SEARCHABILITY_RE).first || note.scan(SCAN_SEARCHABILITY_FEDIBIRD_RE).first + searchability_bio = note.scan(SCAN_SEARCHABILITY_FEDIBIRD_RE).first || note.scan(SCAN_SEARCHABILITY_RE).first return nil unless searchability_bio searchability = searchability_bio[0] diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index 43c7c13e96..151da1c4e5 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -503,7 +503,7 @@ RSpec.describe ActivityPub::Activity::Create do end context 'with multible searchabilities' do - let(:bio) { '#searchable_by_nobody' } + let(:sender_bio) { '#searchable_by_nobody' } let(:searchable_by) { 'https://www.w3.org/ns/activitystreams#Public' } let(:object_json) do { diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index 8c37b1accc..24fab0bd91 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -114,6 +114,72 @@ RSpec.describe Status do end end + describe '#searchability' do + subject { Fabricate(:status, account: account, searchability: status_searchability) } + + let(:account_searchability) { :public } + let(:status_searchability) { :public } + let(:account_domain) { 'example.com' } + let(:account) { Fabricate(:account, domain: account_domain, searchability: account_searchability) } + + context 'when public-public' do + it 'returns public' do + expect(subject.compute_searchability).to eq 'public' + end + end + + context 'when public-private' do + let(:status_searchability) { :private } + + it 'returns private' do + expect(subject.compute_searchability).to eq 'private' + end + end + + context 'when public-direct' do + let(:status_searchability) { :direct } + + it 'returns direct' do + expect(subject.compute_searchability).to eq 'direct' + end + end + + context 'when private-public' do + let(:account_searchability) { :private } + + it 'returns private' do + expect(subject.compute_searchability).to eq 'private' + end + end + + context 'when direct-public' do + let(:account_searchability) { :direct } + + it 'returns direct' do + expect(subject.compute_searchability).to eq 'direct' + end + end + + context 'when private-limited' do + let(:account_searchability) { :private } + let(:status_searchability) { :limited } + + it 'returns limited' do + expect(subject.compute_searchability).to eq 'limited' + end + end + + context 'when private-public of local account' do + let(:account_searchability) { :private } + let(:account_domain) { nil } + let(:status_searchability) { :public } + + it 'returns public' do + expect(subject.compute_searchability).to eq 'public' + end + end + end + describe '#content' do it 'returns the text of the status if it is not a reblog' do expect(subject.content).to eql subject.text diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb index a84ca28e21..1ea3b6491b 100644 --- a/spec/services/activitypub/process_account_service_spec.rb +++ b/spec/services/activitypub/process_account_service_spec.rb @@ -5,6 +5,113 @@ require 'rails_helper' RSpec.describe ActivityPub::ProcessAccountService, type: :service do subject { described_class.new } + context 'with searchability' do + subject { described_class.new.call('alice', 'example.com', payload) } + + let(:software) { 'mastodon' } + let(:searchable_by) { 'https://www.w3.org/ns/activitystreams#Public' } + let(:sender_bio) { '' } + let(:payload) do + { + id: 'https://foo.test', + type: 'Actor', + inbox: 'https://foo.test/inbox', + followers: 'https://example.com/followers', + searchableBy: searchable_by, + summary: sender_bio, + }.with_indifferent_access + end + + before do + Fabricate(:instance_info, domain: 'example.com', software: software) + stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '{}') + stub_request(:get, 'https://example.com/followers').to_return(body: '[]') + end + + context 'when public' do + it 'searchability is public' do + expect(subject.searchability).to eq 'public' + end + end + + context 'when private' do + let(:searchable_by) { 'https://example.com/followers' } + + it 'searchability is private' do + expect(subject.searchability).to eq 'private' + end + end + + context 'when direct' do + let(:searchable_by) { '' } + + it 'searchability is direct' do + expect(subject.searchability).to eq 'direct' + end + end + + context 'when limited' do + let(:searchable_by) { 'as:Limited' } + + it 'searchability is limited' do + expect(subject.searchability).to eq 'limited' + end + end + + context 'when default value' do + let(:searchable_by) { nil } + + it 'searchability is direct' do + expect(subject.searchability).to eq 'direct' + end + end + + context 'when misskey user' do + let(:software) { 'misskey' } + let(:searchable_by) { nil } + + it 'searchability is public' do + expect(subject.searchability).to eq 'public' + end + end + + context 'with bio' do + let(:searchable_by) { nil } + + context 'with public' do + let(:sender_bio) { '#searchable_by_all_users' } + + it 'searchability is public' do + expect(subject.searchability).to eq 'public' + end + end + + context 'with private' do + let(:sender_bio) { '#searchable_by_followers_only' } + + it 'searchability is private' do + expect(subject.searchability).to eq 'private' + end + end + + context 'with direct' do + let(:sender_bio) { '#searchable_by_reacted_users_only' } + + it 'searchability is direct' do + expect(subject.searchability).to eq 'direct' + end + end + + context 'with limited' do + let(:sender_bio) { '#searchable_by_nobody' } + + it 'searchability is limited' do + expect(subject.searchability).to eq 'limited' + end + end + end + end + context 'with property values' do let(:payload) do {