From 6793bec4c67e695100cb4d8551f0bda0b7e87b12 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 4 May 2018 21:14:34 +0200 Subject: Store URIs of follows, follow requests and blocks for ActivityPub (#7160) Same URI passed between follow request and follow, since they are the same thing in ActivityPub. Local URIs are generated during creation using UUIDs and are passed to serializers. --- app/lib/activitypub/activity/block.rb | 2 +- app/lib/activitypub/activity/follow.rb | 2 +- app/lib/activitypub/tag_manager.rb | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'app/lib') diff --git a/app/lib/activitypub/activity/block.rb b/app/lib/activitypub/activity/block.rb index f630d5db2..26da8bdf5 100644 --- a/app/lib/activitypub/activity/block.rb +++ b/app/lib/activitypub/activity/block.rb @@ -7,6 +7,6 @@ class ActivityPub::Activity::Block < ActivityPub::Activity return if target_account.nil? || !target_account.local? || delete_arrived_first?(@json['id']) || @account.blocking?(target_account) UnfollowService.new.call(target_account, @account) if target_account.following?(@account) - @account.block!(target_account) + @account.block!(target_account, uri: @json['id']) end end diff --git a/app/lib/activitypub/activity/follow.rb b/app/lib/activitypub/activity/follow.rb index 8adbbb9c3..fbbf358a8 100644 --- a/app/lib/activitypub/activity/follow.rb +++ b/app/lib/activitypub/activity/follow.rb @@ -12,7 +12,7 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity return end - follow_request = FollowRequest.create!(account: @account, target_account: target_account) + follow_request = FollowRequest.create!(account: @account, target_account: target_account, uri: @json['id']) if target_account.locked? NotifyService.new.call(target_account, follow_request) diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index fa2a8f7d3..908ea9639 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -38,6 +38,10 @@ class ActivityPub::TagManager end end + def generate_uri_for(_target) + URI.join(root_url, 'payloads', SecureRandom.uuid) + end + def activity_uri_for(target) raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local? -- cgit From c947e2e4c57dd6d351fd740c0070fefdc1e1298c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 5 May 2018 18:22:34 +0200 Subject: Fix handling of malformed ActivityPub payloads when URIs are nil (#7370) * Fix handling of malformed ActivityPub payloads when URIs are nil * Gracefully handle JSON-LD canonicalization failures --- app/lib/activitypub/tag_manager.rb | 4 ++++ app/services/activitypub/fetch_remote_status_service.rb | 1 + app/services/activitypub/process_collection_service.rb | 3 +++ 3 files changed, 8 insertions(+) (limited to 'app/lib') diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index 908ea9639..95d1cf9f3 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -86,6 +86,8 @@ class ActivityPub::TagManager end def local_uri?(uri) + return false if uri.nil? + uri = Addressable::URI.parse(uri) host = uri.normalized_host host = "#{host}:#{uri.port}" if uri.port @@ -99,6 +101,8 @@ class ActivityPub::TagManager end def uri_to_resource(uri, klass) + return if uri.nil? + if local_uri?(uri) case klass.name when 'Account' diff --git a/app/services/activitypub/fetch_remote_status_service.rb b/app/services/activitypub/fetch_remote_status_service.rb index 930fbad1f..b6c00a9e7 100644 --- a/app/services/activitypub/fetch_remote_status_service.rb +++ b/app/services/activitypub/fetch_remote_status_service.rb @@ -34,6 +34,7 @@ class ActivityPub::FetchRemoteStatusService < BaseService end def trustworthy_attribution?(uri, attributed_to) + return false if uri.nil? || attributed_to.nil? Addressable::URI.parse(uri).normalized_host.casecmp(Addressable::URI.parse(attributed_to).normalized_host).zero? end diff --git a/app/services/activitypub/process_collection_service.rb b/app/services/activitypub/process_collection_service.rb index eb93329e9..79cdca297 100644 --- a/app/services/activitypub/process_collection_service.rb +++ b/app/services/activitypub/process_collection_service.rb @@ -45,5 +45,8 @@ class ActivityPub::ProcessCollectionService < BaseService def verify_account! @account = ActivityPub::LinkedDataSignature.new(@json).verify_account! + rescue JSON::LD::JsonLdError => e + Rails.logger.debug "Could not verify LD-Signature for #{value_or_id(@json['actor'])}: #{e.message}" + nil end end -- cgit From 61a90186070395e133ad2f8e959bdf003a8615ca Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 6 May 2018 11:48:51 +0200 Subject: Enable custom emojis in profiles (notes, field values, display names) (#7374) Follow-up to #6124 --- app/helpers/stream_entries_helper.rb | 4 ++-- .../mastodon/actions/importer/normalizer.js | 19 +++++++++++-------- app/lib/formatter.rb | 12 ++++++++++-- app/models/account.rb | 6 +++++- app/serializers/rest/account_serializer.rb | 1 + app/views/about/_administration.html.haml | 2 +- app/views/about/_contact.html.haml | 2 +- app/views/accounts/_grid_card.html.haml | 2 +- app/views/accounts/_header.html.haml | 4 ++-- app/views/accounts/_moved_strip.html.haml | 4 ++-- app/views/admin/reports/_account.html.haml | 2 +- app/views/authorize_follows/_card.html.haml | 2 +- app/views/remote_unfollows/_card.html.haml | 2 +- app/views/shared/_landing_strip.html.haml | 2 +- app/views/stream_entries/_detailed_status.html.haml | 2 +- app/views/stream_entries/_simple_status.html.haml | 2 +- app/views/stream_entries/_status.html.haml | 2 +- 17 files changed, 43 insertions(+), 27 deletions(-) (limited to 'app/lib') diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/stream_entries_helper.rb index c6f12ecd4..707c8e26c 100644 --- a/app/helpers/stream_entries_helper.rb +++ b/app/helpers/stream_entries_helper.rb @@ -4,8 +4,8 @@ module StreamEntriesHelper EMBEDDED_CONTROLLER = 'statuses' EMBEDDED_ACTION = 'embed' - def display_name(account) - account.display_name.presence || account.username + def display_name(account, **options) + Formatter.instance.format_display_name(account, options) end def account_description(account) diff --git a/app/javascript/mastodon/actions/importer/normalizer.js b/app/javascript/mastodon/actions/importer/normalizer.js index 5f1274fab..057bff58b 100644 --- a/app/javascript/mastodon/actions/importer/normalizer.js +++ b/app/javascript/mastodon/actions/importer/normalizer.js @@ -3,18 +3,25 @@ import emojify from '../../features/emoji/emoji'; const domParser = new DOMParser(); +const makeEmojiMap = record => record.emojis.reduce((obj, emoji) => { + obj[`:${emoji.shortcode}:`] = emoji; + return obj; +}, {}); + export function normalizeAccount(account) { account = { ...account }; + const emojiMap = makeEmojiMap(account); const displayName = account.display_name.length === 0 ? account.username : account.display_name; - account.display_name_html = emojify(escapeTextContentForBrowser(displayName)); - account.note_emojified = emojify(account.note); + + account.display_name_html = emojify(escapeTextContentForBrowser(displayName), emojiMap); + account.note_emojified = emojify(account.note, emojiMap); if (account.fields) { account.fields = account.fields.map(pair => ({ ...pair, name_emojified: emojify(escapeTextContentForBrowser(pair.name)), - value_emojified: emojify(pair.value), + value_emojified: emojify(pair.value, emojiMap), })); } @@ -42,11 +49,7 @@ export function normalizeStatus(status, normalOldStatus) { normalStatus.hidden = normalOldStatus.get('hidden'); } else { const searchContent = [status.spoiler_text, status.content].join('\n\n').replace(//g, '\n').replace(/<\/p>

/g, '\n\n'); - - const emojiMap = normalStatus.emojis.reduce((obj, emoji) => { - obj[`:${emoji.shortcode}:`] = emoji; - return obj; - }, {}); + const emojiMap = makeEmojiMap(normalStatus); normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent; normalStatus.contentHtml = emojify(normalStatus.content, emojiMap); diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 050c651ee..e1ab05cc0 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -67,9 +67,17 @@ class Formatter html.html_safe # rubocop:disable Rails/OutputSafety end - def format_field(account, str) + def format_display_name(account, **options) + html = encode(account.display_name.presence || account.username) + html = encode_custom_emojis(html, account.emojis) if options[:custom_emojify] + html.html_safe # rubocop:disable Rails/OutputSafety + end + + def format_field(account, str, **options) return reformat(str).html_safe unless account.local? # rubocop:disable Rails/OutputSafety - encode_and_link_urls(str, me: true).html_safe # rubocop:disable Rails/OutputSafety + html = encode_and_link_urls(str, me: true) + html = encode_custom_emojis(html, account.emojis) if options[:custom_emojify] + html.html_safe # rubocop:disable Rails/OutputSafety end def linkify(text) diff --git a/app/models/account.rb b/app/models/account.rb index 72ba0398e..4467d1512 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -398,7 +398,7 @@ class Account < ApplicationRecord end def emojis - @emojis ||= CustomEmoji.from_text(note, domain) + @emojis ||= CustomEmoji.from_text(emojifiable_text, domain) end before_create :generate_keys @@ -425,4 +425,8 @@ class Account < ApplicationRecord self.domain = TagManager.instance.normalize_domain(domain) end + + def emojifiable_text + [note, display_name, fields.map(&:value)].join(' ') + end end diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb index 863238eb7..8761bbb5e 100644 --- a/app/serializers/rest/account_serializer.rb +++ b/app/serializers/rest/account_serializer.rb @@ -8,6 +8,7 @@ class REST::AccountSerializer < ActiveModel::Serializer :followers_count, :following_count, :statuses_count has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested? + has_many :emojis, serializer: REST::CustomEmojiSerializer class FieldSerializer < ActiveModel::Serializer attributes :name, :value diff --git a/app/views/about/_administration.html.haml b/app/views/about/_administration.html.haml index ec5834f9c..02286d68b 100644 --- a/app/views/about/_administration.html.haml +++ b/app/views/about/_administration.html.haml @@ -6,7 +6,7 @@ .account__avatar{ style: "background-image: url(#{@instance_presenter.contact_account.avatar.url})" } %span.display-name %bdi - %strong.display-name__html.emojify= display_name(@instance_presenter.contact_account) + %strong.display-name__html.emojify= display_name(@instance_presenter.contact_account, custom_emojify: true) %span.display-name__account @#{@instance_presenter.contact_account.acct} - else .account__display-name diff --git a/app/views/about/_contact.html.haml b/app/views/about/_contact.html.haml index cf21ad5a3..3215d50b5 100644 --- a/app/views/about/_contact.html.haml +++ b/app/views/about/_contact.html.haml @@ -12,7 +12,7 @@ .avatar= image_tag contact.contact_account.avatar.url .name = link_to TagManager.instance.url_for(contact.contact_account) do - %span.display_name.emojify= display_name(contact.contact_account) + %span.display_name.emojify= display_name(contact.contact_account, custom_emojify: true) %span.username @#{contact.contact_account.acct} - else .owner diff --git a/app/views/accounts/_grid_card.html.haml b/app/views/accounts/_grid_card.html.haml index 95acbd581..a59ed128e 100644 --- a/app/views/accounts/_grid_card.html.haml +++ b/app/views/accounts/_grid_card.html.haml @@ -5,7 +5,7 @@ .avatar= image_tag account.avatar.url(:original) .name = link_to TagManager.instance.url_for(account) do - %span.display_name.emojify= display_name(account) + %span.display_name.emojify= display_name(account, custom_emojify: true) %span.username @#{account.local? ? account.local_username_and_domain : account.acct} = fa_icon('lock') if account.locked? diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml index 41315f039..13dcaf616 100644 --- a/app/views/accounts/_header.html.haml +++ b/app/views/accounts/_header.html.haml @@ -5,7 +5,7 @@ .card__bio %h1.name - %span.p-name.emojify= display_name(account) + %span.p-name.emojify= display_name(account, custom_emojify: true) %small< %span>< @#{account.local_username_and_domain} = fa_icon('lock') if account.locked? @@ -28,7 +28,7 @@ - account.fields.each do |field| %dl %dt.emojify{ title: field.name }= field.name - %dd.emojify{ title: field.value }= Formatter.instance.format_field(account, field.value) + %dd.emojify{ title: field.value }= Formatter.instance.format_field(account, field.value, custom_emojify: true) .details-counters .counter{ class: active_nav_class(short_account_url(account)) } diff --git a/app/views/accounts/_moved_strip.html.haml b/app/views/accounts/_moved_strip.html.haml index 6a14a5dd3..ae18c6dc7 100644 --- a/app/views/accounts/_moved_strip.html.haml +++ b/app/views/accounts/_moved_strip.html.haml @@ -3,7 +3,7 @@ .moved-strip .moved-strip__message = fa_icon 'suitcase' - = t('accounts.moved_html', name: content_tag(:strong, display_name(account), class: :emojify), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), TagManager.instance.url_for(moved_to_account), class: 'mention')) + = t('accounts.moved_html', name: content_tag(:strong, display_name(account, custom_emojify: true), class: :emojify), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), TagManager.instance.url_for(moved_to_account), class: 'mention')) .moved-strip__card = link_to TagManager.instance.url_for(moved_to_account), class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do @@ -13,5 +13,5 @@ .account__avatar-overlay-overlay{ style: "background-image: url('#{account.avatar.url(:original)}')" } %span.display-name - %strong.emojify= display_name(moved_to_account) + %strong.emojify= display_name(moved_to_account, custom_emojify: true) %span @#{moved_to_account.acct} diff --git a/app/views/admin/reports/_account.html.haml b/app/views/admin/reports/_account.html.haml index 22b7a0861..9ac161c9c 100644 --- a/app/views/admin/reports/_account.html.haml +++ b/app/views/admin/reports/_account.html.haml @@ -15,5 +15,5 @@ .account__avatar{ style: "background-image: url(#{account.avatar.url}); width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px" } %span.display-name %bdi - %strong.display-name__html.emojify= display_name(account) + %strong.display-name__html.emojify= display_name(account, custom_emojify: true) %span.display-name__account @#{account.acct} diff --git a/app/views/authorize_follows/_card.html.haml b/app/views/authorize_follows/_card.html.haml index e81e292ba..9abcfd37e 100644 --- a/app/views/authorize_follows/_card.html.haml +++ b/app/views/authorize_follows/_card.html.haml @@ -6,7 +6,7 @@ %span.display-name - account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account) = link_to account_url, class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do - %strong.emojify= display_name(account) + %strong.emojify= display_name(account, custom_emojify: true) %span @#{account.acct} - if account.note? diff --git a/app/views/remote_unfollows/_card.html.haml b/app/views/remote_unfollows/_card.html.haml index e81e292ba..9abcfd37e 100644 --- a/app/views/remote_unfollows/_card.html.haml +++ b/app/views/remote_unfollows/_card.html.haml @@ -6,7 +6,7 @@ %span.display-name - account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account) = link_to account_url, class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do - %strong.emojify= display_name(account) + %strong.emojify= display_name(account, custom_emojify: true) %span @#{account.acct} - if account.note? diff --git a/app/views/shared/_landing_strip.html.haml b/app/views/shared/_landing_strip.html.haml index ae26fc1ff..78f5ed4bc 100644 --- a/app/views/shared/_landing_strip.html.haml +++ b/app/views/shared/_landing_strip.html.haml @@ -2,7 +2,7 @@ = image_tag asset_pack_path('logo.svg'), class: 'logo' %div - = t('landing_strip_html', name: content_tag(:span, display_name(account), class: :emojify), link_to_root_path: link_to(content_tag(:strong, site_hostname), root_path)) + = t('landing_strip_html', name: content_tag(:span, display_name(account, custom_emojify: true), class: :emojify), link_to_root_path: link_to(content_tag(:strong, site_hostname), root_path)) - if open_registrations? = t('landing_strip_signup_html', sign_up_path: new_user_registration_path) diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index afc66d148..c0f1e4f0f 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -4,7 +4,7 @@ .avatar = image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '', class: 'u-photo' %span.display-name - %strong.p-name.emojify= display_name(status.account) + %strong.p-name.emojify= display_name(status.account, custom_emojify: true) %span= acct(status.account) - if embedded_view? diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml index a6f5120fb..b89860ad9 100644 --- a/app/views/stream_entries/_simple_status.html.haml +++ b/app/views/stream_entries/_simple_status.html.haml @@ -10,7 +10,7 @@ %div = image_tag status.account.avatar(:original), width: 48, height: 48, alt: '', class: 'u-photo' %span.display-name - %strong.p-name.emojify= display_name(status.account) + %strong.p-name.emojify= display_name(status.account, custom_emojify: true) %span= acct(status.account) .status__content.p-name.emojify< diff --git a/app/views/stream_entries/_status.html.haml b/app/views/stream_entries/_status.html.haml index 9764bc74d..b87ca2177 100644 --- a/app/views/stream_entries/_status.html.haml +++ b/app/views/stream_entries/_status.html.haml @@ -28,7 +28,7 @@ = fa_icon('retweet fw') %span = link_to TagManager.instance.url_for(status.account), class: 'status__display-name muted' do - %strong.emojify= display_name(status.account) + %strong.emojify= display_name(status.account, custom_emojify: true) = t('stream_entries.reblogged') - elsif pinned .pre-header -- cgit From 6208ea5a531e8ece85ec29dd42dbc051e34a29e4 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 7 May 2018 14:49:13 +0200 Subject: If an OStatus message contains nsfw hashtag, mark it as sensitive (#7398) * If an OStatus message contains nsfw hashtag, mark it as sensitive Undo parts of #7048 * Put nsfw hashtag on OStatus messages if they have any media * Fix code style issues --- app/lib/ostatus/activity/creation.rb | 8 +++++++- app/lib/ostatus/atom_serializer.rb | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'app/lib') diff --git a/app/lib/ostatus/activity/creation.rb b/app/lib/ostatus/activity/creation.rb index 1e7f47029..dbccc8330 100644 --- a/app/lib/ostatus/activity/creation.rb +++ b/app/lib/ostatus/activity/creation.rb @@ -46,7 +46,8 @@ class OStatus::Activity::Creation < OStatus::Activity::Base visibility: visibility_scope, conversation: find_or_create_conversation, thread: thread? ? find_status(thread.first) || find_activitypub_status(thread.first, thread.second) : nil, - media_attachment_ids: media_attachments.map(&:id) + media_attachment_ids: media_attachments.map(&:id), + sensitive: sensitive? ) save_mentions(status) @@ -105,6 +106,11 @@ class OStatus::Activity::Creation < OStatus::Activity::Base private + def sensitive? + # OStatus-specific convention (not standard) + @xml.xpath('./xmlns:category', xmlns: OStatus::TagManager::XMLNS).any? { |category| category['term'] == 'nsfw' } + end + def find_or_create_conversation uri = @xml.at_xpath('./ostatus:conversation', ostatus: OStatus::TagManager::OS_XMLNS)&.attribute('ref')&.content return if uri.nil? diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb index 7c66f2066..698f2ee22 100644 --- a/app/lib/ostatus/atom_serializer.rb +++ b/app/lib/ostatus/atom_serializer.rb @@ -368,6 +368,7 @@ class OStatus::AtomSerializer append_element(entry, 'link', nil, rel: :enclosure, type: media.file_content_type, length: media.file_file_size, href: full_asset_url(media.file.url(:original, false))) end + append_element(entry, 'category', nil, term: 'nsfw') if status.sensitive? && status.media_attachments.any? append_element(entry, 'mastodon:scope', status.visibility) status.emojis.each do |emoji| -- cgit From edf882320a12b2c0cfa7fc0fb7eafaa39021cb0f Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Wed, 9 May 2018 23:59:39 +0900 Subject: Support gzip encoding on Request (#7425) --- app/lib/request.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/lib') diff --git a/app/lib/request.rb b/app/lib/request.rb index 00f94dacf..fc7d398e0 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -51,7 +51,7 @@ class Request end def headers - (@account ? @headers.merge('Signature' => signature) : @headers).without(REQUEST_TARGET) + (@account ? @headers.merge('Signature' => signature) : @headers).reverse_merge('Accept-Encoding' => 'gzip').without(REQUEST_TARGET) end private @@ -100,7 +100,7 @@ class Request end def http_client - @http_client ||= HTTP.timeout(:per_operation, timeout).follow(max_hops: 2) + @http_client ||= HTTP.use(:auto_inflate).timeout(:per_operation, timeout).follow(max_hops: 2) end def use_proxy? -- cgit From 6588f6a0a9118e6feb2f23d82655b2435c6cbbca Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Thu, 10 May 2018 21:36:12 +0900 Subject: Disable inflate gzip on head method (#7432) --- app/lib/request.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'app/lib') diff --git a/app/lib/request.rb b/app/lib/request.rb index fc7d398e0..731bf7687 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -51,16 +51,17 @@ class Request end def headers - (@account ? @headers.merge('Signature' => signature) : @headers).reverse_merge('Accept-Encoding' => 'gzip').without(REQUEST_TARGET) + (@account ? @headers.merge('Signature' => signature) : @headers).without(REQUEST_TARGET) end private def set_common_headers! - @headers[REQUEST_TARGET] = "#{@verb} #{@url.path}" - @headers['User-Agent'] = user_agent - @headers['Host'] = @url.host - @headers['Date'] = Time.now.utc.httpdate + @headers[REQUEST_TARGET] = "#{@verb} #{@url.path}" + @headers['User-Agent'] = user_agent + @headers['Host'] = @url.host + @headers['Date'] = Time.now.utc.httpdate + @headers['Accept-Encoding'] = 'gzip' if @verb != :head end def set_digest! -- cgit From 7467361d706e38aa53b6bd2fcb919153327175ed Mon Sep 17 00:00:00 2001 From: ThibG Date: Sat, 12 May 2018 16:48:32 +0200 Subject: Fetch boosted statuses on behalf of a follower (fixes #7426) (#7459) When an ActivityPub Announce is processed and the boosted toot is not known, fetch it on behalf of one of the booster's followers. This is to allow fetching self-boosts of previously-unknown private toots. If fetching on behalf of a user fails, try fetching it anonymously: the selected follower of a boosting user may be banned by the boosted toot's author. --- app/helpers/jsonld_helper.rb | 15 ++++++++++----- app/lib/activitypub/activity/announce.rb | 2 +- app/services/activitypub/fetch_remote_status_service.rb | 4 ++-- 3 files changed, 13 insertions(+), 8 deletions(-) (limited to 'app/lib') diff --git a/app/helpers/jsonld_helper.rb b/app/helpers/jsonld_helper.rb index e9056166c..9d2b6cf00 100644 --- a/app/helpers/jsonld_helper.rb +++ b/app/helpers/jsonld_helper.rb @@ -52,18 +52,22 @@ module JsonLdHelper graph.dump(:normalize) end - def fetch_resource(uri, id) + def fetch_resource(uri, id, on_behalf_of = nil) unless id - json = fetch_resource_without_id_validation(uri) + json = fetch_resource_without_id_validation(uri, on_behalf_of) return unless json uri = json['id'] end - json = fetch_resource_without_id_validation(uri) + json = fetch_resource_without_id_validation(uri, on_behalf_of) json.present? && json['id'] == uri ? json : nil end - def fetch_resource_without_id_validation(uri) + def fetch_resource_without_id_validation(uri, on_behalf_of = nil) + build_request(uri, on_behalf_of).perform do |response| + return body_to_json(response.body_with_limit) if response.code == 200 + end + # If request failed, retry without doing it on behalf of a user build_request(uri).perform do |response| response.code == 200 ? body_to_json(response.body_with_limit) : nil end @@ -85,8 +89,9 @@ module JsonLdHelper private - def build_request(uri) + def build_request(uri, on_behalf_of = nil) request = Request.new(:get, uri) + request.on_behalf_of(on_behalf_of) if on_behalf_of request.add_headers('Accept' => 'application/activity+json, application/ld+json') request end diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index 7e146ea8c..f810c88a2 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -30,7 +30,7 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity if object_uri.start_with?('http') return if ActivityPub::TagManager.instance.local_uri?(object_uri) - ActivityPub::FetchRemoteStatusService.new.call(object_uri, id: true) + ActivityPub::FetchRemoteStatusService.new.call(object_uri, id: true, on_behalf_of: @account.followers.local.first) elsif @object['url'].present? ::FetchRemoteStatusService.new.call(@object['url']) end diff --git a/app/services/activitypub/fetch_remote_status_service.rb b/app/services/activitypub/fetch_remote_status_service.rb index b6c00a9e7..2b447abb3 100644 --- a/app/services/activitypub/fetch_remote_status_service.rb +++ b/app/services/activitypub/fetch_remote_status_service.rb @@ -4,9 +4,9 @@ class ActivityPub::FetchRemoteStatusService < BaseService include JsonLdHelper # Should be called when uri has already been checked for locality - def call(uri, id: true, prefetched_body: nil) + def call(uri, id: true, prefetched_body: nil, on_behalf_of: nil) @json = if prefetched_body.nil? - fetch_resource(uri, id) + fetch_resource(uri, id, on_behalf_of) else body_to_json(prefetched_body) end -- cgit From 55fd55714a374eaedfab457f7e7254f816911ff1 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Wed, 16 May 2018 19:29:45 +0900 Subject: Raise Mastodon::RaceConditionError if Redis lock failed (#7511) An explicit error allows user agents to know the error and Sidekiq to retry. --- app/controllers/media_proxy_controller.rb | 2 ++ app/lib/activitypub/activity/create.rb | 2 ++ app/lib/ostatus/activity/creation.rb | 2 ++ app/services/activitypub/process_account_service.rb | 2 ++ app/services/fetch_link_card_service.rb | 2 ++ app/services/resolve_account_service.rb | 2 ++ 6 files changed, 12 insertions(+) (limited to 'app/lib') diff --git a/app/controllers/media_proxy_controller.rb b/app/controllers/media_proxy_controller.rb index 155670837..d820b257e 100644 --- a/app/controllers/media_proxy_controller.rb +++ b/app/controllers/media_proxy_controller.rb @@ -8,6 +8,8 @@ class MediaProxyController < ApplicationController if lock.acquired? @media_attachment = MediaAttachment.remote.find(params[:id]) redownload! if @media_attachment.needs_redownload? && !reject_media? + else + raise Mastodon::RaceConditionError end end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 8d17a4ebe..ab1d63cd4 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -11,6 +11,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity if lock.acquired? @status = find_existing_status process_status if @status.nil? + else + raise Mastodon::RaceConditionError end end diff --git a/app/lib/ostatus/activity/creation.rb b/app/lib/ostatus/activity/creation.rb index dbccc8330..d3a303a0c 100644 --- a/app/lib/ostatus/activity/creation.rb +++ b/app/lib/ostatus/activity/creation.rb @@ -15,6 +15,8 @@ class OStatus::Activity::Creation < OStatus::Activity::Base @status = find_status(id) return [@status, false] unless @status.nil? @status = process_status + else + raise Mastodon::RaceConditionError end end diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index 783bbd8e5..453253db4 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -23,6 +23,8 @@ class ActivityPub::ProcessAccountService < BaseService create_account if @account.nil? update_account process_tags + else + raise Mastodon::RaceConditionError end end diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index f9b1b2f0c..86d0f9971 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -23,6 +23,8 @@ class FetchLinkCardService < BaseService if lock.acquired? @card = PreviewCard.find_by(url: @url) process_url if @card.nil? || @card.updated_at <= 2.weeks.ago + else + raise Mastodon::RaceConditionError end end diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb index de8d1151d..4323e7f06 100644 --- a/app/services/resolve_account_service.rb +++ b/app/services/resolve_account_service.rb @@ -49,6 +49,8 @@ class ResolveAccountService < BaseService else handle_ostatus end + else + raise Mastodon::RaceConditionError end end -- cgit From 919eef309820a421d6f5886b8ae811d3924cea97 Mon Sep 17 00:00:00 2001 From: MIYAGI Hikaru Date: Fri, 18 May 2018 08:47:22 +0900 Subject: User agent for WebFinger (#7531) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * User agent for WebFinger * local_domain → web_domain * 'http' is away accidentally... --- app/lib/request.rb | 6 +----- config/initializers/http_client_proxy.rb | 3 ++- lib/mastodon/version.rb | 4 ++++ 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'app/lib') diff --git a/app/lib/request.rb b/app/lib/request.rb index 731bf7687..397614fac 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -58,7 +58,7 @@ class Request def set_common_headers! @headers[REQUEST_TARGET] = "#{@verb} #{@url.path}" - @headers['User-Agent'] = user_agent + @headers['User-Agent'] = Mastodon::Version.user_agent @headers['Host'] = @url.host @headers['Date'] = Time.now.utc.httpdate @headers['Accept-Encoding'] = 'gzip' if @verb != :head @@ -83,10 +83,6 @@ class Request @headers.keys.join(' ').downcase end - def user_agent - @user_agent ||= "#{HTTP::Request::USER_AGENT} (Mastodon/#{Mastodon::Version}; +#{root_url})" - end - def key_id case @key_id_format when :acct diff --git a/config/initializers/http_client_proxy.rb b/config/initializers/http_client_proxy.rb index f5026d59e..52c595c5d 100644 --- a/config/initializers/http_client_proxy.rb +++ b/config/initializers/http_client_proxy.rb @@ -18,7 +18,8 @@ module Goldfinger def self.finger(uri, opts = {}) to_hidden = /\.(onion|i2p)(:\d+)?$/.match(uri) raise Mastodon::HostValidationError, 'Instance does not support hidden service connections' if !Rails.configuration.x.access_to_hidden_service && to_hidden - opts = opts.merge(Rails.configuration.x.http_client_proxy).merge(ssl: !to_hidden) + opts = { ssl: !to_hidden, headers: {} }.merge(Rails.configuration.x.http_client_proxy).merge(opts) + opts[:headers]['User-Agent'] ||= Mastodon::Version.user_agent Goldfinger::Client.new(uri, opts).finger end end diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 697f317d8..874dfedb7 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -48,5 +48,9 @@ module Mastodon source_base_url end end + + def user_agent + @user_agent ||= "#{HTTP::Request::USER_AGENT} (Mastodon/#{Version}; +http#{Rails.configuration.x.use_https ? 's' : ''}://#{Rails.configuration.x.web_domain}/)" + end end end -- cgit From 1e02dc871533de78174b48a6a527f11b0f2bc7ec Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 18 May 2018 02:26:51 +0200 Subject: Add preference to hide following/followers lists (#7532) * Add preference to hide following/followers lists - Public pages - ActivityPub collections (does not return pages but does give total) - REST API (unless it's your own) (does not federate) Fix #6901 * Add preference * Add delegation * Fix issue * Fix issue --- .../api/v1/accounts/follower_accounts_controller.rb | 2 ++ .../api/v1/accounts/following_accounts_controller.rb | 2 ++ app/controllers/follower_accounts_controller.rb | 4 ++++ app/controllers/following_accounts_controller.rb | 4 ++++ app/controllers/settings/preferences_controller.rb | 1 + app/javascript/styles/mastodon/accounts.scss | 13 +++++++++++-- app/javascript/styles/mastodon/footer.scss | 2 +- app/lib/user_settings_decorator.rb | 5 +++++ app/models/account.rb | 1 + app/models/user.rb | 6 +++++- app/views/accounts/_follow_grid.html.haml | 3 ++- app/views/accounts/_follow_grid_hidden.html.haml | 3 +++ app/views/follower_accounts/index.html.haml | 5 ++++- app/views/following_accounts/index.html.haml | 5 ++++- app/views/layouts/public.html.haml | 4 ++-- app/views/settings/preferences/show.html.haml | 3 +++ config/locales/en.yml | 1 + config/locales/simple_form.en.yml | 2 ++ config/settings.yml | 1 + 19 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 app/views/accounts/_follow_grid_hidden.html.haml (limited to 'app/lib') diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index c4f600c54..4578cf6ca 100644 --- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb @@ -19,6 +19,8 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController end def load_accounts + return [] if @account.user_hides_network? && current_account.id != @account.id + default_accounts.merge(paginated_follows).to_a end diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb index 90b1f7fc5..ce2bbda85 100644 --- a/app/controllers/api/v1/accounts/following_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb @@ -19,6 +19,8 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController end def load_accounts + return [] if @account.user_hides_network? && current_account.id != @account.id + default_accounts.merge(paginated_follows).to_a end diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb index ac0d4c54e..99cb3676f 100644 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@ -6,11 +6,15 @@ class FollowerAccountsController < ApplicationController def index respond_to do |format| format.html do + next if @account.user_hides_network? + follows @relationships = AccountRelationshipsPresenter.new(follows.map(&:account_id), current_user.account_id) if user_signed_in? end format.json do + raise Mastodon::NotPermittedError if params[:page].present? && @account.user_hides_network? + render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb index 974d95c8e..03c4b1046 100644 --- a/app/controllers/following_accounts_controller.rb +++ b/app/controllers/following_accounts_controller.rb @@ -6,11 +6,15 @@ class FollowingAccountsController < ApplicationController def index respond_to do |format| format.html do + next if @account.user_hides_network? + follows @relationships = AccountRelationshipsPresenter.new(follows.map(&:target_account_id), current_user.account_id) if user_signed_in? end format.json do + raise Mastodon::NotPermittedError if params[:page].present? && @account.user_hides_network? + render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index 839763138..57793d776 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -44,6 +44,7 @@ class Settings::PreferencesController < ApplicationController :setting_system_font_ui, :setting_noindex, :setting_theme, + :setting_hide_network, notification_emails: %i(follow follow_request reblog favourite mention digest), interactions: %i(must_be_follower must_be_following) ) diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss index b063ca52d..93aa134cf 100644 --- a/app/javascript/styles/mastodon/accounts.scss +++ b/app/javascript/styles/mastodon/accounts.scss @@ -322,6 +322,15 @@ z-index: 2; position: relative; + &.empty img { + position: absolute; + opacity: 0.2; + height: 200px; + left: 0; + bottom: 0; + pointer-events: none; + } + @media screen and (max-width: 740px) { border-radius: 0; box-shadow: none; @@ -438,8 +447,8 @@ font-size: 14px; font-weight: 500; text-align: center; - padding: 60px 0; - padding-top: 55px; + padding: 130px 0; + padding-top: 125px; margin: 0 auto; cursor: default; } diff --git a/app/javascript/styles/mastodon/footer.scss b/app/javascript/styles/mastodon/footer.scss index ba2a06954..dd3c1b688 100644 --- a/app/javascript/styles/mastodon/footer.scss +++ b/app/javascript/styles/mastodon/footer.scss @@ -4,7 +4,7 @@ font-size: 12px; color: $darker-text-color; - .domain { + .footer__domain { font-weight: 500; a { diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb index 9260a81bc..a82f8974b 100644 --- a/app/lib/user_settings_decorator.rb +++ b/app/lib/user_settings_decorator.rb @@ -28,6 +28,7 @@ class UserSettingsDecorator user.settings['system_font_ui'] = system_font_ui_preference if change?('setting_system_font_ui') user.settings['noindex'] = noindex_preference if change?('setting_noindex') user.settings['theme'] = theme_preference if change?('setting_theme') + user.settings['hide_network'] = hide_network_preference if change?('setting_hide_network') end def merged_notification_emails @@ -78,6 +79,10 @@ class UserSettingsDecorator boolean_cast_setting 'setting_noindex' end + def hide_network_preference + boolean_cast_setting 'setting_hide_network' + end + def theme_preference settings['setting_theme'] end diff --git a/app/models/account.rb b/app/models/account.rb index 2b3ef5cdc..72e850aa7 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -136,6 +136,7 @@ class Account < ApplicationRecord :moderator?, :staff?, :locale, + :hides_network?, to: :user, prefix: true, allow_nil: true diff --git a/app/models/user.rb b/app/models/user.rb index 21c217e77..cfbae58ed 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -86,7 +86,7 @@ class User < ApplicationRecord has_many :session_activations, dependent: :destroy delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :delete_modal, - :reduce_motion, :system_font_ui, :noindex, :theme, :display_sensitive_media, + :reduce_motion, :system_font_ui, :noindex, :theme, :display_sensitive_media, :hide_network, to: :settings, prefix: :setting, allow_nil: false attr_accessor :invite_code @@ -219,6 +219,10 @@ class User < ApplicationRecord settings.notification_emails['digest'] end + def hides_network? + @hides_network ||= settings.hide_network + end + def token_for_app(a) return nil if a.nil? || a.owner != self Doorkeeper::AccessToken diff --git a/app/views/accounts/_follow_grid.html.haml b/app/views/accounts/_follow_grid.html.haml index a6d0ee817..fdcef84be 100644 --- a/app/views/accounts/_follow_grid.html.haml +++ b/app/views/accounts/_follow_grid.html.haml @@ -1,5 +1,6 @@ -.accounts-grid +.accounts-grid{ class: accounts.empty? ? 'empty' : '' } - if accounts.empty? + = image_tag asset_pack_path('elephant_ui_greeting.svg'), alt: '', role: 'presentational' = render partial: 'accounts/nothing_here' - else = render partial: 'accounts/grid_card', collection: accounts, as: :account, cached: !user_signed_in? diff --git a/app/views/accounts/_follow_grid_hidden.html.haml b/app/views/accounts/_follow_grid_hidden.html.haml new file mode 100644 index 000000000..e970350e6 --- /dev/null +++ b/app/views/accounts/_follow_grid_hidden.html.haml @@ -0,0 +1,3 @@ +.accounts-grid.empty + = image_tag asset_pack_path('elephant_ui_greeting.svg'), alt: '', role: 'presentational' + %p.nothing-here= t('accounts.network_hidden') diff --git a/app/views/follower_accounts/index.html.haml b/app/views/follower_accounts/index.html.haml index a24e4ea20..65af81a5b 100644 --- a/app/views/follower_accounts/index.html.haml +++ b/app/views/follower_accounts/index.html.haml @@ -7,4 +7,7 @@ = render 'accounts/header', account: @account -= render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:account) +- if @account.user_hides_network? + = render 'accounts/follow_grid_hidden' +- else + = render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:account) diff --git a/app/views/following_accounts/index.html.haml b/app/views/following_accounts/index.html.haml index 67f6cfede..8fd95a0b4 100644 --- a/app/views/following_accounts/index.html.haml +++ b/app/views/following_accounts/index.html.haml @@ -7,4 +7,7 @@ = render 'accounts/header', account: @account -= render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:target_account) +- if @account.user_hides_network? + = render 'accounts/follow_grid_hidden' +- else + = render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:target_account) diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml index be9648561..63cc3c7a7 100644 --- a/app/views/layouts/public.html.haml +++ b/app/views/layouts/public.html.haml @@ -8,9 +8,9 @@ %span.single-user-login = link_to t('auth.login'), new_user_session_path — - %span.domain= link_to site_hostname, about_path + %span.footer__domain= link_to site_hostname, about_path - else - %span.domain= link_to site_hostname, root_path + %span.footer__domain= link_to site_hostname, root_path %span.powered-by != t('generic.powered_by', link: link_to('Mastodon', 'https://joinmastodon.org')) diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml index fd66e13fb..d2e866373 100644 --- a/app/views/settings/preferences/show.html.haml +++ b/app/views/settings/preferences/show.html.haml @@ -26,6 +26,9 @@ .fields-group = f.input :setting_noindex, as: :boolean, wrapper: :with_label + .fields-group + = f.input :setting_hide_network, as: :boolean, wrapper: :with_label + %h4= t 'preferences.web' .fields-group diff --git a/config/locales/en.yml b/config/locales/en.yml index c074fa5b0..0257241cf 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -40,6 +40,7 @@ en: following: Following media: Media moved_html: "%{name} has moved to %{new_profile_link}:" + network_hidden: This information is not available nothing_here: There is nothing here! people_followed_by: People whom %{name} follows people_who_follow: People who follow %{name} diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 7d6907ff5..85597e9a7 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -15,6 +15,7 @@ en: note: one: 1 character left other: %{count} characters left + setting_hide_network: Who you follow and who follows you will not be shown on your profile setting_noindex: Affects your public profile and status pages setting_theme: Affects how Mastodon looks when you're logged in from any device. imports: @@ -54,6 +55,7 @@ en: setting_default_sensitive: Always mark media as sensitive setting_delete_modal: Show confirmation dialog before deleting a toot setting_display_sensitive_media: Always show media marked as sensitive + setting_hide_network: Hide your network setting_noindex: Opt-out of search engine indexing setting_reduce_motion: Reduce motion in animations setting_system_font_ui: Use system's default font diff --git a/config/settings.yml b/config/settings.yml index dcf655008..3581d10a2 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -20,6 +20,7 @@ defaults: &defaults timeline_preview: true show_staff_badge: true default_sensitive: false + hide_network: false unfollow_modal: false boost_modal: false delete_modal: true -- cgit From 57b503d4ef0754e4651eae26b628cba60e1ab4e9 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 18 May 2018 11:33:56 +0200 Subject: Resolve unknown status from Add activity, skip Remove if unknown (#7526) Fix #7518 --- app/lib/activitypub/activity.rb | 9 +++++++++ app/lib/activitypub/activity/add.rb | 5 +++-- app/lib/activitypub/activity/announce.rb | 10 ---------- app/lib/activitypub/activity/remove.rb | 2 +- spec/lib/activitypub/activity/add_spec.rb | 25 ++++++++++++++++++++++--- 5 files changed, 35 insertions(+), 16 deletions(-) (limited to 'app/lib') diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 84d4b1752..03476920b 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -118,4 +118,13 @@ class ActivityPub::Activity def delete_later!(uri) redis.setex("delete_upon_arrival:#{@account.id}:#{uri}", 6.hours.seconds, uri) end + + def fetch_remote_original_status + if object_uri.start_with?('http') + return if ActivityPub::TagManager.instance.local_uri?(object_uri) + ActivityPub::FetchRemoteStatusService.new.call(object_uri, id: true, on_behalf_of: @account.followers.local.first) + elsif @object['url'].present? + ::FetchRemoteStatusService.new.call(@object['url']) + end + end end diff --git a/app/lib/activitypub/activity/add.rb b/app/lib/activitypub/activity/add.rb index ea94d2f98..688ab00b3 100644 --- a/app/lib/activitypub/activity/add.rb +++ b/app/lib/activitypub/activity/add.rb @@ -4,9 +4,10 @@ class ActivityPub::Activity::Add < ActivityPub::Activity def perform return unless @json['target'].present? && value_or_id(@json['target']) == @account.featured_collection_url - status = status_from_uri(object_uri) + status = status_from_uri(object_uri) + status ||= fetch_remote_original_status - return unless status.account_id == @account.id && !@account.pinned?(status) + return unless !status.nil? && status.account_id == @account.id && !@account.pinned?(status) StatusPin.create!(account: @account, status: status) end diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index f810c88a2..1147a4481 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -26,16 +26,6 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity private - def fetch_remote_original_status - if object_uri.start_with?('http') - return if ActivityPub::TagManager.instance.local_uri?(object_uri) - - ActivityPub::FetchRemoteStatusService.new.call(object_uri, id: true, on_behalf_of: @account.followers.local.first) - elsif @object['url'].present? - ::FetchRemoteStatusService.new.call(@object['url']) - end - end - def announceable?(status) status.account_id == @account.id || status.public_visibility? || status.unlisted_visibility? end diff --git a/app/lib/activitypub/activity/remove.rb b/app/lib/activitypub/activity/remove.rb index 62a1e3196..f523ead9f 100644 --- a/app/lib/activitypub/activity/remove.rb +++ b/app/lib/activitypub/activity/remove.rb @@ -6,7 +6,7 @@ class ActivityPub::Activity::Remove < ActivityPub::Activity status = status_from_uri(object_uri) - return unless status.account_id == @account.id + return unless !status.nil? && status.account_id == @account.id pin = StatusPin.find_by(account: @account, status: status) pin&.destroy! diff --git a/spec/lib/activitypub/activity/add_spec.rb b/spec/lib/activitypub/activity/add_spec.rb index 3ebab4e37..16db71c88 100644 --- a/spec/lib/activitypub/activity/add_spec.rb +++ b/spec/lib/activitypub/activity/add_spec.rb @@ -18,12 +18,31 @@ RSpec.describe ActivityPub::Activity::Add do describe '#perform' do subject { described_class.new(json, sender) } - before do + it 'creates a pin' do subject.perform + expect(sender.pinned?(status)).to be true end - it 'creates a pin' do - expect(sender.pinned?(status)).to be true + context 'when status was not known before' do + let(:json) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: 'foo', + type: 'Add', + actor: ActivityPub::TagManager.instance.uri_for(sender), + object: 'https://example.com/unknown', + target: sender.featured_collection_url, + }.with_indifferent_access + end + + before do + stub_request(:get, 'https://example.com/unknown').to_return(status: 410) + end + + it 'fetches the status' do + subject.perform + expect(a_request(:get, 'https://example.com/unknown')).to have_been_made.at_least_once + end end end end -- cgit From cdbdf7f98bb45439908cb23d0dfae228d59b3c1f Mon Sep 17 00:00:00 2001 From: ThibG Date: Fri, 25 May 2018 14:26:45 +0200 Subject: Ignore multiple occurrences of a hashtag within a status (fixes #7585) (#7606) --- app/lib/activitypub/activity/create.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/lib') diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index ab1d63cd4..010ed1bb5 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -80,7 +80,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity hashtag = tag['name'].gsub(/\A#/, '').mb_chars.downcase hashtag = Tag.where(name: hashtag).first_or_initialize(name: hashtag) - status.tags << hashtag + status.tags << hashtag unless status.tags.include?(hashtag) rescue ActiveRecord::RecordInvalid nil end -- cgit From ab36e0ef72a52e5cc184d63cda0fe411c8b4086a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 28 May 2018 05:21:04 +0200 Subject: Record trending tags from ActivityPub, too (#7647) --- app/lib/activitypub/activity/create.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'app/lib') diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 010ed1bb5..869749f1e 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -78,9 +78,12 @@ class ActivityPub::Activity::Create < ActivityPub::Activity return if tag['name'].blank? hashtag = tag['name'].gsub(/\A#/, '').mb_chars.downcase - hashtag = Tag.where(name: hashtag).first_or_initialize(name: hashtag) + hashtag = Tag.where(name: hashtag).first_or_create(name: hashtag) - status.tags << hashtag unless status.tags.include?(hashtag) + return if status.tags.include?(hashtag) + + status.tags << hashtag + TrendingTags.record_use!(hashtag, status.account, status.created_at) rescue ActiveRecord::RecordInvalid nil end -- cgit From 90908fc24ba57c877de75fe117b8cc234e29d4f0 Mon Sep 17 00:00:00 2001 From: abcang Date: Tue, 29 May 2018 20:34:02 +0900 Subject: Fix N+1 on AtomSerializer (#7669) --- app/lib/ostatus/atom_serializer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/lib') diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb index 698f2ee22..5c6ff4f9b 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.order(:id).each do |mentioned| + status.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 -- cgit