diff options
Diffstat (limited to 'app/services')
-rw-r--r-- | app/services/activitypub/fetch_remote_poll_service.rb | 51 | ||||
-rw-r--r-- | app/services/activitypub/fetch_replies_service.rb | 9 | ||||
-rw-r--r-- | app/services/activitypub/process_poll_service.rb | 64 | ||||
-rw-r--r-- | app/services/app_sign_up_service.rb | 2 | ||||
-rw-r--r-- | app/services/notify_service.rb | 6 | ||||
-rw-r--r-- | app/services/post_status_service.rb | 3 | ||||
-rw-r--r-- | app/services/remove_status_service.rb | 6 | ||||
-rw-r--r-- | app/services/vote_service.rb | 23 |
8 files changed, 98 insertions, 66 deletions
diff --git a/app/services/activitypub/fetch_remote_poll_service.rb b/app/services/activitypub/fetch_remote_poll_service.rb index 4f9814fcd..44a23712c 100644 --- a/app/services/activitypub/fetch_remote_poll_service.rb +++ b/app/services/activitypub/fetch_remote_poll_service.rb @@ -4,54 +4,7 @@ class ActivityPub::FetchRemotePollService < BaseService include JsonLdHelper def call(poll, on_behalf_of = nil) - @json = fetch_resource(poll.status.uri, true, on_behalf_of) - - return unless supported_context? && expected_type? - - expires_at = begin - if @json['closed'].is_a?(String) - @json['closed'] - elsif !@json['closed'].nil? && !@json['closed'].is_a?(FalseClass) - Time.now.utc - else - @json['endTime'] - end - end - - items = begin - if @json['anyOf'].is_a?(Array) - @json['anyOf'] - else - @json['oneOf'] - end - end - - latest_options = items.map { |item| item['name'].presence || item['content'] } - - # If for some reasons the options were changed, it invalidates all previous - # votes, so we need to remove them - poll.votes.delete_all if latest_options != poll.options - - begin - poll.update!( - last_fetched_at: Time.now.utc, - expires_at: expires_at, - options: latest_options, - cached_tallies: items.map { |item| item.dig('replies', 'totalItems') || 0 } - ) - rescue ActiveRecord::StaleObjectError - poll.reload - retry - end - end - - private - - def supported_context? - super(@json) - end - - def expected_type? - equals_or_includes_any?(@json['type'], %w(Question)) + json = fetch_resource(poll.status.uri, true, on_behalf_of) + ActivityPub::ProcessPollService.new.call(poll, json) end end diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb index 569d0d7c1..8cb309e52 100644 --- a/app/services/activitypub/fetch_replies_service.rb +++ b/app/services/activitypub/fetch_replies_service.rb @@ -46,13 +46,4 @@ class ActivityPub::FetchRepliesService < BaseService # Also limit to 5 fetched replies to limit potential for DoS. @items.map { |item| value_or_id(item) }.reject { |uri| invalid_origin?(uri) }.take(5) end - - def invalid_origin?(url) - return true if unsupported_uri_scheme?(url) - - needle = Addressable::URI.parse(url).host - haystack = Addressable::URI.parse(@account.uri).host - - !haystack.casecmp(needle).zero? - end end diff --git a/app/services/activitypub/process_poll_service.rb b/app/services/activitypub/process_poll_service.rb new file mode 100644 index 000000000..ee248169d --- /dev/null +++ b/app/services/activitypub/process_poll_service.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +class ActivityPub::ProcessPollService < BaseService + include JsonLdHelper + + def call(poll, json) + @json = json + return unless supported_context? && expected_type? + + previous_expires_at = poll.expires_at + + expires_at = begin + if @json['closed'].is_a?(String) + @json['closed'] + elsif !@json['closed'].nil? && !@json['closed'].is_a?(FalseClass) + Time.now.utc + else + @json['endTime'] + end + end + + items = begin + if @json['anyOf'].is_a?(Array) + @json['anyOf'] + else + @json['oneOf'] + end + end + + latest_options = items.map { |item| item['name'].presence || item['content'] } + + # If for some reasons the options were changed, it invalidates all previous + # votes, so we need to remove them + poll.votes.delete_all if latest_options != poll.options + + begin + poll.update!( + last_fetched_at: Time.now.utc, + expires_at: expires_at, + options: latest_options, + cached_tallies: items.map { |item| item.dig('replies', 'totalItems') || 0 } + ) + rescue ActiveRecord::StaleObjectError + poll.reload + retry + end + + # If the poll had no expiration date set but now has, and people have voted, + # schedule a notification. + if previous_expires_at.nil? && poll.expires_at.present? && poll.votes.exists? + PollExpirationNotifyWorker.perform_at(poll.expires_at + 5.minutes, poll.id) + end + end + + private + + def supported_context? + super(@json) + end + + def expected_type? + equals_or_includes_any?(@json['type'], %w(Question)) + end +end diff --git a/app/services/app_sign_up_service.rb b/app/services/app_sign_up_service.rb index d621cc462..6dee9cd81 100644 --- a/app/services/app_sign_up_service.rb +++ b/app/services/app_sign_up_service.rb @@ -18,6 +18,6 @@ class AppSignUpService < BaseService private def allowed_registrations? - Setting.open_registrations && !Rails.configuration.x.single_user_mode + Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode end end diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index b80ceef03..b5c721589 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -38,6 +38,10 @@ class NotifyService < BaseService false end + def blocked_poll? + false + end + def following_sender? return @following_sender if defined?(@following_sender) @following_sender = @recipient.following?(@notification.from_account) || @recipient.requested?(@notification.from_account) @@ -88,7 +92,7 @@ class NotifyService < BaseService def blocked? blocked = @recipient.suspended? # Skip if the recipient account is suspended anyway - blocked ||= from_self? # Skip for interactions with self + blocked ||= from_self? && @notification.type != :poll # Skip for interactions with self return blocked if message? && from_staff? diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index 8a9d26c56..b9952369d 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -91,10 +91,13 @@ class PostStatusService < BaseService def postprocess_status! LinkCrawlWorker.perform_async(@status.id) unless @status.spoiler_text? DistributionWorker.perform_async(@status.id) + unless @status.local_only? Pubsubhubbub::DistributionWorker.perform_async(@status.stream_entry.id) ActivityPub::DistributionWorker.perform_async(@status.id) end + + PollExpirationNotifyWorker.perform_at(@status.poll.expires_at, @status.poll.id) if @status.poll end def validate_media! diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 99c8e6cbb..7eec11ddf 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -10,7 +10,7 @@ class RemoveStatusService < BaseService @account = status.account @tags = status.tags.pluck(:name).to_a @mentions = status.active_mentions.includes(:account).to_a - @reblogs = status.reblogs.to_a + @reblogs = status.reblogs.includes(:account).to_a @stream_entry = status.stream_entry @options = options @@ -78,8 +78,8 @@ class RemoveStatusService < BaseService end # ActivityPub - ActivityPub::DeliveryWorker.push_bulk(target_accounts.select(&:activitypub?).uniq(&:inbox_url)) do |target_account| - [signed_activity_json, @account.id, target_account.inbox_url] + ActivityPub::DeliveryWorker.push_bulk(target_accounts.select(&:activitypub?).uniq(&:preferred_inbox_url)) do |target_account| + [signed_activity_json, @account.id, target_account.preferred_inbox_url] end end diff --git a/app/services/vote_service.rb b/app/services/vote_service.rb index 5b80da03a..0cace6c00 100644 --- a/app/services/vote_service.rb +++ b/app/services/vote_service.rb @@ -19,8 +19,27 @@ class VoteService < BaseService end end - return if @poll.account.local? + if @poll.account.local? + distribute_poll! + else + deliver_votes! + queue_final_poll_check! + end + end + + private + + def distribute_poll! + return if @poll.hide_totals? + ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, @poll.status.id) + end + + def queue_final_poll_check! + return unless @poll.expires? + PollExpirationNotifyWorker.perform_at(@poll.expires_at + 5.minutes, @poll.id) + end + def deliver_votes! @votes.each do |vote| ActivityPub::DeliveryWorker.perform_async( build_json(vote), @@ -30,8 +49,6 @@ class VoteService < BaseService end end - private - def build_json(vote) ActiveModelSerializers::SerializableResource.new( vote, |