diff --git a/app/lib/activitypub/activity/follow.rb b/app/lib/activitypub/activity/follow.rb index 1e805c0d1758fa4349ff89de051b2cc3f66a0afe..3eb88339aebaa6cf4abbd0c4e857a00a06ebe52a 100644 --- a/app/lib/activitypub/activity/follow.rb +++ b/app/lib/activitypub/activity/follow.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class ActivityPub::Activity::Follow < ActivityPub::Activity + include Payloadable + def perform target_account = account_from_uri(object_uri) @@ -28,7 +30,7 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity end def reject_follow_request!(target_account) - json = ActiveModelSerializers::SerializableResource.new(FollowRequest.new(account: @account, target_account: target_account, uri: @json['id']), serializer: ActivityPub::RejectFollowSerializer, adapter: ActivityPub::Adapter).to_json + json = Oj.dump(serialize_payload(FollowRequest.new(account: @account, target_account: target_account, uri: @json['id']), ActivityPub::RejectFollowSerializer)) ActivityPub::DeliveryWorker.perform_async(json, target_account.id, @account.inbox_url) end end diff --git a/app/models/account.rb b/app/models/account.rb index fe48fce1050dc18d31b85c682ae7320c7c8fc1cf..c977f887c74500c68d0615da50c6e48ef20b81dd 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -204,6 +204,10 @@ class Account < ApplicationRecord end end + def sign? + true + end + def keypair @keypair ||= OpenSSL::PKey::RSA.new(private_key || public_key) end diff --git a/app/models/form/account_batch.rb b/app/models/form/account_batch.rb index 5bc44e809bd3fc32c6dcaf394e8c0adb1e878d47..f1b7a45664f25173a1000a7fdabee37876c77e9f 100644 --- a/app/models/form/account_batch.rb +++ b/app/models/form/account_batch.rb @@ -3,6 +3,7 @@ class Form::AccountBatch include ActiveModel::Model include Authorization + include Payloadable attr_accessor :account_ids, :action, :current_account @@ -54,13 +55,7 @@ class Form::AccountBatch return unless follow.account.activitypub? - json = ActiveModelSerializers::SerializableResource.new( - follow, - serializer: ActivityPub::RejectFollowSerializer, - adapter: ActivityPub::Adapter - ).to_json - - ActivityPub::DeliveryWorker.perform_async(json, current_account.id, follow.account.inbox_url) + ActivityPub::DeliveryWorker.perform_async(Oj.dump(serialize_payload(follow, ActivityPub::RejectFollowSerializer)), current_account.id, follow.account.inbox_url) end def approve! diff --git a/app/models/status.rb b/app/models/status.rb index 2f6101b9082c33c4acf36aa027afb859702232f8..a7f32f41c787425fba01e39eae55dfcfe94db895 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -204,6 +204,8 @@ class Status < ApplicationRecord public_visibility? || unlisted_visibility? end + alias sign? distributable? + def with_media? media_attachments.any? end diff --git a/app/services/after_block_domain_from_account_service.rb b/app/services/after_block_domain_from_account_service.rb index 180f134032375f8af3d27c7a07d03f1a2471e91b..a87c2e792c928f6039917cb0f4557e1d918a2783 100644 --- a/app/services/after_block_domain_from_account_service.rb +++ b/app/services/after_block_domain_from_account_service.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class AfterBlockDomainFromAccountService < BaseService + include Payloadable + # This service does not create an AccountDomainBlock record, # it's meant to be called after such a record has been created # synchronously, to "clean up" @@ -31,12 +33,6 @@ class AfterBlockDomainFromAccountService < BaseService return unless follow.account.activitypub? - json = ActiveModelSerializers::SerializableResource.new( - follow, - serializer: ActivityPub::RejectFollowSerializer, - adapter: ActivityPub::Adapter - ).to_json - - ActivityPub::DeliveryWorker.perform_async(json, @account.id, follow.account.inbox_url) + ActivityPub::DeliveryWorker.perform_async(Oj.dump(serialize_payload(follow, ActivityPub::RejectFollowSerializer)), @account.id, follow.account.inbox_url) end end diff --git a/app/services/authorize_follow_service.rb b/app/services/authorize_follow_service.rb index f2e3ebe7d00b4770fea3dd2e478dfead17ee0027..29b8700c7c7d06781d00d8d11b695f8da7b779b0 100644 --- a/app/services/authorize_follow_service.rb +++ b/app/services/authorize_follow_service.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class AuthorizeFollowService < BaseService + include Payloadable + def call(source_account, target_account, **options) if options[:skip_follow_request] follow_request = FollowRequest.new(account: source_account, target_account: target_account, uri: options[:follow_request_uri]) @@ -24,11 +26,7 @@ class AuthorizeFollowService < BaseService end def build_json(follow_request) - ActiveModelSerializers::SerializableResource.new( - follow_request, - serializer: ActivityPub::AcceptFollowSerializer, - adapter: ActivityPub::Adapter - ).to_json + Oj.dump(serialize_payload(follow_request, ActivityPub::AcceptFollowSerializer)) end def build_xml(follow_request) diff --git a/app/services/block_service.rb b/app/services/block_service.rb index 10ed470e0a3e433acb5976ce378728d816292d12..9050a48585cea9cb18984661a91249cd5a35ab44 100644 --- a/app/services/block_service.rb +++ b/app/services/block_service.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class BlockService < BaseService + include Payloadable + def call(account, target_account) return if account.id == target_account.id @@ -26,11 +28,7 @@ class BlockService < BaseService end def build_json(block) - ActiveModelSerializers::SerializableResource.new( - block, - serializer: ActivityPub::BlockSerializer, - adapter: ActivityPub::Adapter - ).to_json + Oj.dump(serialize_payload(block, ActivityPub::BlockSerializer)) end def build_xml(block) diff --git a/app/services/concerns/payloadable.rb b/app/services/concerns/payloadable.rb new file mode 100644 index 0000000000000000000000000000000000000000..13d9c3548353e538be69e52a9abaf69b3da7283a --- /dev/null +++ b/app/services/concerns/payloadable.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Payloadable + def serialize_payload(record, serializer, options = {}) + signer = options.delete(:signer) + sign_with = options.delete(:sign_with) + payload = ActiveModelSerializers::SerializableResource.new(record, options.merge(serializer: serializer, adapter: ActivityPub::Adapter)).as_json + + if (record.respond_to?(:sign?) && record.sign?) && signer && signing_enabled? + ActivityPub::LinkedDataSignature.new(payload).sign!(signer, sign_with: sign_with) + else + payload + end + end + + def signing_enabled? + true + end +end diff --git a/app/services/favourite_service.rb b/app/services/favourite_service.rb index b565bcc3203f30c9f2544c0fccbab496d7fddf7c..128a24ad61e59f484ebda27e432d4f7ee32d96e3 100644 --- a/app/services/favourite_service.rb +++ b/app/services/favourite_service.rb @@ -2,6 +2,7 @@ class FavouriteService < BaseService include Authorization + include Payloadable # Favourite a status and notify remote user # @param [Account] account @@ -43,11 +44,7 @@ class FavouriteService < BaseService end def build_json(favourite) - Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new( - favourite, - serializer: ActivityPub::LikeSerializer, - adapter: ActivityPub::Adapter - ).as_json).sign!(favourite.account)) + Oj.dump(serialize_payload(favourite, ActivityPub::LikeSerializer)) end def build_xml(favourite) diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb index 92d8c864a7de1e8c617e2eafdf159a1560d8735a..0305e2d621afc6f0ee1765480d312c5d37ba9ca4 100644 --- a/app/services/follow_service.rb +++ b/app/services/follow_service.rb @@ -2,6 +2,7 @@ class FollowService < BaseService include Redisable + include Payloadable # Follow a remote user, notify remote user about the follow # @param [Account] source_account From which to follow @@ -78,10 +79,6 @@ class FollowService < BaseService end def build_json(follow_request) - ActiveModelSerializers::SerializableResource.new( - follow_request, - serializer: ActivityPub::FollowSerializer, - adapter: ActivityPub::Adapter - ).to_json + Oj.dump(serialize_payload(follow_request, ActivityPub::FollowSerializer)) end end diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index d27a7dab4c194deef4e2ac79496a848496d52a22..bc607dff3953c210f67b42a33c518753afa52d3b 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -2,6 +2,7 @@ class ProcessMentionsService < BaseService include StreamEntryRenderer + include Payloadable # Scan status for mentions and fetch remote mentioned users, create # local mention pointers, send Salmon notifications to mentioned @@ -61,12 +62,7 @@ class ProcessMentionsService < BaseService def activitypub_json return @activitypub_json if defined?(@activitypub_json) - payload = ActiveModelSerializers::SerializableResource.new( - @status, - serializer: ActivityPub::ActivitySerializer, - adapter: ActivityPub::Adapter - ).as_json - @activitypub_json = Oj.dump(@status.distributable? ? ActivityPub::LinkedDataSignature.new(payload).sign!(@status.account) : payload) + @activitypub_json = Oj.dump(serialize_payload(@status, ActivityPub::ActivitySerializer, signer: @status.account)) end def resolve_account_service diff --git a/app/services/reblog_service.rb b/app/services/reblog_service.rb index 1710640c81db991e3df4f109d4e99f0b9541f24e..9cf4bc128b8f1958f5b5b548384726835918afb4 100644 --- a/app/services/reblog_service.rb +++ b/app/services/reblog_service.rb @@ -3,6 +3,7 @@ class ReblogService < BaseService include Authorization include StreamEntryRenderer + include Payloadable # Reblog a status and notify its remote author # @param [Account] account Account to reblog from @@ -53,10 +54,6 @@ class ReblogService < BaseService end def build_json(reblog) - Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new( - reblog, - serializer: ActivityPub::ActivitySerializer, - adapter: ActivityPub::Adapter - ).as_json).sign!(reblog.account)) + Oj.dump(serialize_payload(reblog, ActivityPub::ActivitySerializer, signer: reblog.account)) end end diff --git a/app/services/reject_follow_service.rb b/app/services/reject_follow_service.rb index a91266aa4b65b6447e1558cdc7373fda46a50aed..f87d0ba914f6382fc5904f885b21da6384c26543 100644 --- a/app/services/reject_follow_service.rb +++ b/app/services/reject_follow_service.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class RejectFollowService < BaseService + include Payloadable + def call(source_account, target_account) follow_request = FollowRequest.find_by!(account: source_account, target_account: target_account) follow_request.reject! @@ -19,11 +21,7 @@ class RejectFollowService < BaseService end def build_json(follow_request) - ActiveModelSerializers::SerializableResource.new( - follow_request, - serializer: ActivityPub::RejectFollowSerializer, - adapter: ActivityPub::Adapter - ).to_json + Oj.dump(serialize_payload(follow_request, ActivityPub::RejectFollowSerializer)) end def build_xml(follow_request) diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 747f209f3320b8f9b54304fddc30725bc0f5f098..81adc5aae54dcb0fe8c4c7f1849cd0e493db3dc2 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -3,6 +3,7 @@ class RemoveStatusService < BaseService include StreamEntryRenderer include Redisable + include Payloadable def call(status, **options) @payload = Oj.dump(event: :delete, payload: status.id.to_s) @@ -115,15 +116,7 @@ class RemoveStatusService < BaseService end def signed_activity_json - @signed_activity_json ||= Oj.dump(ActivityPub::LinkedDataSignature.new(activity_json).sign!(@account)) - end - - def activity_json - @activity_json ||= ActiveModelSerializers::SerializableResource.new( - @status, - serializer: @status.reblog? ? ActivityPub::UndoAnnounceSerializer : ActivityPub::DeleteSerializer, - adapter: ActivityPub::Adapter - ).as_json + @signed_activity_json ||= Oj.dump(serialize_payload(@status, @status.reblog? ? ActivityPub::UndoAnnounceSerializer : ActivityPub::DeleteSerializer, signer: @account)) end def remove_reblogs diff --git a/app/services/report_service.rb b/app/services/report_service.rb index 73bd6694f2e23caafc897d326fc804c6dfd18c75..1e955c1e704b70574511426e1e7f25097889d257 100644 --- a/app/services/report_service.rb +++ b/app/services/report_service.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class ReportService < BaseService + include Payloadable + def call(source_account, target_account, options = {}) @source_account = source_account @target_account = target_account @@ -44,12 +46,7 @@ class ReportService < BaseService end def payload - Oj.dump(ActiveModelSerializers::SerializableResource.new( - @report, - serializer: ActivityPub::FlagSerializer, - adapter: ActivityPub::Adapter, - account: some_local_account - ).as_json) + Oj.dump(serialize_payload(@report, ActivityPub::FlagSerializer, account: some_local_account)) end def some_local_account diff --git a/app/services/suspend_account_service.rb b/app/services/suspend_account_service.rb index 412873f841839b1aa77939a5362a97f786b0fe1b..a5ce3dbd9b303d446fab39b6169cfcf4219774c5 100644 --- a/app/services/suspend_account_service.rb +++ b/app/services/suspend_account_service.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class SuspendAccountService < BaseService + include Payloadable + ASSOCIATIONS_ON_SUSPEND = %w( account_pins active_relationships @@ -118,23 +120,11 @@ class SuspendAccountService < BaseService end def delete_actor_json - return @delete_actor_json if defined?(@delete_actor_json) - - payload = ActiveModelSerializers::SerializableResource.new( - @account, - serializer: ActivityPub::DeleteActorSerializer, - adapter: ActivityPub::Adapter - ).as_json - - @delete_actor_json = Oj.dump(ActivityPub::LinkedDataSignature.new(payload).sign!(@account)) + @delete_actor_json ||= Oj.dump(serialize_payload(@account, ActivityPub::DeleteActorSerializer, signer: @account)) end def build_reject_json(follow) - ActiveModelSerializers::SerializableResource.new( - follow, - serializer: ActivityPub::RejectFollowSerializer, - adapter: ActivityPub::Adapter - ).to_json + Oj.dump(serialize_payload(follow, ActivityPub::RejectFollowSerializer)) end def delivery_inboxes diff --git a/app/services/unblock_service.rb b/app/services/unblock_service.rb index 72fc5ab150d68702d953fd4efa495945b9bdacaa..95a858e9f59a8174502a40fe705ef9125ecdf1a3 100644 --- a/app/services/unblock_service.rb +++ b/app/services/unblock_service.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class UnblockService < BaseService + include Payloadable + def call(account, target_account) return unless account.blocking?(target_account) @@ -20,11 +22,7 @@ class UnblockService < BaseService end def build_json(unblock) - ActiveModelSerializers::SerializableResource.new( - unblock, - serializer: ActivityPub::UndoBlockSerializer, - adapter: ActivityPub::Adapter - ).to_json + Oj.dump(serialize_payload(unblock, ActivityPub::UndoBlockSerializer)) end def build_xml(block) diff --git a/app/services/unfavourite_service.rb b/app/services/unfavourite_service.rb index 2fda11bd660292be67c5eb99ad2960b4422bd3ab..dcc890b7de5f40e6fb3a8a439cf5af0dee31280c 100644 --- a/app/services/unfavourite_service.rb +++ b/app/services/unfavourite_service.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class UnfavouriteService < BaseService + include Payloadable + def call(account, status) favourite = Favourite.find_by!(account: account, status: status) favourite.destroy! @@ -21,11 +23,7 @@ class UnfavouriteService < BaseService end def build_json(favourite) - Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new( - favourite, - serializer: ActivityPub::UndoLikeSerializer, - adapter: ActivityPub::Adapter - ).as_json).sign!(favourite.account)) + Oj.dump(serialize_payload(favourite, ActivityPub::UndoLikeSerializer)) end def build_xml(favourite) diff --git a/app/services/unfollow_service.rb b/app/services/unfollow_service.rb index 95da2a667b32c03ba5a1be1a6da8acd2bfbd579e..17dc29735f9d5006fd7ece962c2c22b6d97de635 100644 --- a/app/services/unfollow_service.rb +++ b/app/services/unfollow_service.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class UnfollowService < BaseService + include Payloadable + # Unfollow and notify the remote user # @param [Account] source_account Where to unfollow from # @param [Account] target_account Which to unfollow @@ -50,19 +52,11 @@ class UnfollowService < BaseService end def build_json(follow) - ActiveModelSerializers::SerializableResource.new( - follow, - serializer: ActivityPub::UndoFollowSerializer, - adapter: ActivityPub::Adapter - ).to_json + Oj.dump(serialize_payload(follow, ActivityPub::UndoFollowSerializer)) end def build_reject_json(follow) - ActiveModelSerializers::SerializableResource.new( - follow, - serializer: ActivityPub::RejectFollowSerializer, - adapter: ActivityPub::Adapter - ).to_json + Oj.dump(serialize_payload(follow, ActivityPub::RejectFollowSerializer)) end def build_xml(follow) diff --git a/app/services/vote_service.rb b/app/services/vote_service.rb index 81af9ef3a4b1df26445d8cdeab7eea1057306f91..0eeb8fd56a95f5a6c2dbb87a9638037ba1b1ce27 100644 --- a/app/services/vote_service.rb +++ b/app/services/vote_service.rb @@ -2,6 +2,7 @@ class VoteService < BaseService include Authorization + include Payloadable def call(account, poll, choices) authorize_with account, poll, :vote? @@ -50,10 +51,6 @@ class VoteService < BaseService end def build_json(vote) - ActiveModelSerializers::SerializableResource.new( - vote, - serializer: ActivityPub::VoteSerializer, - adapter: ActivityPub::Adapter - ).to_json + Oj.dump(serialize_payload(vote, ActivityPub::VoteSerializer)) end end diff --git a/app/workers/activitypub/distribute_poll_update_worker.rb b/app/workers/activitypub/distribute_poll_update_worker.rb index 5eaca6fda30aa4655255c603e3d1268e1eb59844..1e87fa4bf2a784966773e3aeb654ad84cb45fed3 100644 --- a/app/workers/activitypub/distribute_poll_update_worker.rb +++ b/app/workers/activitypub/distribute_poll_update_worker.rb @@ -2,6 +2,7 @@ class ActivityPub::DistributePollUpdateWorker include Sidekiq::Worker + include Payloadable sidekiq_options queue: 'push', unique: :until_executed, retry: 0 @@ -41,20 +42,8 @@ class ActivityPub::DistributePollUpdateWorker @inboxes end - def signed_payload - Oj.dump(ActivityPub::LinkedDataSignature.new(unsigned_payload).sign!(@account)) - end - - def unsigned_payload - ActiveModelSerializers::SerializableResource.new( - @status, - serializer: ActivityPub::UpdatePollSerializer, - adapter: ActivityPub::Adapter - ).as_json - end - def payload - @payload ||= @status.distributable? ? signed_payload : Oj.dump(unsigned_payload) + @payload ||= Oj.dump(serialize_payload(@status, ActivityPub::UpdatePollSerializer, signer: @account)) end def relay! diff --git a/app/workers/activitypub/distribution_worker.rb b/app/workers/activitypub/distribution_worker.rb index d83f017000896eb9dc0f9320f65a1db544da839d..11b6a611108606b6bd9f91e368cd05cec62d8db4 100644 --- a/app/workers/activitypub/distribution_worker.rb +++ b/app/workers/activitypub/distribution_worker.rb @@ -2,6 +2,7 @@ class ActivityPub::DistributionWorker include Sidekiq::Worker + include Payloadable sidekiq_options queue: 'push' @@ -41,20 +42,8 @@ class ActivityPub::DistributionWorker end end - def signed_payload - Oj.dump(ActivityPub::LinkedDataSignature.new(unsigned_payload).sign!(@account)) - end - - def unsigned_payload - ActiveModelSerializers::SerializableResource.new( - @status, - serializer: ActivityPub::ActivitySerializer, - adapter: ActivityPub::Adapter - ).as_json - end - def payload - @payload ||= @status.distributable? ? signed_payload : Oj.dump(unsigned_payload) + @payload ||= Oj.dump(serialize_payload(@status, ActivityPub::ActivitySerializer, signer: @account)) end def relay! diff --git a/app/workers/activitypub/reply_distribution_worker.rb b/app/workers/activitypub/reply_distribution_worker.rb index d8fea6c4e5cafacbca0fc15f10373ce44ab0edb7..1ff8a657e8391912609afeafd9a4ee7b27b700b3 100644 --- a/app/workers/activitypub/reply_distribution_worker.rb +++ b/app/workers/activitypub/reply_distribution_worker.rb @@ -5,6 +5,7 @@ class ActivityPub::ReplyDistributionWorker include Sidekiq::Worker + include Payloadable sidekiq_options queue: 'push' @@ -27,19 +28,7 @@ class ActivityPub::ReplyDistributionWorker @inboxes ||= @account.followers.inboxes end - def signed_payload - Oj.dump(ActivityPub::LinkedDataSignature.new(unsigned_payload).sign!(@status.account)) - end - - def unsigned_payload - ActiveModelSerializers::SerializableResource.new( - @status, - serializer: ActivityPub::ActivitySerializer, - adapter: ActivityPub::Adapter - ).as_json - end - def payload - @payload ||= @status.distributable? ? signed_payload : Oj.dump(unsigned_payload) + @payload ||= Oj.dump(serialize_payload(@status, ActivityPub::ActivitySerializer, signer: @status.account)) end end diff --git a/app/workers/activitypub/update_distribution_worker.rb b/app/workers/activitypub/update_distribution_worker.rb index b9e5ff064f2e532ec1eb8b2c79eb6867badfab1d..3a207f0719c616c3d8a56b97e490b7ba5b54a751 100644 --- a/app/workers/activitypub/update_distribution_worker.rb +++ b/app/workers/activitypub/update_distribution_worker.rb @@ -2,6 +2,7 @@ class ActivityPub::UpdateDistributionWorker include Sidekiq::Worker + include Payloadable sidekiq_options queue: 'push' @@ -27,14 +28,6 @@ class ActivityPub::UpdateDistributionWorker end def signed_payload - @signed_payload ||= Oj.dump(ActivityPub::LinkedDataSignature.new(payload).sign!(@account, sign_with: @options[:sign_with])) - end - - def payload - @payload ||= ActiveModelSerializers::SerializableResource.new( - @account, - serializer: ActivityPub::UpdateSerializer, - adapter: ActivityPub::Adapter - ).as_json + @signed_payload ||= Oj.dump(serialize_payload(@account, ActivityPub::UpdateSerializer, signer: @account, sign_with: @options[:sign_with])) end end