diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2018-10-17 17:13:04 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-17 17:13:04 +0200 |
commit | ddd30f331c7a2af38176d72d9ce2265068984bed (patch) | |
tree | 78ff80eee6e2a10ba8539c6e3211a71fc6ca0ead /app/lib | |
parent | 00387be2898cab016fa730d4f5683202cc540442 (diff) |
Improve support for aspects/circles (#8950)
* Add silent column to mentions * Save silent mentions in ActivityPub Create handler and optimize it Move networking calls out of the database transaction * Add "limited" visibility level masked as "private" in the API Unlike DMs, limited statuses are pushed into home feeds. The access control rules between direct and limited statuses is almost the same, except for counter and conversation logic * Ensure silent column is non-null, add spec * Ensure filters don't check silent mentions for blocks/mutes As those are "this person is also allowed to see" rather than "this person is involved", therefore does not warrant filtering * Clean up code * Use Status#active_mentions to limit returned mentions * Fix code style issues * Use Status#active_mentions in Notification And remove stream_entry eager-loading from Notification
Diffstat (limited to 'app/lib')
-rw-r--r-- | app/lib/activitypub/activity.rb | 2 | ||||
-rw-r--r-- | app/lib/activitypub/activity/create.rb | 24 | ||||
-rw-r--r-- | app/lib/activitypub/tag_manager.rb | 6 | ||||
-rw-r--r-- | app/lib/feed_manager.rb | 8 | ||||
-rw-r--r-- | app/lib/formatter.rb | 2 | ||||
-rw-r--r-- | app/lib/ostatus/atom_serializer.rb | 2 |
6 files changed, 33 insertions, 11 deletions
diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 3a39b723e..999954cb5 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -96,7 +96,7 @@ class ActivityPub::Activity end def notify_about_mentions(status) - status.mentions.includes(:account).each do |mention| + status.active_mentions.includes(:account).each do |mention| next unless mention.account.local? && audience_includes?(mention.account) NotifyService.new.call(mention.account, mention) end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 73475bf02..7e6702a63 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -28,6 +28,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity process_status_params process_tags + process_audience ApplicationRecord.transaction do @status = Status.create!(@params) @@ -66,6 +67,27 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end end + def process_audience + (as_array(@object['to']) + as_array(@object['cc'])).uniq.each do |audience| + next if audience == ActivityPub::TagManager::COLLECTIONS[:public] + + # Unlike with tags, there is no point in resolving accounts we don't already + # know here, because silent mentions would only be used for local access + # control anyway + account = account_from_uri(audience) + + next if account.nil? || @mentions.any? { |mention| mention.account_id == account.id } + + @mentions << Mention.new(account: account, silent: true) + + # If there is at least one silent mention, then the status can be considered + # as a limited-audience status, and not strictly a direct message + next unless @params[:visibility] == :direct + + @params[:visibility] = :limited + end + end + def attach_tags(status) @tags.each do |tag| status.tags << tag @@ -113,7 +135,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity return if account.nil? - @mentions << Mention.new(account: account) + @mentions << Mention.new(account: account, silent: false) end def process_emoji(tag) diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index 95d1cf9f3..be3a562d0 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -58,8 +58,8 @@ class ActivityPub::TagManager [COLLECTIONS[:public]] when 'unlisted', 'private' [account_followers_url(status.account)] - when 'direct' - status.mentions.map { |mention| uri_for(mention.account) } + when 'direct', 'limited' + status.active_mentions.map { |mention| uri_for(mention.account) } end end @@ -80,7 +80,7 @@ class ActivityPub::TagManager cc << COLLECTIONS[:public] end - cc.concat(status.mentions.map { |mention| uri_for(mention.account) }) unless status.direct_visibility? + cc.concat(status.active_mentions.map { |mention| uri_for(mention.account) }) unless status.direct_visibility? || status.limited_visibility? cc end diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index b10e5dd24..3d7db2721 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -88,7 +88,7 @@ class FeedManager end query.each do |status| - next if status.direct_visibility? || filter?(:home, status, into_account) + next if status.direct_visibility? || status.limited_visibility? || filter?(:home, status, into_account) add_to_feed(:home, into_account.id, status) end @@ -156,12 +156,12 @@ class FeedManager return true if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?) return true if phrase_filtered?(status, receiver_id, :home) - check_for_blocks = status.mentions.pluck(:account_id) + check_for_blocks = status.active_mentions.pluck(:account_id) check_for_blocks.concat([status.account_id]) if status.reblog? check_for_blocks.concat([status.reblog.account_id]) - check_for_blocks.concat(status.reblog.mentions.pluck(:account_id)) + check_for_blocks.concat(status.reblog.active_mentions.pluck(:account_id)) end return true if blocks_or_mutes?(receiver_id, check_for_blocks, :home) @@ -188,7 +188,7 @@ class FeedManager # This filter is called from NotifyService, but already after the sender of # the notification has been checked for mute/block. Therefore, it's not # necessary to check the author of the toot for mute/block again - check_for_blocks = status.mentions.pluck(:account_id) + check_for_blocks = status.active_mentions.pluck(:account_id) check_for_blocks.concat([status.in_reply_to_account]) if status.reply? && !status.in_reply_to_account_id.nil? should_filter = blocks_or_mutes?(receiver_id, check_for_blocks, :mentions) # Filter if it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked (or muted) diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 35d5a09b7..d13884ec8 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -27,7 +27,7 @@ class Formatter return html.html_safe # rubocop:disable Rails/OutputSafety end - linkable_accounts = status.mentions.map(&:account) + linkable_accounts = status.active_mentions.map(&:account) linkable_accounts << status.account html = raw_content diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb index 1a0a635b3..7a181fb40 100644 --- a/app/lib/ostatus/atom_serializer.rb +++ b/app/lib/ostatus/atom_serializer.rb @@ -354,7 +354,7 @@ class OStatus::AtomSerializer append_element(entry, 'summary', status.spoiler_text, 'xml:lang': status.language) if status.spoiler_text? append_element(entry, 'content', Formatter.instance.format(status).to_str || '.', type: 'html', 'xml:lang': status.language) - status.mentions.sort_by(&:id).each do |mentioned| + status.active_mentions.sort_by(&:id).each do |mentioned| append_element(entry, 'link', nil, rel: :mentioned, 'ostatus:object-type': OStatus::TagManager::TYPES[:person], href: OStatus::TagManager.instance.uri_for(mentioned.account)) end |