From 1e452a10b8284dd2626255f65e6ea79a2b9a8eb7 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 14 Jul 2021 05:35:49 +0200 Subject: [PATCH 1/4] Fix user email address being banned on self-deletion (#16503) * Add tests * Fix user email address being banned on self-deletion Fixes #16498 --- app/controllers/settings/deletes_controller.rb | 2 +- app/models/account.rb | 4 ++-- spec/controllers/settings/deletes_controller_spec.rb | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/controllers/settings/deletes_controller.rb b/app/controllers/settings/deletes_controller.rb index 7b8f8d2078..e0dd5edcb1 100644 --- a/app/controllers/settings/deletes_controller.rb +++ b/app/controllers/settings/deletes_controller.rb @@ -42,7 +42,7 @@ class Settings::DeletesController < Settings::BaseController end def destroy_account! - current_account.suspend!(origin: :local) + current_account.suspend!(origin: :local, block_email: false) AccountDeletionWorker.perform_async(current_user.account_id) sign_out end diff --git a/app/models/account.rb b/app/models/account.rb index 8be36bf5b8..a6d8d15374 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -232,11 +232,11 @@ class Account < ApplicationRecord suspended? && deletion_request.present? end - def suspend!(date: Time.now.utc, origin: :local) + def suspend!(date: Time.now.utc, origin: :local, block_email: true) transaction do create_deletion_request! update!(suspended_at: date, suspension_origin: origin) - create_canonical_email_block! + create_canonical_email_block! if block_email end end diff --git a/spec/controllers/settings/deletes_controller_spec.rb b/spec/controllers/settings/deletes_controller_spec.rb index 8d5c4774fd..92ab401c96 100644 --- a/spec/controllers/settings/deletes_controller_spec.rb +++ b/spec/controllers/settings/deletes_controller_spec.rb @@ -59,6 +59,10 @@ describe Settings::DeletesController do expect(user.account.reload).to be_suspended end + it 'does not create an email block' do + expect(CanonicalEmailBlock.block?(user.email)).to be false + end + context 'when suspended' do let(:user) { Fabricate(:user, account_attributes: { username: 'alice', suspended_at: Time.now.utc }) } From 1d79ecf72930c67613f471d1a605d7845570f742 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 14 Jul 2021 05:36:23 +0200 Subject: [PATCH 2/4] Fix minor code quality issues (#16502) --- app/javascript/mastodon/features/ui/components/video_modal.js | 2 +- app/javascript/mastodon/reducers/modal.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/javascript/mastodon/features/ui/components/video_modal.js b/app/javascript/mastodon/features/ui/components/video_modal.js index 7e8e1329d7..f3ee89dfd9 100644 --- a/app/javascript/mastodon/features/ui/components/video_modal.js +++ b/app/javascript/mastodon/features/ui/components/video_modal.js @@ -21,7 +21,7 @@ export default class VideoModal extends ImmutablePureComponent { }; componentDidMount () { - const { media, onChangeBackgroundColor, onClose } = this.props; + const { media, onChangeBackgroundColor } = this.props; const backgroundColor = getAverageFromBlurhash(media.get('blurhash')); diff --git a/app/javascript/mastodon/reducers/modal.js b/app/javascript/mastodon/reducers/modal.js index ea81b43323..c43446f6d5 100644 --- a/app/javascript/mastodon/reducers/modal.js +++ b/app/javascript/mastodon/reducers/modal.js @@ -5,11 +5,11 @@ import { Stack as ImmutableStack, Map as ImmutableMap } from 'immutable'; export default function modal(state = ImmutableStack(), action) { switch(action.type) { case MODAL_OPEN: - return state.unshift(ImmutableMap({ modalType: action.modalType, modalProps: action.modalProps })); + return state.unshift(ImmutableMap({ modalType: action.modalType, modalProps: action.modalProps })); case MODAL_CLOSE: return (action.modalType === undefined || action.modalType === state.getIn([0, 'modalType'])) ? state.shift() : state; case TIMELINE_DELETE: - return state.filterNot((modal) => modal.get('modalProps').statusId === action.id); + return state.filterNot((modal) => modal.get('modalProps').statusId === action.id); default: return state; } From 9c1d3086af901aedc28e719833ace3a6e7db4c36 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 15 Jul 2021 15:56:58 +0200 Subject: [PATCH 3/4] Fix inefficiencies in auto-linking code (#16506) The auto-linking code basically rewrote the whole string escaping non-ascii characters in an inefficient way, and building a full character offset map between the unescaped and escaped texts before sending the contents to TwitterText's extractor. Instead of doing that, this commit changes the TwitterText regexps to include valid IRI characters in addition to valid URI characters. --- app/lib/formatter.rb | 31 +--------------------------- config/initializers/twitter_regex.rb | 4 ++++ 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index fd65375262..1610f36892 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -214,39 +214,10 @@ class Formatter result.flatten.join end - UNICODE_ESCAPE_BLACKLIST_RE = /\p{Z}|\p{P}/ - def utf8_friendly_extractor(text, options = {}) - old_to_new_index = [0] - - escaped = text.chars.map do |c| - output = begin - if c.ord.to_s(16).length > 2 && !UNICODE_ESCAPE_BLACKLIST_RE.match?(c) - CGI.escape(c) - else - c - end - end - - old_to_new_index << old_to_new_index.last + output.length - - output - end.join - # Note: I couldn't obtain list_slug with @user/list-name format # for mention so this requires additional check - special = Extractor.extract_urls_with_indices(escaped, options).map do |extract| - new_indices = [ - old_to_new_index.find_index(extract[:indices].first), - old_to_new_index.find_index(extract[:indices].last), - ] - - next extract.merge( - indices: new_indices, - url: text[new_indices.first..new_indices.last - 1] - ) - end - + special = Extractor.extract_urls_with_indices(text, options) standard = Extractor.extract_entities_with_indices(text, options) extra = Extractor.extract_extra_uris_with_indices(text, options) diff --git a/config/initializers/twitter_regex.rb b/config/initializers/twitter_regex.rb index 3ff2aa9e5d..84c09ff35c 100644 --- a/config/initializers/twitter_regex.rb +++ b/config/initializers/twitter_regex.rb @@ -24,6 +24,10 @@ module Twitter::TwitterText ) \) /iox + REGEXEN[:valid_iri_ucschar] = /[\u{A0}-\u{D7FF}\u{F900}-\u{FDCF}\u{FDF0}-\u{FFEF}\u{10000}-\u{1FFFD}\u{20000}-\u{2FFFD}\u{30000}-\u{3FFFD}\u{40000}-\u{4FFFD}\u{50000}-\u{5FFFD}\u{60000}-\u{6FFFD}\u{70000}-\u{7FFFD}\u{80000}-\u{8FFFD}\u{90000}-\u{9FFFD}\u{A0000}-\u{AFFFD}\u{B0000}-\u{BFFFD}\u{C0000}-\u{CFFFD}\u{D0000}-\u{DFFFD}\u{E1000}-\u{EFFFD}]/iou + REGEXEN[:valid_iri_iprivate] = /[\u{E000}-\u{F8FF}\u{F0000}-\u{FFFFD}\u{100000}-\u{10FFFD}]/iou + REGEXEN[:valid_url_query_chars] = /(?:#{REGEXEN[:valid_iri_ucschar]})|(?:#{REGEXEN[:valid_iri_iprivate]})|[a-z0-9!?\*'\(\);:&=\+\$\/%#\[\]\-_\.,~|@]/iou + REGEXEN[:valid_url_query_ending_chars] = /(?:#{REGEXEN[:valid_iri_ucschar]})|(?:#{REGEXEN[:valid_iri_iprivate]})|[a-z0-9_&=#\/\-]/iou REGEXEN[:valid_url_path] = /(?: (?: #{REGEXEN[:valid_general_url_path_chars]}* From 4235b0d0315680666de04b9ca2e5b8ac5cf1ec69 Mon Sep 17 00:00:00 2001 From: Claire Date: Sat, 17 Jul 2021 17:06:52 +0200 Subject: [PATCH 4/4] Fix replying from modal (#16516) Fixes #16515 Not using a router object somehow made `this.history` lag behind the real browser history whenever pushing a new history item in `replyCompose`. Not using the context-provided router in this case was an oversight made when porting glitch-soc changes in #16499. --- app/javascript/mastodon/components/modal_root.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/javascript/mastodon/components/modal_root.js b/app/javascript/mastodon/components/modal_root.js index 8c9409d014..755c46fd6b 100644 --- a/app/javascript/mastodon/components/modal_root.js +++ b/app/javascript/mastodon/components/modal_root.js @@ -6,6 +6,10 @@ import { multiply } from 'color-blend'; export default class ModalRoot extends React.PureComponent { + static contextTypes = { + router: PropTypes.object, + }; + static propTypes = { children: PropTypes.node, onClose: PropTypes.func.isRequired,