From 11c3ceb56e11b7b5816bc2559eab370355941ad1 Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 20 Mar 2019 17:20:16 +0100 Subject: [PATCH 1/2] Do not try fetching keys of unknown accounts on a Delete from them (#10326) --- .../activitypub/inboxes_controller.rb | 16 +++++++++++++--- .../activitypub/inboxes_controller_spec.rb | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/app/controllers/activitypub/inboxes_controller.rb b/app/controllers/activitypub/inboxes_controller.rb index 8f5e1887ea..1501b914ec 100644 --- a/app/controllers/activitypub/inboxes_controller.rb +++ b/app/controllers/activitypub/inboxes_controller.rb @@ -2,11 +2,14 @@ class ActivityPub::InboxesController < Api::BaseController include SignatureVerification + include JsonLdHelper before_action :set_account def create - if signed_request_account + if unknown_deleted_account? + head 202 + elsif signed_request_account upgrade_account process_payload head 202 @@ -17,12 +20,19 @@ class ActivityPub::InboxesController < Api::BaseController private + def unknown_deleted_account? + json = Oj.load(body, mode: :strict) + json['type'] == 'Delete' && json['actor'].present? && json['actor'] == value_or_id(json['object']) && !Account.where(uri: json['actor']).exists? + rescue Oj::ParseError + false + end + def set_account @account = Account.find_local!(params[:account_username]) if params[:account_username] end def body - @body ||= request.body.read + @body ||= request.body.read.force_encoding('UTF-8') end def upgrade_account @@ -36,6 +46,6 @@ class ActivityPub::InboxesController < Api::BaseController end def process_payload - ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body.force_encoding('UTF-8'), @account&.id) + ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body, @account&.id) end end diff --git a/spec/controllers/activitypub/inboxes_controller_spec.rb b/spec/controllers/activitypub/inboxes_controller_spec.rb index 4055d93424..eab4b8c3e6 100644 --- a/spec/controllers/activitypub/inboxes_controller_spec.rb +++ b/spec/controllers/activitypub/inboxes_controller_spec.rb @@ -10,7 +10,7 @@ RSpec.describe ActivityPub::InboxesController, type: :controller do Fabricate(:account) end - post :create + post :create, body: '{}' expect(response).to have_http_status(202) end end @@ -21,7 +21,7 @@ RSpec.describe ActivityPub::InboxesController, type: :controller do false end - post :create + post :create, body: '{}' expect(response).to have_http_status(401) end end From 2a211ff18cc023aa1fe81128cdcee547046df920 Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 20 Mar 2019 17:29:12 +0100 Subject: [PATCH 2/2] Add support for custom emojis in poll options (#10322) * Backend changes for custom emoji support in poll options * Serialize poll emojis in REST API * Render custom emojis in poll options * Render custom emoji in poll options on public pages --- .../mastodon/actions/importer/normalizer.js | 4 +++- app/javascript/mastodon/components/poll.js | 13 ++++++++++++- app/lib/formatter.rb | 6 ++++++ app/models/poll.rb | 4 ++++ app/models/status.rb | 6 +++++- app/serializers/rest/poll_serializer.rb | 1 + app/views/stream_entries/_detailed_status.html.haml | 2 +- app/views/stream_entries/_poll.html.haml | 4 ++-- app/views/stream_entries/_simple_status.html.haml | 2 +- 9 files changed, 35 insertions(+), 7 deletions(-) diff --git a/app/javascript/mastodon/actions/importer/normalizer.js b/app/javascript/mastodon/actions/importer/normalizer.js index ea80c0efb3..5badb0c49e 100644 --- a/app/javascript/mastodon/actions/importer/normalizer.js +++ b/app/javascript/mastodon/actions/importer/normalizer.js @@ -71,9 +71,11 @@ export function normalizeStatus(status, normalOldStatus) { export function normalizePoll(poll) { const normalPoll = { ...poll }; + const emojiMap = makeEmojiMap(normalPoll); + normalPoll.options = poll.options.map(option => ({ ...option, - title_emojified: emojify(escapeTextContentForBrowser(option.title)), + title_emojified: emojify(escapeTextContentForBrowser(option.title), emojiMap), })); return normalPoll; diff --git a/app/javascript/mastodon/components/poll.js b/app/javascript/mastodon/components/poll.js index a1b297ce75..56331cb290 100644 --- a/app/javascript/mastodon/components/poll.js +++ b/app/javascript/mastodon/components/poll.js @@ -44,6 +44,11 @@ const timeRemainingString = (intl, date, now) => { return relativeTime; }; +const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => { + obj[`:${emoji.get('shortcode')}:`] = emoji.toJS(); + return obj; +}, {}); + export default @injectIntl class Poll extends ImmutablePureComponent { @@ -99,6 +104,12 @@ class Poll extends ImmutablePureComponent { const active = !!this.state.selected[`${optionIndex}`]; const showResults = poll.get('voted') || poll.get('expired'); + let titleEmojified = option.get('title_emojified'); + if (!titleEmojified) { + const emojiMap = makeEmojiMap(poll); + titleEmojified = emojify(escapeTextContentForBrowser(option.get('title')), emojiMap); + } + return (
  • {showResults && ( @@ -122,7 +133,7 @@ class Poll extends ImmutablePureComponent { {!showResults && } {showResults && {Math.round(percent)}%} - +
  • ); diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 464e1ee7e8..aadf03b2ac 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -71,6 +71,12 @@ class Formatter html.html_safe # rubocop:disable Rails/OutputSafety end + def format_poll_option(status, option, **options) + html = encode(option.title) + html = encode_custom_emojis(html, status.emojis, options[:autoplay]) + html.html_safe # rubocop:disable Rails/OutputSafety + end + def format_display_name(account, **options) html = encode(account.display_name.presence || account.username) html = encode_custom_emojis(html, account.emojis, options[:autoplay]) if options[:custom_emojify] diff --git a/app/models/poll.rb b/app/models/poll.rb index 6df2303370..8f72c7b112 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -60,6 +60,10 @@ class Poll < ApplicationRecord !local? end + def emojis + @emojis ||= CustomEmoji.from_text(options.join(' '), account.domain) + end + class Option < ActiveModelSerializers::Model attributes :id, :title, :votes_count, :poll diff --git a/app/models/status.rb b/app/models/status.rb index b9479c76be..d3fb83ccaa 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -213,7 +213,11 @@ class Status < ApplicationRecord end def emojis - @emojis ||= CustomEmoji.from_text([spoiler_text, text].join(' '), account.domain) + return @emojis if defined?(@emojis) + fields = [spoiler_text, text] + fields += owned_poll.options unless owned_poll.nil? + @emojis = CustomEmoji.from_text(fields.join(' '), account.domain) + @emojis end def mark_for_mass_destruction! diff --git a/app/serializers/rest/poll_serializer.rb b/app/serializers/rest/poll_serializer.rb index 4dae1c09f4..356c45b838 100644 --- a/app/serializers/rest/poll_serializer.rb +++ b/app/serializers/rest/poll_serializer.rb @@ -5,6 +5,7 @@ class REST::PollSerializer < ActiveModel::Serializer :multiple, :votes_count has_many :loaded_options, key: :options + has_many :emojis, serializer: REST::CustomEmojiSerializer attribute :voted, if: :current_user? diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index b19d2452ad..d18ecd37a4 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -24,7 +24,7 @@ - if status.poll = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do - = render partial: 'stream_entries/poll', locals: { poll: status.poll } + = render partial: 'stream_entries/poll', locals: { status: status, poll: status.poll, autoplay: autoplay } - elsif !status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first diff --git a/app/views/stream_entries/_poll.html.haml b/app/views/stream_entries/_poll.html.haml index d6b2c0cd91..ba34890dfe 100644 --- a/app/views/stream_entries/_poll.html.haml +++ b/app/views/stream_entries/_poll.html.haml @@ -10,11 +10,11 @@ %label.poll__text>< %span.poll__number= percent.round - = option.title + = Formatter.instance.format_poll_option(status, option, autoplay: autoplay) - else %label.poll__text>< %span.poll__input{ class: poll.multiple? ? 'checkbox' : nil}>< - = option.title + = Formatter.instance.format_poll_option(status, option, autoplay: autoplay) .poll__footer - unless show_results %button.button.button-secondary{ disabled: true } diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml index 68e48edbb8..a499a86343 100644 --- a/app/views/stream_entries/_simple_status.html.haml +++ b/app/views/stream_entries/_simple_status.html.haml @@ -28,7 +28,7 @@ - if status.poll = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do - = render partial: 'stream_entries/poll', locals: { poll: status.poll } + = render partial: 'stream_entries/poll', locals: { status: status, poll: status.poll, autoplay: autoplay } - elsif !status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first