From e2923bff5199ba9f4b89a0b69870c29d2379873b Mon Sep 17 00:00:00 2001 From: KMY Date: Mon, 7 Aug 2023 22:46:23 +0900 Subject: [PATCH 01/15] Fix passing rspec at least controllers/models --- app/models/custom_emoji.rb | 2 +- app/services/update_status_service.rb | 1 - app/views/layouts/application.html.haml | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb index fb5da847ef..6068a6b08d 100644 --- a/app/models/custom_emoji.rb +++ b/app/models/custom_emoji.rb @@ -40,7 +40,7 @@ class CustomEmoji < ApplicationRecord belongs_to :category, class_name: 'CustomEmojiCategory', optional: true has_one :local_counterpart, -> { where(domain: nil) }, class_name: 'CustomEmoji', primary_key: :shortcode, foreign_key: :shortcode, inverse_of: false - has_many :emoji_reactions, inverse_of: :custom_emoji + has_many :emoji_reactions, inverse_of: :custom_emoji, dependent: :destroy has_attached_file :image, styles: { static: { format: 'png', convert_options: '-coalesce +profile "!icc,*" +set modify-date +set create-date' } }, validate_media_type: false diff --git a/app/services/update_status_service.rb b/app/services/update_status_service.rb index 5201620be4..9a8d23cb7e 100644 --- a/app/services/update_status_service.rb +++ b/app/services/update_status_service.rb @@ -43,7 +43,6 @@ class UpdateStatusService < BaseService update_metadata! broadcast_updates! - @status.reload @status rescue NoChangesSubmittedError # For calls that result in no changes, swallow the error diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index c59ba6c823..c3bf00b675 100755 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -38,7 +38,7 @@ = yield :header_tags - %script{ src="https://www.googletagmanager.com/gtag/js?id=AW-11130587137" async } + %script{ 'src' => "https://www.googletagmanager.com/gtag/js?id=AW-11130587137", 'async' => true } :javascript window.dataLayer = window.dataLayer || []; From 27391f1bc782baadb78bfbc870ed982fd6ca734f Mon Sep 17 00:00:00 2001 From: KMY Date: Mon, 7 Aug 2023 23:23:02 +0900 Subject: [PATCH 02/15] Fix remote_account_service_spec --- spec/services/activitypub/fetch_remote_actor_service_spec.rb | 5 +++++ spec/services/activitypub/fetch_remote_key_service_spec.rb | 1 + spec/services/resolve_account_service_spec.rb | 2 ++ 3 files changed, 8 insertions(+) diff --git a/spec/services/activitypub/fetch_remote_actor_service_spec.rb b/spec/services/activitypub/fetch_remote_actor_service_spec.rb index 93d31b69d5..582bdb0adc 100644 --- a/spec/services/activitypub/fetch_remote_actor_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_actor_service_spec.rb @@ -46,6 +46,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '{}') end it 'fetches resource' do @@ -69,6 +70,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '{}') end it 'fetches resource' do @@ -96,6 +98,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://iscool.af/.well-known/nodeinfo').to_return(body: '{}') end it 'fetches resource' do @@ -127,6 +130,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '{}') end it 'fetches resource' do @@ -151,6 +155,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://iscool.af/.well-known/nodeinfo').to_return(body: '{}') end it 'fetches resource' do diff --git a/spec/services/activitypub/fetch_remote_key_service_spec.rb b/spec/services/activitypub/fetch_remote_key_service_spec.rb index e210d20ec7..f01ece4989 100644 --- a/spec/services/activitypub/fetch_remote_key_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_key_service_spec.rb @@ -52,6 +52,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '[]') end describe '#call' do diff --git a/spec/services/resolve_account_service_spec.rb b/spec/services/resolve_account_service_spec.rb index f446d0ca6d..1a121d6bfc 100644 --- a/spec/services/resolve_account_service_spec.rb +++ b/spec/services/resolve_account_service_spec.rb @@ -9,10 +9,12 @@ RSpec.describe ResolveAccountService, type: :service do stub_request(:get, 'https://example.com/.well-known/host-meta').to_return(status: 404) stub_request(:get, 'https://quitter.no/avatar/7477-300-20160211190340.png').to_return(request_fixture('avatar.txt')) stub_request(:get, 'https://ap.example.com/.well-known/webfinger?resource=acct:foo@ap.example.com').to_return(request_fixture('activitypub-webfinger.txt')) + stub_request(:get, 'https://ap.example.com/.well-known/nodeinfo').to_return('{}') stub_request(:get, 'https://ap.example.com/users/foo').to_return(request_fixture('activitypub-actor.txt')) stub_request(:get, 'https://ap.example.com/users/foo.atom').to_return(request_fixture('activitypub-feed.txt')) stub_request(:get, %r{https://ap\.example\.com/users/foo/\w+}).to_return(status: 404) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:hoge@example.com').to_return(status: 410) + stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(status: 410) end context 'when using skip_webfinger' do From 1ecb577a8a0399edc223aeacfc0d8ebe280e83bb Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 08:36:50 +0900 Subject: [PATCH 03/15] Fix rspec at least services --- app/services/update_status_service.rb | 6 ++++-- .../activitypub/fetch_remote_account_service_spec.rb | 5 +++++ .../services/activitypub/fetch_remote_key_service_spec.rb | 2 +- spec/services/activitypub/process_account_service_spec.rb | 8 ++++++++ spec/services/resolve_account_service_spec.rb | 4 +++- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/app/services/update_status_service.rb b/app/services/update_status_service.rb index 9a8d23cb7e..ccf7b4827f 100644 --- a/app/services/update_status_service.rb +++ b/app/services/update_status_service.rb @@ -39,10 +39,13 @@ class UpdateStatusService < BaseService queue_poll_notifications! reset_preview_card! - update_references! update_metadata! + update_references! broadcast_updates! + # Mentions are not updated (Cause unknown) + @status.reload + @status rescue NoChangesSubmittedError # For calls that result in no changes, swallow the error @@ -164,7 +167,6 @@ class UpdateStatusService < BaseService def update_metadata! ProcessHashtagsService.new.call(@status) ProcessMentionsService.new.call(@status) - ProcessReferencesWorker.perform_async(@status.id, (@options[:status_reference_ids] || []).map(&:to_i).filter(&:positive?), []) end def broadcast_updates! diff --git a/spec/services/activitypub/fetch_remote_account_service_spec.rb b/spec/services/activitypub/fetch_remote_account_service_spec.rb index ac7484d96d..0abd1daa2c 100644 --- a/spec/services/activitypub/fetch_remote_account_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_account_service_spec.rb @@ -46,6 +46,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '{}') end it 'fetches resource' do @@ -69,6 +70,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '{}') end it 'fetches resource' do @@ -96,6 +98,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://iscool.af/.well-known/nodeinfo').to_return(body: '{}') end it 'fetches resource' do @@ -127,6 +130,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '{}') end it 'fetches resource' do @@ -151,6 +155,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://iscool.af/.well-known/nodeinfo').to_return(body: '{}') end it 'fetches resource' do diff --git a/spec/services/activitypub/fetch_remote_key_service_spec.rb b/spec/services/activitypub/fetch_remote_key_service_spec.rb index f01ece4989..a27b392bf5 100644 --- a/spec/services/activitypub/fetch_remote_key_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_key_service_spec.rb @@ -52,7 +52,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do before do stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) - stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '[]') + stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '{}') end describe '#call' do diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb index c02a0800a3..a84ca28e21 100644 --- a/spec/services/activitypub/process_account_service_spec.rb +++ b/spec/services/activitypub/process_account_service_spec.rb @@ -19,6 +19,10 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do }.with_indifferent_access end + before do + stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '{}') + end + it 'parses out of attachment' do account = subject.call('alice', 'example.com', payload) expect(account.fields).to be_a Array @@ -127,6 +131,9 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do before do stub_const 'ActivityPub::ProcessAccountService::SUBDOMAINS_RATELIMIT', 5 + 8.times do |i| + stub_request(:get, "https://test#{i}.testdomain.com/.well-known/nodeinfo").to_return(body: '{}') + end end it 'creates at least some accounts' do @@ -192,6 +199,7 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do stub_request(:get, "https://foo.test/users/#{i}/featured").to_return(status: 200, body: featured_json.to_json, headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, "https://foo.test/users/#{i}/status").to_return(status: 200, body: status_json.to_json, headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, "https://foo.test/.well-known/webfinger?resource=acct:user#{i}@foo.test").to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://foo.test/.well-known/nodeinfo').to_return(body: '{}') end end diff --git a/spec/services/resolve_account_service_spec.rb b/spec/services/resolve_account_service_spec.rb index 1a121d6bfc..efdeb42e13 100644 --- a/spec/services/resolve_account_service_spec.rb +++ b/spec/services/resolve_account_service_spec.rb @@ -9,7 +9,7 @@ RSpec.describe ResolveAccountService, type: :service do stub_request(:get, 'https://example.com/.well-known/host-meta').to_return(status: 404) stub_request(:get, 'https://quitter.no/avatar/7477-300-20160211190340.png').to_return(request_fixture('avatar.txt')) stub_request(:get, 'https://ap.example.com/.well-known/webfinger?resource=acct:foo@ap.example.com').to_return(request_fixture('activitypub-webfinger.txt')) - stub_request(:get, 'https://ap.example.com/.well-known/nodeinfo').to_return('{}') + stub_request(:get, 'https://ap.example.com/.well-known/nodeinfo').to_return(body: '{}') stub_request(:get, 'https://ap.example.com/users/foo').to_return(request_fixture('activitypub-actor.txt')) stub_request(:get, 'https://ap.example.com/users/foo.atom').to_return(request_fixture('activitypub-feed.txt')) stub_request(:get, %r{https://ap\.example\.com/users/foo/\w+}).to_return(status: 404) @@ -137,8 +137,10 @@ RSpec.describe ResolveAccountService, type: :service do before do webfinger = { subject: 'acct:foo@evil.example.com', links: [{ rel: 'self', href: 'https://ap.example.com/users/foo', type: 'application/activity+json' }] } stub_request(:get, 'https://redirected.example.com/.well-known/webfinger?resource=acct:Foo@redirected.example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://redirected.example.com/.well-known/nodeinfo').to_return(body: '{}') webfinger2 = { subject: 'acct:foo@ap.example.com', links: [{ rel: 'self', href: 'https://ap.example.com/users/foo', type: 'application/activity+json' }] } stub_request(:get, 'https://evil.example.com/.well-known/webfinger?resource=acct:foo@evil.example.com').to_return(body: Oj.dump(webfinger2), headers: { 'Content-Type': 'application/jrd+json' }) + stub_request(:get, 'https://evil.example.com/.well-known/nodeinfo').to_return(body: '{}') end it 'does not return a new remote account' do From 31911db91ca9fc4f04eb78177fa496de96b8ced7 Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 08:37:40 +0900 Subject: [PATCH 04/15] Revival rspec test budge on README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 51ea436c6a..1ec0792cc7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # kmyblue +[![Ruby Testing](https://github.com/mastodon/mastodon/actions/workflows/test-ruby.yml/badge.svg)](https://github.com/mastodon/mastodon/actions/workflows/test-ruby.yml) + kmyblue は[Mastodon](https://github.com/mastodon/mastodon)のフォークです。創作作家のための Mastodon を目指して開発しました。 kmyblue はフォーク名であり、同時に[サーバー名](https://kmy.blue)でもあります。以下は特に記述がない限り、フォークとしての kmyblue をさします。 From 2964d5917183ce2b7a5b0eb51211d6f06f701988 Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 09:05:32 +0900 Subject: [PATCH 05/15] Fix filter test (whole_word default value) --- spec/requests/api/v2/filters/filters_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/requests/api/v2/filters/filters_spec.rb b/spec/requests/api/v2/filters/filters_spec.rb index 2ee24d8095..5a0c17ca5d 100644 --- a/spec/requests/api/v2/filters/filters_spec.rb +++ b/spec/requests/api/v2/filters/filters_spec.rb @@ -63,7 +63,7 @@ RSpec.describe 'Filters' do expect(json[:title]).to eq 'magic' expect(json[:filter_action]).to eq 'hide' expect(json[:context]).to eq ['home'] - expect(json[:keywords].map { |keyword| keyword.slice(:keyword, :whole_word) }).to eq [{ keyword: 'magic', whole_word: true }] + expect(json[:keywords].map { |keyword| keyword.slice(:keyword, :whole_word) }).to eq [{ keyword: 'magic', whole_word: false }] end it 'creates a filter', :aggregate_failures do From 383533fd25eaa21ddd2edee88e379e0a3d5981be Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 09:07:31 +0900 Subject: [PATCH 06/15] Fix filter test with api call --- spec/requests/api/v2/filters/filters_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/requests/api/v2/filters/filters_spec.rb b/spec/requests/api/v2/filters/filters_spec.rb index 5a0c17ca5d..bd3a27a92f 100644 --- a/spec/requests/api/v2/filters/filters_spec.rb +++ b/spec/requests/api/v2/filters/filters_spec.rb @@ -47,7 +47,7 @@ RSpec.describe 'Filters' do it_behaves_like 'unauthorized for invalid token' context 'with valid params' do - let(:params) { { title: 'magic', context: %w(home), filter_action: 'hide', keywords_attributes: [keyword: 'magic'] } } + let(:params) { { title: 'magic', context: %w(home), filter_action: 'hide', keywords_attributes: [keyword: 'magic', whole_word: true] } } it 'returns http success' do subject @@ -63,7 +63,7 @@ RSpec.describe 'Filters' do expect(json[:title]).to eq 'magic' expect(json[:filter_action]).to eq 'hide' expect(json[:context]).to eq ['home'] - expect(json[:keywords].map { |keyword| keyword.slice(:keyword, :whole_word) }).to eq [{ keyword: 'magic', whole_word: false }] + expect(json[:keywords].map { |keyword| keyword.slice(:keyword, :whole_word) }).to eq [{ keyword: 'magic', whole_word: true }] end it 'creates a filter', :aggregate_failures do From 875cecf4d8f0ddf34f896ef01d50e42f67f0c0bf Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 10:40:45 +0900 Subject: [PATCH 07/15] Fix downcase test --- db/migrate/20181207011115_downcase_custom_emoji_domains.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/db/migrate/20181207011115_downcase_custom_emoji_domains.rb b/db/migrate/20181207011115_downcase_custom_emoji_domains.rb index 3f3da937a5..0497f7be10 100644 --- a/db/migrate/20181207011115_downcase_custom_emoji_domains.rb +++ b/db/migrate/20181207011115_downcase_custom_emoji_domains.rb @@ -3,6 +3,10 @@ class DowncaseCustomEmojiDomains < ActiveRecord::Migration[5.2] disable_ddl_transaction! + class EmojiReaction < ApplicationRecord + # Dummy class, to make migration possible across version changes + end + def up duplicates = CustomEmoji.connection.select_all('SELECT string_agg(id::text, \',\') AS ids FROM custom_emojis GROUP BY shortcode, lower(domain) HAVING count(*) > 1').to_ary From 9185091ae96ce7e741ebc2f43a433077fafd1716 Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 10:48:50 +0900 Subject: [PATCH 08/15] Fix emoji_reactions table not found error when managing custom_emojis table --- .../20181207011115_downcase_custom_emoji_domains.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/db/migrate/20181207011115_downcase_custom_emoji_domains.rb b/db/migrate/20181207011115_downcase_custom_emoji_domains.rb index 0497f7be10..b5fc70882e 100644 --- a/db/migrate/20181207011115_downcase_custom_emoji_domains.rb +++ b/db/migrate/20181207011115_downcase_custom_emoji_domains.rb @@ -3,11 +3,9 @@ class DowncaseCustomEmojiDomains < ActiveRecord::Migration[5.2] disable_ddl_transaction! - class EmojiReaction < ApplicationRecord - # Dummy class, to make migration possible across version changes - end - def up + CustomEmoji.connection.execute('CREATE TABLE IF NOT EXISTS emoji_reactions (id integer, custom_emoji_id integer, created_at datetime NOT NULL, updated_at datetime NOT NULL)') + duplicates = CustomEmoji.connection.select_all('SELECT string_agg(id::text, \',\') AS ids FROM custom_emojis GROUP BY shortcode, lower(domain) HAVING count(*) > 1').to_ary duplicates.each do |row| @@ -15,6 +13,8 @@ class DowncaseCustomEmojiDomains < ActiveRecord::Migration[5.2] end CustomEmoji.in_batches.update_all('domain = lower(domain)') + + CustomEmoji.connection.execute('DROP TABLE IF EXISTS emoji_reactions') end def down; end From b524a3fea4015b9bd47567a18257bb611576d2ec Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 10:49:46 +0900 Subject: [PATCH 09/15] Fix rspec budge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ec0792cc7..714d160e41 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # kmyblue -[![Ruby Testing](https://github.com/mastodon/mastodon/actions/workflows/test-ruby.yml/badge.svg)](https://github.com/mastodon/mastodon/actions/workflows/test-ruby.yml) +[![Ruby Testing](https://github.com/kmycode/mastodon/actions/workflows/test-ruby.yml/badge.svg)](https://github.com/kmycode/mastodon/actions/workflows/test-ruby.yml) kmyblue は[Mastodon](https://github.com/mastodon/mastodon)のフォークです。創作作家のための Mastodon を目指して開発しました。 From 669771db9c74366303ffd1c54e793764bb77f08f Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 10:52:49 +0900 Subject: [PATCH 10/15] Fix emoji_reactions column type --- db/migrate/20181207011115_downcase_custom_emoji_domains.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20181207011115_downcase_custom_emoji_domains.rb b/db/migrate/20181207011115_downcase_custom_emoji_domains.rb index b5fc70882e..76b5d54428 100644 --- a/db/migrate/20181207011115_downcase_custom_emoji_domains.rb +++ b/db/migrate/20181207011115_downcase_custom_emoji_domains.rb @@ -4,7 +4,7 @@ class DowncaseCustomEmojiDomains < ActiveRecord::Migration[5.2] disable_ddl_transaction! def up - CustomEmoji.connection.execute('CREATE TABLE IF NOT EXISTS emoji_reactions (id integer, custom_emoji_id integer, created_at datetime NOT NULL, updated_at datetime NOT NULL)') + CustomEmoji.connection.execute('CREATE TABLE IF NOT EXISTS emoji_reactions (id integer, custom_emoji_id integer, created_at timestamp NOT NULL, updated_at timestamp NOT NULL)') duplicates = CustomEmoji.connection.select_all('SELECT string_agg(id::text, \',\') AS ids FROM custom_emojis GROUP BY shortcode, lower(domain) HAVING count(*) > 1').to_ary From c090b20f3996abaf77c6b6fa24c58e12b5213df4 Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 10:57:49 +0900 Subject: [PATCH 11/15] Fix ruby lint --- app/models/trends/statuses.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/trends/statuses.rb b/app/models/trends/statuses.rb index d4b7031a81..8a31ab727b 100644 --- a/app/models/trends/statuses.rb +++ b/app/models/trends/statuses.rb @@ -106,7 +106,9 @@ class Trends::Statuses < Trends::Base private def eligible?(status) - (status.searchability.nil? || status.public_searchability?) && (status.public_visibility? || status.public_unlisted_visibility?) && status.account.discoverable? && !status.account.silenced? && status.spoiler_text.blank? && (!status.sensitive? || status.media_attachments.none?) && !status.reply? && valid_locale?(status.language) + (status.searchability.nil? || status.public_searchability?) && (status.public_visibility? || status.public_unlisted_visibility?) && + status.account.discoverable? && !status.account.silenced? && status.spoiler_text.blank? && (!status.sensitive? || status.media_attachments.none?) && + !status.reply? && valid_locale?(status.language) end def calculate_scores(statuses, at_time) From daa0f170c6e115b300f87a59efebc7e5530d0fee Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 12:34:27 +0900 Subject: [PATCH 12/15] Add public_unlisted/login visibilities to public_feed_spec --- app/models/public_feed.rb | 17 ++++----- spec/models/public_feed_spec.rb | 61 +++++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/app/models/public_feed.rb b/app/models/public_feed.rb index c87b9361b6..f73f639006 100644 --- a/app/models/public_feed.rb +++ b/app/models/public_feed.rb @@ -19,13 +19,12 @@ class PublicFeed # @param [Integer] min_id # @return [Array] def get(limit, max_id = nil, since_id = nil, min_id = nil) - scope = public_scope + scope = local_only? ? public_scope : global_timeline_only_scope scope.merge!(without_replies_scope) unless with_replies? scope.merge!(without_reblogs_scope) unless with_reblogs? scope.merge!(local_only_scope) if local_only? scope.merge!(remote_only_scope) if remote_only? || hide_local_users? - scope.merge!(global_timeline_only_scope) if global_timeline? scope.merge!(account_filters_scope) if account? scope.merge!(media_only_scope) if media_only? scope.merge!(language_scope) if account&.chosen_languages.present? @@ -58,10 +57,6 @@ class PublicFeed @account.nil? && Setting.hide_local_users_for_anonymous end - def global_timeline? - !options[:remote] && !options[:local] - end - def account? account.present? end @@ -74,6 +69,10 @@ class PublicFeed Status.with_public_visibility.joins(:account).merge(Account.without_suspended.without_silenced) end + def global_timeline_only_scope + Status.with_global_timeline_visibility.joins(:account).merge(Account.without_suspended.without_silenced) + end + def public_search_scope Status.with_public_search_visibility.joins(:account).merge(Account.without_suspended.without_silenced) end @@ -86,10 +85,6 @@ class PublicFeed Status.remote end - def global_timeline_only_scope - Status.with_global_timeline_visibility.joins(:account).merge(Account.without_suspended.without_silenced) - end - def without_replies_scope Status.without_replies end @@ -107,7 +102,7 @@ class PublicFeed end def anonymous_scope - Status.where(visibility: [:public, :public_unlisted]) + local_only? ? Status.where(visibility: [:public, :public_unlisted]) : Status.where(visibility: :public) end def account_filters_scope diff --git a/spec/models/public_feed_spec.rb b/spec/models/public_feed_spec.rb index 53e01cafd3..6107bc3ed0 100644 --- a/spec/models/public_feed_spec.rb +++ b/spec/models/public_feed_spec.rb @@ -6,14 +6,36 @@ RSpec.describe PublicFeed do let(:account) { Fabricate(:account) } describe '#get' do - subject { described_class.new(nil).get(20).map(&:id) } + subject { described_class.new(viewer).get(20).map(&:id) } - it 'only includes statuses with public visibility' do - public_status = Fabricate(:status, visibility: :public) - private_status = Fabricate(:status, visibility: :private) + let(:viewer) { nil } - expect(subject).to include(public_status.id) - expect(subject).to_not include(private_status.id) + context 'with only includes statuses with public visibility' do + let!(:public_status) { Fabricate(:status, visibility: :public) } + let!(:login_status) { Fabricate(:status, visibility: :login) } + let!(:unlisted_status) { Fabricate(:status, visibility: :unlisted) } + let!(:private_status) { Fabricate(:status, visibility: :private) } + let!(:direct_status) { Fabricate(:status, visibility: :direct) } + + it 'without user' do + expect(subject).to include(public_status.id) + expect(subject).to_not include(login_status.id) + expect(subject).to_not include(unlisted_status.id) + expect(subject).to_not include(private_status.id) + expect(subject).to_not include(direct_status.id) + end + + context 'with user' do + let(:viewer) { account } + + it 'on global timeline' do + expect(subject).to include(public_status.id) + expect(subject).to include(login_status.id) + expect(subject).to_not include(unlisted_status.id) + expect(subject).to_not include(private_status.id) + expect(subject).to_not include(direct_status.id) + end + end end it 'does not include replies' do @@ -50,6 +72,7 @@ RSpec.describe PublicFeed do let!(:remote_account) { Fabricate(:account, domain: 'test.com') } let!(:local_status) { Fabricate(:status, account: local_account) } let!(:remote_status) { Fabricate(:status, account: remote_account) } + let!(:public_unlisted_status) { Fabricate(:status, account: local_account, visibility: :public_unlisted) } context 'without a viewer' do let(:viewer) { nil } @@ -61,6 +84,10 @@ RSpec.describe PublicFeed do it 'includes local statuses' do expect(subject).to include(local_status.id) end + + it 'excludes public_unlisted statuses' do + expect(subject).to_not include(public_unlisted_status.id) + end end context 'with a viewer' do @@ -73,6 +100,10 @@ RSpec.describe PublicFeed do it 'includes local statuses' do expect(subject).to include(local_status.id) end + + it 'excludes public_unlisted statuses' do + expect(subject).to_not include(public_unlisted_status.id) + end end end @@ -83,6 +114,7 @@ RSpec.describe PublicFeed do let!(:remote_account) { Fabricate(:account, domain: 'test.com') } let!(:local_status) { Fabricate(:status, account: local_account) } let!(:remote_status) { Fabricate(:status, account: remote_account) } + let!(:public_unlisted_status) { Fabricate(:status, account: local_account, visibility: :public_unlisted) } context 'without a viewer' do let(:viewer) { nil } @@ -91,6 +123,10 @@ RSpec.describe PublicFeed do expect(subject).to include(local_status.id) expect(subject).to_not include(remote_status.id) end + + it 'includes public_unlisted statuses' do + expect(subject).to include(public_unlisted_status.id) + end end context 'with a viewer' do @@ -106,6 +142,10 @@ RSpec.describe PublicFeed do expect(subject).to include(local_status.id) expect(subject).to_not include(remote_status.id) end + + it 'includes public_unlisted statuses' do + expect(subject).to include(public_unlisted_status.id) + end end end @@ -116,6 +156,7 @@ RSpec.describe PublicFeed do let!(:remote_account) { Fabricate(:account, domain: 'test.com') } let!(:local_status) { Fabricate(:status, account: local_account) } let!(:remote_status) { Fabricate(:status, account: remote_account) } + let!(:public_unlisted_status) { Fabricate(:status, account: local_account, visibility: :public_unlisted) } context 'without a viewer' do let(:viewer) { nil } @@ -124,6 +165,10 @@ RSpec.describe PublicFeed do expect(subject).to_not include(local_status.id) expect(subject).to include(remote_status.id) end + + it 'excludes public_unlisted statuses' do + expect(subject).to_not include(public_unlisted_status.id) + end end context 'with a viewer' do @@ -133,6 +178,10 @@ RSpec.describe PublicFeed do expect(subject).to_not include(local_status.id) expect(subject).to include(remote_status.id) end + + it 'excludes public_unlisted statuses' do + expect(subject).to_not include(public_unlisted_status.id) + end end end From 8915cb4c2be7b5338a96bee9fce18db462e8ac44 Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 14:03:48 +0900 Subject: [PATCH 13/15] Add searchability post/receive test --- spec/fabricators/instance_info_fabricator.rb | 7 + spec/lib/activitypub/activity/create_spec.rb | 219 ++++++++++++++++++- spec/models/instance_info_spec.rb | 3 + spec/services/post_status_service_spec.rb | 28 +++ 4 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 spec/fabricators/instance_info_fabricator.rb create mode 100644 spec/models/instance_info_spec.rb diff --git a/spec/fabricators/instance_info_fabricator.rb b/spec/fabricators/instance_info_fabricator.rb new file mode 100644 index 0000000000..a0bdb2b713 --- /dev/null +++ b/spec/fabricators/instance_info_fabricator.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +Fabricator(:instance_info) do + domain 'info.example.com' + software 'mastodon' + version '4.1.0' +end diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index f6c24754c0..43c7c13e96 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -3,7 +3,8 @@ require 'rails_helper' RSpec.describe ActivityPub::Activity::Create do - let(:sender) { Fabricate(:account, followers_url: 'http://example.com/followers', domain: 'example.com', uri: 'https://example.com/actor') } + let(:sender_bio) { '' } + let(:sender) { Fabricate(:account, followers_url: 'http://example.com/followers', domain: 'example.com', uri: 'https://example.com/actor', note: sender_bio) } let(:json) do { @@ -27,7 +28,10 @@ RSpec.describe ActivityPub::Activity::Create do context 'when fetching' do subject { described_class.new(json, sender) } + let(:sender_software) { 'mastodon' } + before do + Fabricate(:instance_info, domain: 'example.com', software: sender_software) subject.perform end @@ -318,6 +322,219 @@ RSpec.describe ActivityPub::Activity::Create do end end + context 'when searchability' do + let(:searchable_by) { 'https://www.w3.org/ns/activitystreams#Public' } + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + to: 'https://www.w3.org/ns/activitystreams#Public', + searchableBy: searchable_by, + } + end + + context 'with explicit public address' do + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'public' + end + end + + context 'with public with as:Public' do + let(:searchable_by) { 'as:Public' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'public' + end + end + + context 'with public with Public' do + let(:searchable_by) { 'Public' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'public' + end + end + + context 'with private' do + let(:searchable_by) { 'http://example.com/followers' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'private' + end + end + + context 'with direct' do + let(:searchable_by) { '' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'direct' + end + end + + context 'with direct when not specify' do + let(:searchable_by) { nil } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to be_nil + end + end + + context 'with limited' do + let(:searchable_by) { 'as:Limited' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'limited' + end + end + + context 'with bio' do + let(:searchable_by) { nil } + + context 'with public' do + let(:sender_bio) { '#searchable_by_all_users' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'public' + end + end + + context 'with private' do + let(:sender_bio) { '#searchable_by_followers_only' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'private' + end + end + + context 'with direct' do + let(:sender_bio) { '#searchable_by_reacted_users_only' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'direct' + end + end + + context 'with limited' do + let(:sender_bio) { '#searchable_by_nobody' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'limited' + end + end + + context 'without hashtags' do + let(:sender_bio) { '' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to be_nil + end + end + end + end + + context 'when searchability from misskey server' do + let(:sender_software) { 'misskey' } + let(:to) { 'https://www.w3.org/ns/activitystreams#Public' } + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + to: to, + } + end + + context 'without specify searchability from misskey' do + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'public' + end + end + + context 'without specify searchability from misskey which visibility is private' do + let(:to) { 'http://example.com/followers' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'limited' + end + end + end + + context 'with multible searchabilities' do + let(:bio) { '#searchable_by_nobody' } + let(:searchable_by) { 'https://www.w3.org/ns/activitystreams#Public' } + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + to: 'https://www.w3.org/ns/activitystreams#Public', + searchableBy: searchable_by, + } + end + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'public' + end + + context 'with misskey' do + let(:sender_software) { 'misskey' } + let(:searchable_by) { 'as:Limited' } + + it 'create status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.searchability).to eq 'limited' + end + end + end + context 'with a reply' do let(:original_status) { Fabricate(:status) } diff --git a/spec/models/instance_info_spec.rb b/spec/models/instance_info_spec.rb new file mode 100644 index 0000000000..ccfa9ee8d8 --- /dev/null +++ b/spec/models/instance_info_spec.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require 'rails_helper' diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb index 7d7679c889..8626ab919e 100644 --- a/spec/services/post_status_service_spec.rb +++ b/spec/services/post_status_service_spec.rb @@ -113,6 +113,34 @@ RSpec.describe PostStatusService, type: :service do expect(status.visibility).to eq 'unlisted' end + it 'creates a status with the given searchability' do + status = create_status_with_options(searchability: :public, visibility: :public) + + expect(status).to be_persisted + expect(status.searchability).to eq 'public' + end + + it 'creates a status with limited searchability for silenced users' do + status = subject.call(Fabricate(:account, silenced: true), text: 'test', searchability: :public, visibility: :public) + + expect(status).to be_persisted + expect(status.searchability).to eq 'private' + end + + it 'creates a status with the given searchability=public / visibility=unlisted' do + status = create_status_with_options(searchability: :public, visibility: :unlisted) + + expect(status).to be_persisted + expect(status.searchability).to eq 'public' + end + + it 'creates a status with the given searchability=public / visibility=private' do + status = create_status_with_options(searchability: :public, visibility: :private) + + expect(status).to be_persisted + expect(status.searchability).to eq 'private' + end + it 'creates a status for the given application' do application = Fabricate(:application) From 114bd48c4b17b120cce7113ee7c8fc6b521a709b Mon Sep 17 00:00:00 2001 From: KMY Date: Tue, 8 Aug 2023 18:28:58 +0900 Subject: [PATCH 14/15] Add searchability account/status.compute_searchability test --- app/lib/activitypub/activity/create.rb | 2 +- .../activitypub/process_account_service.rb | 8 +- spec/lib/activitypub/activity/create_spec.rb | 2 +- spec/models/status_spec.rb | 66 +++++++++++ .../process_account_service_spec.rb | 107 ++++++++++++++++++ 5 files changed, 180 insertions(+), 5 deletions(-) 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 { From 7c9ea215a602dd6d953a1fc54f7cd0a7b44ddc20 Mon Sep 17 00:00:00 2001 From: KMY Date: Wed, 9 Aug 2023 08:46:42 +0900 Subject: [PATCH 15/15] Update account_status_filter_spec for public_unlisted/login visibilities --- spec/models/account_statuses_filter_spec.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/spec/models/account_statuses_filter_spec.rb b/spec/models/account_statuses_filter_spec.rb index fa7664d921..8f388dc67f 100644 --- a/spec/models/account_statuses_filter_spec.rb +++ b/spec/models/account_statuses_filter_spec.rb @@ -42,8 +42,11 @@ RSpec.describe AccountStatusesFilter do before do status!(:public) + status!(:public_unlisted) status!(:unlisted) + status!(:login) status!(:private) + status!(:direct) status_with_parent!(:public) status_with_reblog!(:public) status_with_tag!(:public, tag) @@ -90,7 +93,7 @@ RSpec.describe AccountStatusesFilter do let(:direct_status) { nil } it 'returns only public statuses' do - expect(subject.results.pluck(:visibility).uniq).to match_array %w(unlisted public) + expect(subject.results.pluck(:visibility).uniq).to match_array %w(unlisted public_unlisted public) end it 'returns public replies' do @@ -120,7 +123,7 @@ RSpec.describe AccountStatusesFilter do let(:current_account) { account } it 'returns everything' do - expect(subject.results.pluck(:visibility).uniq).to match_array %w(direct private unlisted public) + expect(subject.results.pluck(:visibility).uniq).to match_array %w(direct private login unlisted public_unlisted public) end it 'returns replies' do @@ -142,7 +145,7 @@ RSpec.describe AccountStatusesFilter do end it 'returns private statuses' do - expect(subject.results.pluck(:visibility).uniq).to match_array %w(private unlisted public) + expect(subject.results.pluck(:visibility).uniq).to match_array %w(private login unlisted public_unlisted public) end it 'returns replies' do @@ -168,7 +171,7 @@ RSpec.describe AccountStatusesFilter do let(:current_account) { Fabricate(:account) } it 'returns only public statuses' do - expect(subject.results.pluck(:visibility).uniq).to match_array %w(unlisted public) + expect(subject.results.pluck(:visibility).uniq).to match_array %w(login unlisted public_unlisted public) end it 'returns public replies' do