From 149887a0ffc81b588520ff82ab9fda8dff7bce6c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 11 Feb 2017 02:12:05 +0100 Subject: Make follow requests federate --- app/models/favourite.rb | 4 ++-- app/models/follow_request.rb | 36 ++++++++++++++++++++++++++++++++++++ app/models/stream_entry.rb | 2 +- 3 files changed, 39 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/favourite.rb b/app/models/favourite.rb index 3f3616dce..cd8e2098c 100644 --- a/app/models/favourite.rb +++ b/app/models/favourite.rb @@ -12,11 +12,11 @@ class Favourite < ApplicationRecord validates :status_id, uniqueness: { scope: :account_id } def verb - :favorite + destroyed? ? :unfavorite : :favorite end def title - "#{account.acct} favourited a status by #{status.account.acct}" + destroyed? ? "#{account.acct} no longer favourites a status by #{status.account.acct}" : "#{account.acct} favourited a status by #{status.account.acct}" end delegate :object_type, to: :target diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb index 936ad0691..989c2c2a2 100644 --- a/app/models/follow_request.rb +++ b/app/models/follow_request.rb @@ -2,6 +2,7 @@ class FollowRequest < ApplicationRecord include Paginable + include Streamable belongs_to :account belongs_to :target_account, class_name: 'Account' @@ -12,12 +13,47 @@ class FollowRequest < ApplicationRecord validates :account_id, uniqueness: { scope: :target_account_id } def authorize! + @verb = :authorize + account.follow!(target_account) MergeWorker.perform_async(target_account.id, account.id) + destroy! end def reject! + @verb = :reject destroy! end + + def verb + destroyed? ? (@verb || :delete) : :request_friend + end + + def target + target_account + end + + def object_type + :person + end + + def hidden? + true + end + + def title + if destroyed? + case @verb + when :authorize + "#{target_account.acct} authorized #{account.acct}'s request to follow" + when :reject + "#{target_account.acct} rejected #{account.acct}'s request to follow" + else + "#{account.acct} withdrew the request to follow #{target_account.acct}" + end + else + "#{account.acct} requested to follow #{target_account.acct}" + end + end end diff --git a/app/models/stream_entry.rb b/app/models/stream_entry.rb index fcc691bef..e0b85be15 100644 --- a/app/models/stream_entry.rb +++ b/app/models/stream_entry.rb @@ -30,7 +30,7 @@ class StreamEntry < ApplicationRecord end def targeted? - [:follow, :unfollow, :block, :unblock, :share, :favorite].include? verb + [:follow, :request_friend, :authorize, :unfollow, :block, :unblock, :share, :favorite].include? verb end def target -- cgit From dc851c922ee1c244146baf1415a7bce4a25cccef Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 11 Feb 2017 15:10:22 +0100 Subject: Mentions in private statuses allow mentioned people to see them --- app/lib/feed_manager.rb | 1 - app/models/status.rb | 10 +++++++++- app/services/process_feed_service.rb | 18 +++++++----------- app/services/process_mentions_service.rb | 2 -- 4 files changed, 16 insertions(+), 15 deletions(-) (limited to 'app/models') diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index f0928a945..623a1af03 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -107,7 +107,6 @@ class FeedManager should_filter ||= receiver.blocking?(status.account) # or it's from someone I blocked should_filter ||= receiver.blocking?(status.mentions.includes(:account).map(&:account)) # or if it mentions someone I blocked should_filter ||= (status.account.silenced? && !receiver.following?(status.account)) # of if the account is silenced and I'm not following them - should_filter ||= (status.private_visibility? && !receiver.following?(status.account)) # or if the mentioned account is not permitted to see the private status if status.reply? && !status.in_reply_to_account_id.nil? # or it's a reply should_filter ||= receiver.blocking?(status.in_reply_to_account) # to a user I blocked diff --git a/app/models/status.rb b/app/models/status.rb index d2be72308..93594ec8f 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -76,7 +76,11 @@ class Status < ApplicationRecord end def permitted?(other_account = nil) - private_visibility? ? (account.id == other_account&.id || other_account&.following?(account)) : other_account.nil? || !account.blocking?(other_account) + if private_visibility? + (account.id == other_account&.id || other_account&.following?(account) || mentions.include?(other_account)) + else + other_account.nil? || !account.blocking?(other_account) + end end def ancestors(account = nil) @@ -153,6 +157,10 @@ class Status < ApplicationRecord where('1 = 1') elsif !account.nil? && target_account.blocking?(account) where('1 = 0') + elsif !account.nil? + joins('LEFT OUTER JOIN mentions ON statuses.id = mentions.status_id') + .where('mentions.account_id = ?', account.id) + .where('statuses.visibility != ? OR mentions.id IS NOT NULL', Status.visibilities[:private]) else where.not(visibility: :private) end diff --git a/app/services/process_feed_service.rb b/app/services/process_feed_service.rb index c411e3e82..f0a62aa14 100644 --- a/app/services/process_feed_service.rb +++ b/app/services/process_feed_service.rb @@ -106,7 +106,8 @@ class ProcessFeedService < BaseService text: content(entry), spoiler_text: content_warning(entry), created_at: published(entry), - reply: thread?(entry) + reply: thread?(entry), + visibility: visibility_scope(entry) ) if thread?(entry) @@ -144,15 +145,9 @@ class ProcessFeedService < BaseService def mentions_from_xml(parent, xml) processed_account_ids = [] - public_visibility = false xml.xpath('./xmlns:link[@rel="mentioned"]', xmlns: TagManager::XMLNS).each do |link| - if link['ostatus:object-type'] == TagManager::TYPES[:collection] && link['href'] == TagManager::COLLECTIONS[:public] - public_visibility = true - next - elsif link['ostatus:object-type'] == TagManager::TYPES[:group] - next - end + next if [TagManager::TYPES[:group], TagManager::TYPES[:collection]].include? link['ostatus:object-type'] url = Addressable::URI.parse(link['href']) @@ -172,9 +167,6 @@ class ProcessFeedService < BaseService # So we can skip duplicate mentions processed_account_ids << mentioned_account.id end - - parent.visibility = public_visibility ? :public : :unlisted - parent.save! end def hashtags_from_xml(parent, xml) @@ -230,6 +222,10 @@ class ProcessFeedService < BaseService xml.at_xpath('./xmlns:summary', xmlns: TagManager::XMLNS)&.content || '' end + def visibility_scope(xml = @xml) + xml.at_xpath('./mastodon:scope', mastodon: TagManager::MTDN_XMLNS)&.content&.to_sym || :public + end + def published(xml = @xml) xml.at_xpath('./xmlns:published', xmlns: TagManager::XMLNS).content end diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index 67fd3dcf7..d3d3af8af 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -30,8 +30,6 @@ class ProcessMentionsService < BaseService status.mentions.each do |mention| mentioned_account = mention.account - next if status.private_visibility? && (!mentioned_account.following?(status.account) || !mentioned_account.local?) - if mentioned_account.local? NotifyService.new.call(mentioned_account, mention) else -- cgit From 446aad4ce2cb7afd0ba8e4b508e4dcba57eac790 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 11 Feb 2017 15:41:39 +0100 Subject: Make PuSH only distribute to subscriptions that match follower domains Allow PuSH to distribute private toots with that condition --- app/models/account.rb | 4 ++++ app/workers/pubsubhubbub/distribution_worker.rb | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/account.rb b/app/models/account.rb index c2a41c4c6..ed5c46197 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -95,6 +95,10 @@ class Account < ApplicationRecord follow_requests.where(target_account: other_account).exists? end + def followers_domains + followers.reorder('').select('DISTINCT accounts.domain').map(&:domain) + end + def local? domain.nil? end diff --git a/app/workers/pubsubhubbub/distribution_worker.rb b/app/workers/pubsubhubbub/distribution_worker.rb index d5437bf6b..4576dc4a2 100644 --- a/app/workers/pubsubhubbub/distribution_worker.rb +++ b/app/workers/pubsubhubbub/distribution_worker.rb @@ -8,13 +8,18 @@ class Pubsubhubbub::DistributionWorker def perform(stream_entry_id) stream_entry = StreamEntry.find(stream_entry_id) - return if stream_entry.hidden? + # Most hidden stream entries should not be PuSHed, + # but statuses need to be distributed to trusted + # followers even when they are hidden + return if stream_entry.hidden? && stream_entry.activity_type != 'Status' account = stream_entry.account renderer = AccountsController.renderer.new(method: 'get', http_host: Rails.configuration.x.local_domain, https: Rails.configuration.x.use_https) payload = renderer.render(:show, assigns: { account: account, entries: [stream_entry] }, formats: [:atom]) + domains = account.followers_domains - Subscription.where(account: account).active.select('id').find_each do |subscription| + Subscription.where(account: account).active.select('id, callback_url').find_each do |subscription| + next unless domains.include?(Addressable::URI.parse(subscription.callback_url).host) Pubsubhubbub::DeliveryWorker.perform_async(subscription.id, payload) end rescue ActiveRecord::RecordNotFound -- cgit