From b194caade4b6bd6b733cbeb2386ed2ee5e8bfc5c Mon Sep 17 00:00:00 2001 From: ThibG Date: Sun, 29 Dec 2019 05:39:08 +0100 Subject: [PATCH 01/44] Fix old migrations failing because of strong_migrations update (#12692) Fixes #12690 The `strong_migrations` update from f673e3d120fb5a2b08b5c30b9e0eefd46c722e8d introduced a check for `change_column_null` specific to Postgres. This rejects old migrations. This commit just wraps old migrations with `safety_assured` to bypass this check. Alternatives would have been to: - Disable that check entirely (a possibility added in that same `strong_migrations` version) for Mastodon, but it makes sense to write new migrations without such a strong lock. - Rewrite the old migrations to do it in a way that do not require an exclusive lock. I thought fixing those old migrations for performance wasn't worth the pain. Also, if I understand correctly, the next version of `strong_migrations` is going to include a helper to do that. We could update those migrations at that point. --- .../20170711225116_fix_null_booleans.rb | 20 ++++++++++--------- ...nonnullable_in_account_moderation_notes.rb | 6 ++++-- ..._change_account_id_nonnullable_in_lists.rb | 4 +++- ...ge_columns_in_notifications_nonnullable.rb | 10 ++++++---- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/db/migrate/20170711225116_fix_null_booleans.rb b/db/migrate/20170711225116_fix_null_booleans.rb index 5b319471d7..aabb81f217 100644 --- a/db/migrate/20170711225116_fix_null_booleans.rb +++ b/db/migrate/20170711225116_fix_null_booleans.rb @@ -1,17 +1,19 @@ class FixNullBooleans < ActiveRecord::Migration[5.1] def change - change_column_default :domain_blocks, :reject_media, false - change_column_null :domain_blocks, :reject_media, false, false + safety_assured do + change_column_default :domain_blocks, :reject_media, false + change_column_null :domain_blocks, :reject_media, false, false - change_column_default :imports, :approved, false - change_column_null :imports, :approved, false, false + change_column_default :imports, :approved, false + change_column_null :imports, :approved, false, false - change_column_null :statuses, :sensitive, false, false - change_column_null :statuses, :reply, false, false + change_column_null :statuses, :sensitive, false, false + change_column_null :statuses, :reply, false, false - change_column_null :users, :admin, false, false + change_column_null :users, :admin, false, false - change_column_default :users, :otp_required_for_login, false - change_column_null :users, :otp_required_for_login, false, false + change_column_default :users, :otp_required_for_login, false + change_column_null :users, :otp_required_for_login, false, false + end end end diff --git a/db/migrate/20171010025614_change_accounts_nonnullable_in_account_moderation_notes.rb b/db/migrate/20171010025614_change_accounts_nonnullable_in_account_moderation_notes.rb index 747e5a8269..1d7a0086c2 100644 --- a/db/migrate/20171010025614_change_accounts_nonnullable_in_account_moderation_notes.rb +++ b/db/migrate/20171010025614_change_accounts_nonnullable_in_account_moderation_notes.rb @@ -1,6 +1,8 @@ class ChangeAccountsNonnullableInAccountModerationNotes < ActiveRecord::Migration[5.1] def change - change_column_null :account_moderation_notes, :account_id, false - change_column_null :account_moderation_notes, :target_account_id, false + safety_assured do + change_column_null :account_moderation_notes, :account_id, false + change_column_null :account_moderation_notes, :target_account_id, false + end end end diff --git a/db/migrate/20171201000000_change_account_id_nonnullable_in_lists.rb b/db/migrate/20171201000000_change_account_id_nonnullable_in_lists.rb index 3369e3b9e9..ac86c9e777 100644 --- a/db/migrate/20171201000000_change_account_id_nonnullable_in_lists.rb +++ b/db/migrate/20171201000000_change_account_id_nonnullable_in_lists.rb @@ -1,5 +1,7 @@ class ChangeAccountIdNonnullableInLists < ActiveRecord::Migration[5.1] def change - change_column_null :lists, :account_id, false + safety_assured do + change_column_null :lists, :account_id, false + end end end diff --git a/db/migrate/20180310000000_change_columns_in_notifications_nonnullable.rb b/db/migrate/20180310000000_change_columns_in_notifications_nonnullable.rb index 05ffd05010..dba789207d 100644 --- a/db/migrate/20180310000000_change_columns_in_notifications_nonnullable.rb +++ b/db/migrate/20180310000000_change_columns_in_notifications_nonnullable.rb @@ -1,8 +1,10 @@ class ChangeColumnsInNotificationsNonnullable < ActiveRecord::Migration[5.1] def change - change_column_null :notifications, :activity_id, false - change_column_null :notifications, :activity_type, false - change_column_null :notifications, :account_id, false - change_column_null :notifications, :from_account_id, false + safety_assured do + change_column_null :notifications, :activity_id, false + change_column_null :notifications, :activity_type, false + change_column_null :notifications, :account_id, false + change_column_null :notifications, :from_account_id, false + end end end From 47b330df2a11eab58c898ca2da33172f96a74a71 Mon Sep 17 00:00:00 2001 From: Matt Panaro Date: Sat, 28 Dec 2019 23:39:48 -0500 Subject: [PATCH 02/44] =?UTF-8?q?Summary:=20fix=20slowness=20due=20to=20la?= =?UTF-8?q?yout=20thrashing=20when=20reloading=20a=20large=20=E2=80=A6=20(?= =?UTF-8?q?#12661)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Summary: fix slowness due to layout thrashing when reloading a large set of status updates in order to limit the maximum size of a status in a list view (e.g. the home timeline), so as to avoid having to scroll all the way through an abnormally large status update (see https://github.com/tootsuite/mastodon/pull/8205), the following steps are taken: •the element containing the status is rendered in the browser •its height is calculated, to determine if it exceeds the maximum height threshold. Unfortunately for performance, these steps are carried out in the componentDidMount(/Update) method, which also performs style modifications on the element. The combination of height request and style modification during javascript evaluation in the browser leads to layout-thrashing, where the elements are repeatedly re-laid-out (see https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing & https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Performance_best_practices_for_Firefox_fe_engineers). The solution implemented here is to memoize the collapsed state in Redux the first time the status is seen (e.g. when fetched as part of a small batch, to populate the home timeline) , so that on subsequent re-renders, the value can be queried, rather than recalculated. This strategy is derived from https://github.com/tootsuite/mastodon/pull/4439 & https://github.com/tootsuite/mastodon/pull/4909, and should resolve https://github.com/tootsuite/mastodon/issues/12455. Andrew Lin (https://github.com/onethreeseven) is thanked for his assistance in root cause analysis and solution brainstorming * remove getSnapshotBeforeUpdate from status * remove componentWillUnmount from status * persist last-intersected status update and restore when ScrollableList is restored e.g. when navigating from home-timeline to a status conversational thread and ({ + type: CURRENTLY_VIEWING, + timeline, + id, +}); + export const loadPending = timeline => ({ type: TIMELINE_LOAD_PENDING, timeline, diff --git a/app/javascript/mastodon/components/intersection_observer_article.js b/app/javascript/mastodon/components/intersection_observer_article.js index e453730ba4..d475e5d1c0 100644 --- a/app/javascript/mastodon/components/intersection_observer_article.js +++ b/app/javascript/mastodon/components/intersection_observer_article.js @@ -20,6 +20,8 @@ export default class IntersectionObserverArticle extends React.Component { cachedHeight: PropTypes.number, onHeightChange: PropTypes.func, children: PropTypes.node, + currentlyViewing: PropTypes.number, + updateCurrentlyViewing: PropTypes.func, }; state = { @@ -48,6 +50,8 @@ export default class IntersectionObserverArticle extends React.Component { ); this.componentMounted = true; + + if(id === this.props.currentlyViewing) this.node.scrollIntoView(); } componentWillUnmount () { @@ -60,6 +64,8 @@ export default class IntersectionObserverArticle extends React.Component { handleIntersection = (entry) => { this.entry = entry; + if(entry.intersectionRatio > 0.75 && this.props.updateCurrentlyViewing) this.props.updateCurrentlyViewing(this.id); + scheduleIdleTask(this.calculateHeight); this.setState(this.updateStateAfterIntersection); } diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js index 421756803c..6338ccd5c5 100644 --- a/app/javascript/mastodon/components/scrollable_list.js +++ b/app/javascript/mastodon/components/scrollable_list.js @@ -36,6 +36,8 @@ export default class ScrollableList extends PureComponent { emptyMessage: PropTypes.node, children: PropTypes.node, bindToDocument: PropTypes.bool, + currentlyViewing: PropTypes.number, + updateCurrentlyViewing: PropTypes.func, }; static defaultProps = { @@ -309,6 +311,8 @@ export default class ScrollableList extends PureComponent { listLength={childrenCount} intersectionObserverWrapper={this.intersectionObserverWrapper} saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null} + currentlyViewing={this.props.currentlyViewing} + updateCurrentlyViewing={this.props.updateCurrentlyViewing} > {React.cloneElement(child, { getScrollPosition: this.getScrollPosition, diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index e120278a05..12fc4a9a6d 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -76,6 +76,7 @@ class Status extends ImmutablePureComponent { onEmbed: PropTypes.func, onHeightChange: PropTypes.func, onToggleHidden: PropTypes.func, + onToggleCollapsed: PropTypes.func, muted: PropTypes.bool, hidden: PropTypes.bool, unread: PropTypes.bool, @@ -107,14 +108,6 @@ class Status extends ImmutablePureComponent { this.didShowCard = !this.props.muted && !this.props.hidden && this.props.status && this.props.status.get('card'); } - getSnapshotBeforeUpdate () { - if (this.props.getScrollPosition) { - return this.props.getScrollPosition(); - } else { - return null; - } - } - static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.status && nextProps.status.get('id') !== prevState.statusId) { return { @@ -141,17 +134,6 @@ class Status extends ImmutablePureComponent { } } - componentWillUnmount() { - if (this.node && this.props.getScrollPosition) { - const position = this.props.getScrollPosition(); - if (position !== null && this.node.offsetTop < position.top) { - requestAnimationFrame(() => { - this.props.updateScrollBottom(position.height - position.top); - }); - } - } - } - handleToggleMediaVisibility = () => { this.setState({ showMedia: !this.state.showMedia }); } @@ -196,7 +178,11 @@ class Status extends ImmutablePureComponent { handleExpandedToggle = () => { this.props.onToggleHidden(this._properStatus()); - }; + } + + handleCollapsedToggle = isCollapsed => { + this.props.onToggleCollapsed(this._properStatus(), isCollapsed); + } renderLoadingMediaGallery () { return
; @@ -466,7 +452,7 @@ class Status extends ImmutablePureComponent {
- + {media} diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js index d13091325b..5d921fd412 100644 --- a/app/javascript/mastodon/components/status_content.js +++ b/app/javascript/mastodon/components/status_content.js @@ -23,11 +23,11 @@ export default class StatusContent extends React.PureComponent { onExpandedToggle: PropTypes.func, onClick: PropTypes.func, collapsable: PropTypes.bool, + onCollapsedToggle: PropTypes.func, }; state = { hidden: true, - collapsed: null, // `collapsed: null` indicates that an element doesn't need collapsing, while `true` or `false` indicates that it does (and is/isn't). }; _updateStatusLinks () { @@ -62,14 +62,16 @@ export default class StatusContent extends React.PureComponent { link.setAttribute('rel', 'noopener noreferrer'); } - if ( - this.props.collapsable - && this.props.onClick - && this.state.collapsed === null - && node.clientHeight > MAX_HEIGHT - && this.props.status.get('spoiler_text').length === 0 - ) { - this.setState({ collapsed: true }); + if (this.props.status.get('collapsed', null) === null) { + let collapsed = + this.props.collapsable + && this.props.onClick + && node.clientHeight > MAX_HEIGHT + && this.props.status.get('spoiler_text').length === 0; + + if(this.props.onCollapsedToggle) this.props.onCollapsedToggle(collapsed); + + this.props.status.set('collapsed', collapsed); } } @@ -178,6 +180,7 @@ export default class StatusContent extends React.PureComponent { } const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden; + const renderReadMore = this.props.onClick && status.get('collapsed'); const content = { __html: status.get('contentHtml') }; const spoilerContent = { __html: status.get('spoilerHtml') }; @@ -185,7 +188,7 @@ export default class StatusContent extends React.PureComponent { const classNames = classnames('status__content', { 'status__content--with-action': this.props.onClick && this.context.router, 'status__content--with-spoiler': status.get('spoiler_text').length > 0, - 'status__content--collapsed': this.state.collapsed === true, + 'status__content--collapsed': renderReadMore, }); if (isRtl(status.get('search_index'))) { @@ -237,7 +240,7 @@ export default class StatusContent extends React.PureComponent { , ]; - if (this.state.collapsed) { + if (renderReadMore) { output.push(readMoreButton); } diff --git a/app/javascript/mastodon/components/status_list.js b/app/javascript/mastodon/components/status_list.js index e1b370c913..82e069601d 100644 --- a/app/javascript/mastodon/components/status_list.js +++ b/app/javascript/mastodon/components/status_list.js @@ -26,6 +26,8 @@ export default class StatusList extends ImmutablePureComponent { emptyMessage: PropTypes.node, alwaysPrepend: PropTypes.bool, timelineId: PropTypes.string, + currentlyViewing: PropTypes.number, + updateCurrentlyViewing: PropTypes.func, }; static defaultProps = { @@ -58,6 +60,12 @@ export default class StatusList extends ImmutablePureComponent { this.props.onLoadMore(this.props.statusIds.size > 0 ? this.props.statusIds.last() : undefined); }, 300, { leading: true }) + updateCurrentlyViewingWithCache = (id) => { + if(this.cachedCurrentlyViewing === id) return; + this.cachedCurrentlyViewing = id; + this.props.updateCurrentlyViewing(id); + } + _selectChild (index, align_top) { const container = this.node.node; const element = container.querySelector(`article:nth-of-type(${index + 1}) .focusable`); @@ -79,6 +87,7 @@ export default class StatusList extends ImmutablePureComponent { render () { const { statusIds, featuredStatusIds, shouldUpdateScroll, onLoadMore, timelineId, ...other } = this.props; const { isLoading, isPartial } = other; + other.updateCurrentlyViewing = this.updateCurrentlyViewingWithCache; if (isPartial) { return ; diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js index 35c16a20ca..2ba3a3123d 100644 --- a/app/javascript/mastodon/containers/status_container.js +++ b/app/javascript/mastodon/containers/status_container.js @@ -23,6 +23,7 @@ import { deleteStatus, hideStatus, revealStatus, + toggleStatusCollapse, } from '../actions/statuses'; import { unmuteAccount, @@ -190,6 +191,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, + onToggleCollapsed (status, isCollapsed) { + dispatch(toggleStatusCollapse(status.get('id'), isCollapsed)); + }, + onBlockDomain (domain) { dispatch(openModal('CONFIRM', { message: {domain} }} />, diff --git a/app/javascript/mastodon/features/ui/containers/status_list_container.js b/app/javascript/mastodon/features/ui/containers/status_list_container.js index 9f6cbf988e..33af628ca7 100644 --- a/app/javascript/mastodon/features/ui/containers/status_list_container.js +++ b/app/javascript/mastodon/features/ui/containers/status_list_container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import StatusList from '../../../components/status_list'; -import { scrollTopTimeline, loadPending } from '../../../actions/timelines'; +import { scrollTopTimeline, loadPending, updateCurrentlyViewing } from '../../../actions/timelines'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { createSelector } from 'reselect'; import { debounce } from 'lodash'; @@ -39,6 +39,7 @@ const makeMapStateToProps = () => { isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false), hasMore: state.getIn(['timelines', timelineId, 'hasMore']), numPending: getPendingStatusIds(state, { type: timelineId }).size, + currentlyViewing: state.getIn(['timelines', timelineId, 'currentlyViewing'], -1), }); return mapStateToProps; @@ -56,6 +57,7 @@ const mapDispatchToProps = (dispatch, { timelineId }) => ({ onLoadPending: () => dispatch(loadPending(timelineId)), + updateCurrentlyViewing: id => dispatch(updateCurrentlyViewing(timelineId, id)), }); export default connect(makeMapStateToProps, mapDispatchToProps)(StatusList); diff --git a/app/javascript/mastodon/reducers/statuses.js b/app/javascript/mastodon/reducers/statuses.js index 772f98bcbf..398a48cff8 100644 --- a/app/javascript/mastodon/reducers/statuses.js +++ b/app/javascript/mastodon/reducers/statuses.js @@ -12,6 +12,7 @@ import { STATUS_UNMUTE_SUCCESS, STATUS_REVEAL, STATUS_HIDE, + STATUS_COLLAPSE, } from '../actions/statuses'; import { TIMELINE_DELETE } from '../actions/timelines'; import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer'; @@ -73,6 +74,8 @@ export default function statuses(state = initialState, action) { } }); }); + case STATUS_COLLAPSE: + return state.setIn([action.id, 'collapsed'], action.isCollapsed); case TIMELINE_DELETE: return deleteStatus(state, action.id, action.references); default: diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js index 0d7222e10a..970db425e8 100644 --- a/app/javascript/mastodon/reducers/timelines.js +++ b/app/javascript/mastodon/reducers/timelines.js @@ -9,6 +9,7 @@ import { TIMELINE_CONNECT, TIMELINE_DISCONNECT, TIMELINE_LOAD_PENDING, + CURRENTLY_VIEWING, } from '../actions/timelines'; import { ACCOUNT_BLOCK_SUCCESS, @@ -28,6 +29,7 @@ const initialTimeline = ImmutableMap({ hasMore: true, pendingItems: ImmutableList(), items: ImmutableList(), + currentlyViewing: -1, }); const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, isLoadingRecent, usePendingItems) => { @@ -168,6 +170,8 @@ export default function timelines(state = initialState, action) { initialTimeline, map => map.set('online', false).update(action.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items) ); + case CURRENTLY_VIEWING: + return state.update(action.timeline, initialTimeline, map => map.set('currentlyViewing', action.id)); default: return state; } From 1919ddbe6f4df93f7d34f9cc51ed5a39ff4c5e28 Mon Sep 17 00:00:00 2001 From: ThibG Date: Sun, 29 Dec 2019 05:41:26 +0100 Subject: [PATCH 03/44] Fix batch actions on non-pending tags in admin interface (#12537) - Allow batch actions on unreviewed tags - Hide checkboxes when batch actions aren't available --- app/views/admin/tags/_tag.html.haml | 5 +++-- app/views/admin/tags/index.html.haml | 15 ++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/views/admin/tags/_tag.html.haml b/app/views/admin/tags/_tag.html.haml index 670f3bc059..287d28e53b 100644 --- a/app/views/admin/tags/_tag.html.haml +++ b/app/views/admin/tags/_tag.html.haml @@ -1,6 +1,7 @@ .batch-table__row - %label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox - = f.check_box :tag_ids, { multiple: true, include_hidden: false }, tag.id + - if batch_available + %label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox + = f.check_box :tag_ids, { multiple: true, include_hidden: false }, tag.id .directory__tag = link_to admin_tag_path(tag.id) do diff --git a/app/views/admin/tags/index.html.haml b/app/views/admin/tags/index.html.haml index b29991328e..7f2c531902 100644 --- a/app/views/admin/tags/index.html.haml +++ b/app/views/admin/tags/index.html.haml @@ -50,25 +50,26 @@ .batch-table.optional .batch-table__toolbar - %label.batch-table__toolbar__select.batch-checkbox-all - = check_box_tag :batch_checkbox_all, nil, false - .batch-table__toolbar__actions - - if params[:pending_review] == '1' + - if params[:pending_review] == '1' || params[:unreviewed] == '1' + %label.batch-table__toolbar__select.batch-checkbox-all + = check_box_tag :batch_checkbox_all, nil, false + .batch-table__toolbar__actions = f.button safe_join([fa_icon('check'), t('admin.accounts.approve')]), name: :approve, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } = f.button safe_join([fa_icon('times'), t('admin.accounts.reject')]), name: :reject, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } - - else + - else + .batch-table__toolbar__actions %span.neutral-hint= t('generic.no_batch_actions_available') .batch-table__body - if @tags.empty? = nothing_here 'nothing-here--under-tabs' - else - = render partial: 'tag', collection: @tags, locals: { f: f } + = render partial: 'tag', collection: @tags, locals: { f: f, batch_available: params[:pending_review] == '1' || params[:unreviewed] == '1' } = paginate @tags -- if params[:pending_review] == '1' +- if params[:pending_review] == '1' || params[:unreviewed] == '1' %hr.spacer/ %div{ style: 'overflow: hidden' } From ed1226c8c86137ce10daf35af76e00dd5f39b8a0 Mon Sep 17 00:00:00 2001 From: Takeshi Umeda Date: Mon, 30 Dec 2019 00:59:25 +0900 Subject: [PATCH 04/44] Fix shortNumberFormat to within 3 chars without units (#12706) --- app/javascript/mastodon/utils/numbers.js | 8 ++++++-- app/javascript/styles/mastodon/components.scss | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/javascript/mastodon/utils/numbers.js b/app/javascript/mastodon/utils/numbers.js index f7e4ceb935..af18dcfddb 100644 --- a/app/javascript/mastodon/utils/numbers.js +++ b/app/javascript/mastodon/utils/numbers.js @@ -4,9 +4,13 @@ import { FormattedNumber } from 'react-intl'; export const shortNumberFormat = number => { if (number < 1000) { return ; - } else if (number < 1000000) { + } else if (number < 10000) { return K; - } else { + } else if (number < 1000000) { + return K; + } else if (number < 10000000) { return M; + } else { + return M; } }; diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 4c7ce9ba7c..7121030d24 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -6399,13 +6399,13 @@ noscript { &__links { font-size: 14px; color: $darker-text-color; + padding: 10px 0; a { display: inline-block; color: $darker-text-color; text-decoration: none; - padding: 10px; - padding-top: 20px; + padding: 5px 10px; font-weight: 500; strong { From c3e286a5266aea0c615df05e04a73dc53b899233 Mon Sep 17 00:00:00 2001 From: Shlee Date: Mon, 30 Dec 2019 00:00:43 +0800 Subject: [PATCH 05/44] Circleci - Upgrade to Buster Images (#12705) * Update config.yml * Update Gemfile.lock --- .circleci/config.yml | 26 +++++++++++++------------- Gemfile.lock | 6 ------ 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ff8eb48598..83a2088d70 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2 aliases: - &defaults docker: - - image: circleci/ruby:2.6-stretch-node + - image: circleci/ruby:2.6-buster-node environment: &ruby_environment BUNDLE_APP_CONFIG: ./.bundle/ DB_HOST: localhost @@ -39,7 +39,6 @@ aliases: steps: - checkout - *attach_workspace - - restore_cache: keys: - v1-node-dependencies-{{ checksum "yarn.lock" }} @@ -49,7 +48,6 @@ aliases: key: v1-node-dependencies-{{ checksum "yarn.lock" }} paths: - ./node_modules/ - - *persist_to_workspace - &install_system_dependencies @@ -58,13 +56,17 @@ aliases: command: | sudo apt-get update sudo apt-get install -y libicu-dev libidn11-dev libprotobuf-dev protobuf-compiler + + ## TODO: FIX THESE BUSTER DEPENDANCES + sudo wget http://ftp.au.debian.org/debian/pool/main/i/icu/libicu57_57.1-6+deb9u3_amd64.deb + sudo dpkg -i libicu57_57.1-6+deb9u3_amd64.deb + sudo wget http://ftp.au.debian.org/debian/pool/main/p/protobuf/libprotobuf10_3.0.0-9_amd64.deb + sudo dpkg -i libprotobuf10_3.0.0-9_amd64.deb - &install_ruby_dependencies steps: - *attach_workspace - - *install_system_dependencies - - run: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version - *restore_ruby_dependencies - run: bundle install --clean --jobs 16 --path ./vendor/bundle/ --retry 3 --with pam_authentication --without development production && bundle clean @@ -82,10 +84,8 @@ aliases: - &test_steps steps: - *attach_workspace - - *install_system_dependencies - run: sudo apt-get install -y ffmpeg - - run: name: Prepare Tests command: ./bin/rails parallel:create parallel:load_schema parallel:prepare @@ -105,14 +105,14 @@ jobs: install-ruby2.5: <<: *defaults docker: - - image: circleci/ruby:2.5-stretch-node + - image: circleci/ruby:2.5-buster-node environment: *ruby_environment <<: *install_ruby_dependencies install-ruby2.4: <<: *defaults docker: - - image: circleci/ruby:2.4-stretch-node + - image: circleci/ruby:2.4-buster-node environment: *ruby_environment <<: *install_ruby_dependencies @@ -131,7 +131,7 @@ jobs: test-ruby2.6: <<: *defaults docker: - - image: circleci/ruby:2.6-stretch-node + - image: circleci/ruby:2.6-buster-node environment: *ruby_environment - image: circleci/postgres:10.6-alpine environment: @@ -142,7 +142,7 @@ jobs: test-ruby2.5: <<: *defaults docker: - - image: circleci/ruby:2.5-stretch-node + - image: circleci/ruby:2.5-buster-node environment: *ruby_environment - image: circleci/postgres:10.6-alpine environment: @@ -153,7 +153,7 @@ jobs: test-ruby2.4: <<: *defaults docker: - - image: circleci/ruby:2.4-stretch-node + - image: circleci/ruby:2.4-buster-node environment: *ruby_environment - image: circleci/postgres:10.6-alpine environment: @@ -164,7 +164,7 @@ jobs: test-webui: <<: *defaults docker: - - image: circleci/node:12.9-stretch + - image: circleci/node:12-buster steps: - *attach_workspace - run: ./bin/retry yarn test:jest diff --git a/Gemfile.lock b/Gemfile.lock index 967b2cf87a..6cd3dca1f5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -803,9 +803,3 @@ DEPENDENCIES webmock (~> 3.7) webpacker (~> 4.2) webpush - -RUBY VERSION - ruby 2.6.5p114 - -BUNDLED WITH - 1.17.3 From 38ccdb696fd1a79a48736e932ddb0d8177902b8b Mon Sep 17 00:00:00 2001 From: "chr v1.x" Date: Sun, 29 Dec 2019 18:17:54 -0800 Subject: [PATCH 06/44] Fix backups stopping due to read timeouts (#12281) * Make BackupService resilient to read timeouts If an attachment read times out, assume that the resources is inaccessible and continue the backup without it. This fixes #12280. * Both errors on one line --- app/services/backup_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb index fba2d19a08..d1090dff1b 100644 --- a/app/services/backup_service.rb +++ b/app/services/backup_service.rb @@ -165,7 +165,7 @@ class BackupService < BaseService io.write(buffer) end end - rescue Errno::ENOENT + rescue Errno::ENOENT, Seahorse::Client::NetworkingError Rails.logger.warn "Could not backup file #{filename}: file not found" end end From b5ebc8e7ddfd5aa2a464ff7a635af6eec0cb92b5 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 30 Dec 2019 03:55:11 +0100 Subject: [PATCH 07/44] Fix undefined error regression in status component in web UI (#12712) Regression from #12661 --- app/javascript/mastodon/components/status.js | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 12fc4a9a6d..0dc00cb98d 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -103,11 +103,6 @@ class Status extends ImmutablePureComponent { statusId: undefined, }; - // Track height changes we know about to compensate scrolling - componentDidMount () { - this.didShowCard = !this.props.muted && !this.props.hidden && this.props.status && this.props.status.get('card'); - } - static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.status && nextProps.status.get('id') !== prevState.statusId) { return { @@ -119,21 +114,6 @@ class Status extends ImmutablePureComponent { } } - // Compensate height changes - componentDidUpdate (prevProps, prevState, snapshot) { - const doShowCard = !this.props.muted && !this.props.hidden && this.props.status && this.props.status.get('card'); - - if (doShowCard && !this.didShowCard) { - this.didShowCard = true; - - if (snapshot !== null && this.props.updateScrollBottom) { - if (this.node && this.node.offsetTop < snapshot.top) { - this.props.updateScrollBottom(snapshot.height - snapshot.top); - } - } - } - } - handleToggleMediaVisibility = () => { this.setState({ showMedia: !this.state.showMedia }); } From 7cca47919ffe0246db8606a484d611c39118950f Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 30 Dec 2019 04:38:18 +0100 Subject: [PATCH 08/44] Fix HTML error pages being returned when JSON is expected (#12713) Fix #12509 See also #12214 --- app/controllers/application_controller.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ca5229f796..3f92053813 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -136,6 +136,9 @@ class ApplicationController < ActionController::Base end def respond_with_error(code) - render "errors/#{code}", layout: 'error', status: code, formats: [:html] + respond_to do |format| + format.any { render "errors/#{code}", layout: 'error', status: code, formats: [:html] } + format.json { render json: { error: Rack::Utils::HTTP_STATUS_CODES[code] }, status: code } + end end end From 49b688137998df060d92cd4e81eb75cace09ec2a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 30 Dec 2019 04:38:30 +0100 Subject: [PATCH 09/44] Fix settings pages being cacheable by the browser (#12714) Fix #12255 --- app/controllers/auth/registrations_controller.rb | 5 +++++ app/controllers/oauth/authorizations_controller.rb | 5 +++++ app/controllers/settings/base_controller.rb | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 019caf9c1a..212519c8b8 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -10,6 +10,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController before_action :set_instance_presenter, only: [:new, :create, :update] before_action :set_body_classes, only: [:new, :create, :edit, :update] before_action :require_not_suspended!, only: [:update] + before_action :set_cache_headers, only: [:edit, :update] skip_before_action :require_functional!, only: [:edit, :update] @@ -109,4 +110,8 @@ class Auth::RegistrationsController < Devise::RegistrationsController def require_not_suspended! forbidden if current_account.suspended? end + + def set_cache_headers + response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' + end end diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb index cebbdc4d08..bb5d639ced 100644 --- a/app/controllers/oauth/authorizations_controller.rb +++ b/app/controllers/oauth/authorizations_controller.rb @@ -5,6 +5,7 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController before_action :store_current_location before_action :authenticate_resource_owner! + before_action :set_cache_headers include Localized @@ -27,4 +28,8 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController def truthy_param?(key) ActiveModel::Type::Boolean.new.cast(params[key]) end + + def set_cache_headers + response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' + end end diff --git a/app/controllers/settings/base_controller.rb b/app/controllers/settings/base_controller.rb index 9bb14afa2d..3c404cfff2 100644 --- a/app/controllers/settings/base_controller.rb +++ b/app/controllers/settings/base_controller.rb @@ -2,10 +2,15 @@ class Settings::BaseController < ApplicationController before_action :set_body_classes + before_action :set_cache_headers private def set_body_classes @body_classes = 'admin' end + + def set_cache_headers + response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' + end end From 510f07e94a25cec8d96a76f1391dc92af0a02834 Mon Sep 17 00:00:00 2001 From: Shlee Date: Mon, 30 Dec 2019 14:41:40 +0800 Subject: [PATCH 10/44] Upgrade Node v12 in Dockerfile (#12703) --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 117727d08d..cc75bd6bee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ FROM ubuntu:18.04 as build-dep SHELL ["bash", "-c"] # Install Node v12 (LTS) -ENV NODE_VER="12.13.1" +ENV NODE_VER="12.14.0" RUN echo "Etc/UTC" > /etc/localtime && \ apt update && \ apt -y install wget python && \ From 7dabbc0818bab97be499e8486e8ec55c0c5e1ac9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2019 21:54:04 +0900 Subject: [PATCH 11/44] Bump eslint from 6.7.2 to 6.8.0 (#12717) Bumps [eslint](https://github.com/eslint/eslint) from 6.7.2 to 6.8.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v6.7.2...v6.8.0) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 15 +++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 5568f3c04b..f8a7c0bbbf 100644 --- a/package.json +++ b/package.json @@ -172,7 +172,7 @@ "babel-jest": "^24.9.0", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.1", - "eslint": "^6.7.2", + "eslint": "^6.8.0", "eslint-plugin-import": "~2.19.1", "eslint-plugin-jsx-a11y": "~6.2.3", "eslint-plugin-promise": "~4.2.1", diff --git a/yarn.lock b/yarn.lock index 4bb3c8049c..50736ccc11 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3938,10 +3938,10 @@ eslint@^2.7.0: text-table "~0.2.0" user-home "^2.0.0" -eslint@^6.7.2: - version "6.7.2" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1" - integrity sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng== +eslint@^6.8.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" + integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -4027,12 +4027,7 @@ estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -esutils@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= - -esutils@^2.0.2: +esutils@^2.0.0, esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== From 6c1ba8d181d6f2e58e18fc95d4d5beb8331fa45b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2019 23:54:43 +0900 Subject: [PATCH 12/44] Bump redux from 4.0.4 to 4.0.5 (#12719) Bumps [redux](https://github.com/reduxjs/redux) from 4.0.4 to 4.0.5. - [Release notes](https://github.com/reduxjs/redux/releases) - [Changelog](https://github.com/reduxjs/redux/blob/master/CHANGELOG.md) - [Commits](https://github.com/reduxjs/redux/compare/v4.0.4...v4.0.5) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f8a7c0bbbf..1910f3e45e 100644 --- a/package.json +++ b/package.json @@ -143,7 +143,7 @@ "react-textarea-autosize": "^7.1.2", "react-toggle": "^4.1.1", "redis": "^2.7.1", - "redux": "^4.0.4", + "redux": "^4.0.5", "redux-immutable": "^4.0.0", "redux-thunk": "^2.2.0", "rellax": "^1.10.0", diff --git a/yarn.lock b/yarn.lock index 50736ccc11..18a18c7cde 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8933,10 +8933,10 @@ redux-thunk@^2.2.0: resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== -redux@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.4.tgz#4ee1aeb164b63d6a1bcc57ae4aa0b6e6fa7a3796" - integrity sha512-vKv4WdiJxOWKxK0yRoaK3Y4pxxB0ilzVx6dszU2W8wLxlb2yikRph4iV/ymtdJ6ZxpBLFbyrxklnT5yBbQSl3Q== +redux@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" + integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== dependencies: loose-envify "^1.4.0" symbol-observable "^1.2.0" From 8494842c6b05c21934807ff7b0b9ed48fc65f730 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2019 23:55:03 +0900 Subject: [PATCH 13/44] Bump @babel/core from 7.7.5 to 7.7.7 (#12720) Bumps [@babel/core](https://github.com/babel/babel) from 7.7.5 to 7.7.7. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel/compare/v7.7.5...v7.7.7) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 1910f3e45e..788b9a8372 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ }, "private": true, "dependencies": { - "@babel/core": "^7.7.5", + "@babel/core": "^7.7.7", "@babel/plugin-proposal-class-properties": "^7.7.4", "@babel/plugin-proposal-decorators": "^7.7.4", "@babel/plugin-transform-react-inline-elements": "^7.7.4", diff --git a/yarn.lock b/yarn.lock index 18a18c7cde..22e0aca3df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,15 +9,15 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.5": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.5.tgz#ae1323cd035b5160293307f50647e83f8ba62f7e" - integrity sha512-M42+ScN4+1S9iB6f+TL7QBpoQETxbclx+KNoKJABghnKYE+fMzSGqst0BZJc8CpI625bwPwYgUyRvxZ+0mZzpw== +"@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.7.tgz#ee155d2e12300bcc0cff6a8ad46f2af5063803e9" + integrity sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.4" + "@babel/generator" "^7.7.7" "@babel/helpers" "^7.7.4" - "@babel/parser" "^7.7.5" + "@babel/parser" "^7.7.7" "@babel/template" "^7.7.4" "@babel/traverse" "^7.7.4" "@babel/types" "^7.7.4" @@ -29,10 +29,10 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.0.0", "@babel/generator@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369" - integrity sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg== +"@babel/generator@^7.0.0", "@babel/generator@^7.7.4", "@babel/generator@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45" + integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ== dependencies: "@babel/types" "^7.7.4" jsesc "^2.5.1" @@ -252,10 +252,10 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.7.4", "@babel/parser@^7.7.5": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71" - integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.7.4", "@babel/parser@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937" + integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw== "@babel/plugin-proposal-async-generator-functions@^7.7.4": version "7.7.4" From cd17c9b89d564771e933612193223d0de900e16b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2019 23:56:23 +0900 Subject: [PATCH 14/44] Bump terser-webpack-plugin from 2.2.2 to 2.3.1 (#12722) Bumps [terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin) from 2.2.2 to 2.3.1. - [Release notes](https://github.com/webpack-contrib/terser-webpack-plugin/releases) - [Changelog](https://github.com/webpack-contrib/terser-webpack-plugin/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack-contrib/terser-webpack-plugin/compare/v2.2.2...v2.3.1) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 788b9a8372..81df3667c4 100644 --- a/package.json +++ b/package.json @@ -154,7 +154,7 @@ "sass-loader": "^8.0.0", "stringz": "^2.0.0", "substring-trie": "^1.0.2", - "terser-webpack-plugin": "^2.2.2", + "terser-webpack-plugin": "^2.3.1", "tesseract.js": "^2.0.0-alpha.16", "throng": "^4.0.0", "tiny-queue": "^0.2.1", diff --git a/yarn.lock b/yarn.lock index 22e0aca3df..3c7c2a052b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4372,10 +4372,10 @@ find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-cache-dir@^3.0.0, find-cache-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.1.0.tgz#9935894999debef4cf9f677fdf646d002c4cdecb" - integrity sha512-zw+EFiNBNPgI2NTrKkDd1xd7q0cs6wr/iWnr/oUkI0yF9K9GqQ+riIt4aiyFaaqpaWbxPrJXHI+QvmNUQbX+0Q== +find-cache-dir@^3.0.0, find-cache-dir@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.2.0.tgz#e7fe44c1abc1299f516146e563108fd1006c1874" + integrity sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg== dependencies: commondir "^1.0.1" make-dir "^3.0.0" @@ -9479,7 +9479,7 @@ serialize-javascript@^1.7.0: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== -serialize-javascript@^2.1.1, serialize-javascript@^2.1.2: +serialize-javascript@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== @@ -10166,24 +10166,24 @@ terser-webpack-plugin@^1.4.1: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser-webpack-plugin@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.2.2.tgz#2a6e00237125564a455ad69b22e08ee59420473a" - integrity sha512-/CHMNswPMAwuD2kd++qys8UmBRmsshPSzHw4BlDwurPtK9YjeK93OV89YWkJulHk972cs07K/7Z92V6PNjWF8A== +terser-webpack-plugin@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.1.tgz#6a63c27debc15b25ffd2588562ee2eeabdcab923" + integrity sha512-dNxivOXmDgZqrGxOttBH6B4xaxT4zNC+Xd+2K8jwGDMK5q2CZI+KZMA1AAnSRT+BTRvuzKsDx+fpxzPAmAMVcA== dependencies: cacache "^13.0.1" - find-cache-dir "^3.1.0" + find-cache-dir "^3.2.0" jest-worker "^24.9.0" schema-utils "^2.6.1" - serialize-javascript "^2.1.1" + serialize-javascript "^2.1.2" source-map "^0.6.1" - terser "^4.4.2" + terser "^4.4.3" webpack-sources "^1.4.3" -terser@^4.1.2, terser@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.2.tgz#448fffad0245f4c8a277ce89788b458bfd7706e8" - integrity sha512-Uufrsvhj9O1ikwgITGsZ5EZS6qPokUOkCegS7fYOdGTv+OA90vndUbU6PEjr5ePqHfNUbGyMO7xyIZv2MhsALQ== +terser@^4.1.2, terser@^4.4.3: + version "4.4.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.3.tgz#401abc52b88869cf904412503b1eb7da093ae2f0" + integrity sha512-0ikKraVtRDKGzHrzkCv5rUNDzqlhmhowOBqC0XqUHFpW+vJ45+20/IFBcebwKfiS2Z9fJin6Eo+F1zLZsxi8RA== dependencies: commander "^2.20.0" source-map "~0.6.1" From 1356f0a8a3c96f3e8b366f9ac964d43b8d31df44 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2019 23:58:24 +0900 Subject: [PATCH 15/44] Bump rack-cors from 1.1.0 to 1.1.1 (#12730) Bumps [rack-cors](https://github.com/cyu/rack-cors) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/cyu/rack-cors/releases) - [Changelog](https://github.com/cyu/rack-cors/blob/master/CHANGELOG.md) - [Commits](https://github.com/cyu/rack-cors/compare/v1.1.0...v1.1.1) Signed-off-by: dependabot-preview[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 6cd3dca1f5..cf52267796 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -461,7 +461,7 @@ GEM rack (2.0.8) rack-attack (6.2.2) rack (>= 1.0, < 3) - rack-cors (1.1.0) + rack-cors (1.1.1) rack (>= 2.0.0) rack-protection (2.0.7) rack From 0fc785b85275a6d1ba6554c21661b3040abe6f9d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 31 Dec 2019 00:07:27 +0900 Subject: [PATCH 16/44] Bump is-nan from 1.2.1 to 1.3.0 (#12723) Bumps [is-nan](https://github.com/es-shims/is-nan) from 1.2.1 to 1.3.0. - [Release notes](https://github.com/es-shims/is-nan/releases) - [Changelog](https://github.com/es-shims/is-nan/blob/master/CHANGELOG.md) - [Commits](https://github.com/es-shims/is-nan/compare/v1.2.1...v1.3.0) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 81df3667c4..99fd0b3fd7 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "intl": "^1.2.5", "intl-messageformat": "^2.2.0", "intl-relativeformat": "^6.4.3", - "is-nan": "^1.2.1", + "is-nan": "^1.3.0", "js-yaml": "^3.13.1", "lodash": "^4.17.14", "mark-loader": "^0.1.6", diff --git a/yarn.lock b/yarn.lock index 3c7c2a052b..fced722e49 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3243,7 +3243,7 @@ default-gateway@^4.2.0: execa "^1.0.0" ip-regex "^2.1.0" -define-properties@^1.1.1, define-properties@^1.1.2, define-properties@^1.1.3: +define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== @@ -5607,12 +5607,12 @@ is-my-json-valid@^2.10.0: jsonpointer "^4.0.0" xtend "^4.0.0" -is-nan@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2" - integrity sha1-n69ltvttskt/XAYoR16nH5iEAeI= +is-nan@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.0.tgz#85d1f5482f7051c2019f5673ccebdb06f3b0db03" + integrity sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ== dependencies: - define-properties "^1.1.1" + define-properties "^1.1.3" is-number-object@^1.0.4: version "1.0.4" From a85b29d2e2a9f9c2c593d7a614f1b1b3c15bb581 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 31 Dec 2019 00:13:25 +0900 Subject: [PATCH 17/44] Bump derailed_benchmarks from 1.4.2 to 1.4.3 (#12729) Bumps [derailed_benchmarks](https://github.com/schneems/derailed_benchmarks) from 1.4.2 to 1.4.3. - [Release notes](https://github.com/schneems/derailed_benchmarks/releases) - [Changelog](https://github.com/schneems/derailed_benchmarks/blob/master/CHANGELOG.md) - [Commits](https://github.com/schneems/derailed_benchmarks/compare/v1.4.2...v1.4.3) Signed-off-by: dependabot-preview[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index cf52267796..54917b8aeb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -188,7 +188,7 @@ GEM css_parser (1.7.0) addressable debug_inspector (0.0.3) - derailed_benchmarks (1.4.2) + derailed_benchmarks (1.4.3) benchmark-ips (~> 2) get_process_mem (~> 0) heapy (~> 0) From ef5b33453a82850dafc473da2c205e7613496559 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 31 Dec 2019 00:14:42 +0900 Subject: [PATCH 18/44] Bump react-test-renderer from 16.11.0 to 16.12.0 (#12721) Bumps [react-test-renderer](https://github.com/facebook/react/tree/HEAD/packages/react-test-renderer) from 16.11.0 to 16.12.0. - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/master/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v16.12.0/packages/react-test-renderer) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 18 +++++------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 99fd0b3fd7..89c282e2ff 100644 --- a/package.json +++ b/package.json @@ -180,7 +180,7 @@ "jest": "^24.9.0", "raf": "^3.4.1", "react-intl-translations-manager": "^5.0.3", - "react-test-renderer": "^16.11.0", + "react-test-renderer": "^16.12.0", "sass-lint": "^1.13.1", "webpack-dev-server": "^3.9.0", "yargs": "^15.0.2" diff --git a/yarn.lock b/yarn.lock index fced722e49..822d852f36 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8772,15 +8772,15 @@ react-swipeable-views@^0.13.3: react-swipeable-views-utils "^0.13.3" warning "^4.0.1" -react-test-renderer@^16.0.0-0, react-test-renderer@^16.11.0: - version "16.11.0" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.11.0.tgz#72574566496462c808ac449b0287a4c0a1a7d8f8" - integrity sha512-nh9gDl8R4ut+ZNNb2EeKO5VMvTKxwzurbSMuGBoKtjpjbg8JK/u3eVPVNi1h1Ue+eYK9oSzJjb+K3lzLxyA4ag== +react-test-renderer@^16.0.0-0, react-test-renderer@^16.12.0: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.12.0.tgz#11417ffda579306d4e841a794d32140f3da1b43f" + integrity sha512-Vj/teSqt2oayaWxkbhQ6gKis+t5JrknXfPVo+aIJ8QwYAqMPH77uptOdrlphyxl8eQI/rtkOYg86i/UWkpFu0w== dependencies: object-assign "^4.1.1" prop-types "^15.6.2" react-is "^16.8.6" - scheduler "^0.17.0" + scheduler "^0.18.0" react-textarea-autosize@^7.1.2: version "7.1.2" @@ -9382,14 +9382,6 @@ sax@^1.2.4, sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -scheduler@^0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe" - integrity sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler@^0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" From 8ba7008cbd68f6beeccb943fc521aadcca1cfbda Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 31 Dec 2019 00:15:16 +0900 Subject: [PATCH 19/44] Bump faker from 2.9.0 to 2.10.0 (#12728) Bumps [faker](https://github.com/faker-ruby/faker) from 2.9.0 to 2.10.0. - [Release notes](https://github.com/faker-ruby/faker/releases) - [Changelog](https://github.com/faker-ruby/faker/blob/master/CHANGELOG.md) - [Commits](https://github.com/faker-ruby/faker/compare/v2.9.0...v2.10.0) Signed-off-by: dependabot-preview[bot] --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 8bd791d711..098d7be802 100644 --- a/Gemfile +++ b/Gemfile @@ -117,7 +117,7 @@ end group :test do gem 'capybara', '~> 3.29' gem 'climate_control', '~> 0.2' - gem 'faker', '~> 2.9' + gem 'faker', '~> 2.10' gem 'microformats', '~> 4.1' gem 'rails-controller-testing', '~> 1.0' gem 'rspec-sidekiq', '~> 3.0' diff --git a/Gemfile.lock b/Gemfile.lock index 54917b8aeb..79cc0e322d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -240,7 +240,7 @@ GEM tzinfo excon (0.71.0) fabrication (2.21.0) - faker (2.9.0) + faker (2.10.0) i18n (>= 1.6, < 1.8) faraday (0.15.4) multipart-post (>= 1.2, < 3) @@ -710,7 +710,7 @@ DEPENDENCIES doorkeeper (~> 5.2) dotenv-rails (~> 2.7) fabrication (~> 2.21) - faker (~> 2.9) + faker (~> 2.10) fast_blank (~> 1.0) fastimage fog-core (<= 2.1.0) From 29c12522f0e16fa197c1a5e1ddd961b73d6e0361 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 31 Dec 2019 00:16:45 +0900 Subject: [PATCH 20/44] Bump redis-namespace from 1.6.0 to 1.7.0 (#12727) Bumps [redis-namespace](https://github.com/resque/redis-namespace) from 1.6.0 to 1.7.0. - [Release notes](https://github.com/resque/redis-namespace/releases) - [Changelog](https://github.com/resque/redis-namespace/blob/master/CHANGELOG.md) - [Commits](https://github.com/resque/redis-namespace/compare/v1.6.0...v1.7.0) Signed-off-by: dependabot-preview[bot] --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 098d7be802..1a28afa426 100644 --- a/Gemfile +++ b/Gemfile @@ -50,7 +50,7 @@ gem 'fast_blank', '~> 1.0' gem 'fastimage' gem 'goldfinger', '~> 2.1' gem 'hiredis', '~> 0.6' -gem 'redis-namespace', '~> 1.5' +gem 'redis-namespace', '~> 1.7' gem 'health_check', git: 'https://github.com/ianheggie/health_check', ref: '0b799ead604f900ed50685e9b2d469cd2befba5b' gem 'htmlentities', '~> 4.3' gem 'http', '~> 3.3' diff --git a/Gemfile.lock b/Gemfile.lock index 79cc0e322d..3e42bdfc8a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -517,7 +517,7 @@ GEM redis-activesupport (5.0.4) activesupport (>= 3, < 6) redis-store (>= 1.3, < 2) - redis-namespace (1.6.0) + redis-namespace (1.7.0) redis (>= 3.0.4) redis-rack (2.0.4) rack (>= 1.5, < 3) @@ -773,7 +773,7 @@ DEPENDENCIES rails-settings-cached (~> 0.6) rdf-normalize (~> 0.3) redis (~> 4.1) - redis-namespace (~> 1.5) + redis-namespace (~> 1.7) redis-rails (~> 5.0) rqrcode (~> 0.10) rspec-rails (~> 3.9) From 25134319e83467755ec218ffc3ea1ee4112b045a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 31 Dec 2019 00:21:51 +0900 Subject: [PATCH 21/44] Bump pg from 1.1.4 to 1.2.0 (#12725) Bumps [pg](https://github.com/ged/ruby-pg) from 1.1.4 to 1.2.0. - [Release notes](https://github.com/ged/ruby-pg/releases) - [Changelog](https://github.com/ged/ruby-pg/blob/master/History.rdoc) - [Commits](https://github.com/ged/ruby-pg/compare/v1.1.4...v1.2.0) Signed-off-by: dependabot-preview[bot] --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 1a28afa426..c7ed114cad 100644 --- a/Gemfile +++ b/Gemfile @@ -11,7 +11,7 @@ gem 'sprockets', '~> 3.7' gem 'thor', '~> 0.20' gem 'hamlit-rails', '~> 0.2' -gem 'pg', '~> 1.1' +gem 'pg', '~> 1.2' gem 'makara', '~> 0.4' gem 'pghero', '~> 2.4' gem 'dotenv-rails', '~> 2.7' diff --git a/Gemfile.lock b/Gemfile.lock index 3e42bdfc8a..afa68d9b58 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -432,7 +432,7 @@ GEM pastel (0.7.3) equatable (~> 0.6) tty-color (~> 0.5) - pg (1.1.4) + pg (1.2.0) pghero (2.4.1) activerecord (>= 5) pkg-config (1.4.0) @@ -755,7 +755,7 @@ DEPENDENCIES parallel (~> 1.19) parallel_tests (~> 2.30) parslet - pg (~> 1.1) + pg (~> 1.2) pghero (~> 2.4) pkg-config (~> 1.4) posix-spawn! From e0e067d569723c96011fffeb1389bc0f66bb53dd Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 31 Dec 2019 00:23:05 +0900 Subject: [PATCH 22/44] Bump stackprof from 0.2.14 to 0.2.15 (#12726) Bumps [stackprof](https://github.com/tmm1/stackprof) from 0.2.14 to 0.2.15. - [Release notes](https://github.com/tmm1/stackprof/releases) - [Changelog](https://github.com/tmm1/stackprof/blob/master/CHANGELOG.md) - [Commits](https://github.com/tmm1/stackprof/compare/v0.2.14...v0.2.15) Signed-off-by: dependabot-preview[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index afa68d9b58..9610eccd9a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -615,7 +615,7 @@ GEM sshkit (1.20.0) net-scp (>= 1.1.2) net-ssh (>= 2.8.0) - stackprof (0.2.14) + stackprof (0.2.15) statsd-ruby (1.4.0) stoplight (2.2.0) streamio-ffmpeg (3.0.2) From 45e56f8f78f5c7dd19e1153d494fa38e08f2173f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 31 Dec 2019 01:49:08 +0900 Subject: [PATCH 23/44] Bump webpack from 4.41.2 to 4.41.5 (#12724) Bumps [webpack](https://github.com/webpack/webpack) from 4.41.2 to 4.41.5. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v4.41.2...v4.41.5) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 25 ++++++++++--------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 89c282e2ff..707db33758 100644 --- a/package.json +++ b/package.json @@ -160,7 +160,7 @@ "tiny-queue": "^0.2.1", "uuid": "^3.3.3", "wavesurfer.js": "^3.2.0", - "webpack": "^4.41.2", + "webpack": "^4.41.5", "webpack-assets-manifest": "^3.1.1", "webpack-bundle-analyzer": "^3.6.0", "webpack-cli": "^3.3.10", diff --git a/yarn.lock b/yarn.lock index 822d852f36..d4a4657eb5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9466,11 +9466,6 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" -serialize-javascript@^1.7.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" - integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== - serialize-javascript@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" @@ -10143,16 +10138,16 @@ tcomb@^2.5.0: resolved "https://registry.yarnpkg.com/tcomb/-/tcomb-2.7.0.tgz#10d62958041669a5d53567b9a4ee8cde22b1c2b0" integrity sha1-ENYpWAQWaaXVNWe5pO6M3iKxwrA= -terser-webpack-plugin@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4" - integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg== +terser-webpack-plugin@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" + integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== dependencies: cacache "^12.0.2" find-cache-dir "^2.1.0" is-wsl "^1.1.0" schema-utils "^1.0.0" - serialize-javascript "^1.7.0" + serialize-javascript "^2.1.2" source-map "^0.6.1" terser "^4.1.2" webpack-sources "^1.4.0" @@ -10837,10 +10832,10 @@ webpack-sources@^1.0.0, webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack- source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.41.2: - version "4.41.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.2.tgz#c34ec76daa3a8468c9b61a50336d8e3303dce74e" - integrity sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A== +webpack@^4.41.5: + version "4.41.5" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.5.tgz#3210f1886bce5310e62bb97204d18c263341b77c" + integrity sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" @@ -10862,7 +10857,7 @@ webpack@^4.41.2: node-libs-browser "^2.2.1" schema-utils "^1.0.0" tapable "^1.1.3" - terser-webpack-plugin "^1.4.1" + terser-webpack-plugin "^1.4.3" watchpack "^1.6.0" webpack-sources "^1.4.1" From fd31dc0f3929f468a2450e7ca2edf5ee7e6b904c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 30 Dec 2019 18:30:24 +0100 Subject: [PATCH 24/44] Fix error when searching for empty phrase (#12711) Fix #12619 --- app/lib/search_query_transformer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/search_query_transformer.rb b/app/lib/search_query_transformer.rb index 6a299f59d8..e07ebfffed 100644 --- a/app/lib/search_query_transformer.rb +++ b/app/lib/search_query_transformer.rb @@ -78,7 +78,7 @@ class SearchQueryTransformer < Parslet::Transform elsif clause[:shortcode] TermClause.new(prefix, operator, ":#{clause[:term]}:") elsif clause[:phrase] - PhraseClause.new(prefix, operator, clause[:phrase].map { |p| p[:term].to_s }.join(' ')) + PhraseClause.new(prefix, operator, clause[:phrase].is_a?(Array) ? clause[:phrase].map { |p| p[:term].to_s }.join(' ') : clause[:phrase].to_s) else raise "Unexpected clause type: #{clause}" end From 6b20921c881423c15d451501d5178abb7d2bd891 Mon Sep 17 00:00:00 2001 From: ThibG Date: Mon, 30 Dec 2019 19:13:02 +0100 Subject: [PATCH 25/44] Remove unused AccountRelationshipsPresenter call in public pages (#12734) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those were used to show a “follow” or “unfollow” button on account grid on public pages, but that got removed a while ago. --- app/controllers/follower_accounts_controller.rb | 1 - app/controllers/following_accounts_controller.rb | 1 - 2 files changed, 2 deletions(-) diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb index 705ff41226..ef183eca7f 100644 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@ -18,7 +18,6 @@ class FollowerAccountsController < ApplicationController 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 diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb index 968de980d1..fb1eaaa377 100644 --- a/app/controllers/following_accounts_controller.rb +++ b/app/controllers/following_accounts_controller.rb @@ -18,7 +18,6 @@ class FollowingAccountsController < ApplicationController 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 From c72c27756f660d0424821c03ffc9051b82372327 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 30 Dec 2019 19:20:43 +0100 Subject: [PATCH 26/44] Fix IDN mentions not being processed, IDN domains not being rendered (#12715) This changes the REST API to return unicode domains in the `acct` attribute instead of punycode, and to render unicode instead of punycode on public HTML pages as well. Fix #7812, fix #12246 --- app/helpers/accounts_helper.rb | 2 +- app/models/account.rb | 6 ++- app/serializers/rest/account_serializer.rb | 4 ++ app/services/process_mentions_service.rb | 11 ++++- .../services/process_mentions_service_spec.rb | 46 ++++++++++++------- 5 files changed, 50 insertions(+), 19 deletions(-) diff --git a/app/helpers/accounts_helper.rb b/app/helpers/accounts_helper.rb index 99815be7be..53939adfcb 100644 --- a/app/helpers/accounts_helper.rb +++ b/app/helpers/accounts_helper.rb @@ -13,7 +13,7 @@ module AccountsHelper if account.local? "@#{account.acct}@#{Rails.configuration.x.local_domain}" else - "@#{account.acct}" + "@#{account.pretty_acct}" end end diff --git a/app/models/account.rb b/app/models/account.rb index 884332e5ab..feaf273c1f 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -50,7 +50,7 @@ class Account < ApplicationRecord USERNAME_RE = /[a-z0-9_]+([a-z0-9_\.-]+[a-z0-9_]+)?/i - MENTION_RE = /(?<=^|[^\/[:word:]])@((#{USERNAME_RE})(?:@[a-z0-9\.\-]+[a-z0-9]+)?)/i + MENTION_RE = /(?<=^|[^\/[:word:]])@((#{USERNAME_RE})(?:@[[:word:]\.\-]+[a-z0-9]+)?)/i include AccountAssociations include AccountAvatar @@ -164,6 +164,10 @@ class Account < ApplicationRecord local? ? username : "#{username}@#{domain}" end + def pretty_acct + local? ? username : "#{username}@#{Addressable::IDNA.to_unicode(domain)}" + end + def local_username_and_domain "#{username}@#{Rails.configuration.x.local_domain}" end diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb index 5fec756738..fd361a34cb 100644 --- a/app/serializers/rest/account_serializer.rb +++ b/app/serializers/rest/account_serializer.rb @@ -24,6 +24,10 @@ class REST::AccountSerializer < ActiveModel::Serializer object.id.to_s end + def acct + object.pretty_acct + end + def note Formatter.instance.simplified_format(object) end diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index 2f7a9e985b..b2d8681654 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -14,7 +14,16 @@ class ProcessMentionsService < BaseService mentions = [] status.text = status.text.gsub(Account::MENTION_RE) do |match| - username, domain = Regexp.last_match(1).split('@') + username, domain = Regexp.last_match(1).split('@') + + domain = begin + if TagManager.instance.local_domain?(domain) + nil + else + TagManager.instance.normalize_domain(domain) + end + end + mentioned_account = Account.find_remote(username, domain) if mention_undeliverable?(mentioned_account) diff --git a/spec/services/process_mentions_service_spec.rb b/spec/services/process_mentions_service_spec.rb index b1abd79b0f..c30de8eeb9 100644 --- a/spec/services/process_mentions_service_spec.rb +++ b/spec/services/process_mentions_service_spec.rb @@ -5,11 +5,11 @@ RSpec.describe ProcessMentionsService, type: :service do let(:visibility) { :public } let(:status) { Fabricate(:status, account: account, text: "Hello @#{remote_user.acct}", visibility: visibility) } + subject { ProcessMentionsService.new } + context 'OStatus with public toot' do let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :ostatus, domain: 'example.com', salmon_url: 'http://salmon.example.com') } - subject { ProcessMentionsService.new } - before do stub_request(:post, remote_user.salmon_url) subject.call(status) @@ -24,8 +24,6 @@ RSpec.describe ProcessMentionsService, type: :service do let(:visibility) { :private } let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :ostatus, domain: 'example.com', salmon_url: 'http://salmon.example.com') } - subject { ProcessMentionsService.new } - before do stub_request(:post, remote_user.salmon_url) subject.call(status) @@ -41,29 +39,45 @@ RSpec.describe ProcessMentionsService, type: :service do end context 'ActivityPub' do - let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') } + context do + let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') } - subject { ProcessMentionsService.new } + before do + stub_request(:post, remote_user.inbox_url) + subject.call(status) + end - before do - stub_request(:post, remote_user.inbox_url) - subject.call(status) - end + it 'creates a mention' do + expect(remote_user.mentions.where(status: status).count).to eq 1 + end - it 'creates a mention' do - expect(remote_user.mentions.where(status: status).count).to eq 1 + it 'sends activity to the inbox' do + expect(a_request(:post, remote_user.inbox_url)).to have_been_made.once + end end - it 'sends activity to the inbox' do - expect(a_request(:post, remote_user.inbox_url)).to have_been_made.once + context 'with an IDN domain' do + let(:remote_user) { Fabricate(:account, username: 'sneak', protocol: :activitypub, domain: 'xn--hresiar-mxa.ch', inbox_url: 'http://example.com/inbox') } + let(:status) { Fabricate(:status, account: account, text: "Hello @sneak@hæresiar.ch") } + + before do + stub_request(:post, remote_user.inbox_url) + subject.call(status) + end + + it 'creates a mention' do + expect(remote_user.mentions.where(status: status).count).to eq 1 + end + + it 'sends activity to the inbox' do + expect(a_request(:post, remote_user.inbox_url)).to have_been_made.once + end end end context 'Temporarily-unreachable ActivityPub user' do let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox', last_webfingered_at: nil) } - subject { ProcessMentionsService.new } - before do stub_request(:get, "https://example.com/.well-known/host-meta").to_return(status: 404) stub_request(:get, "https://example.com/.well-known/webfinger?resource=acct:remote_user@example.com").to_return(status: 500) From c3ef5d76289672ee2f472d7b0540c5ee38cc6f72 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 31 Dec 2019 00:54:38 +0100 Subject: [PATCH 27/44] Fix error when fetching followers/following from REST API when user has network hidden (#12716) Fix #12510 --- app/controllers/api/v1/accounts/follower_accounts_controller.rb | 2 +- .../api/v1/accounts/following_accounts_controller.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index 2dabb8398c..950e9acf0e 100644 --- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb @@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController end def hide_results? - (@account.user_hides_network? && current_account.id != @account.id) || (current_account && @account.blocking?(current_account)) + (@account.user_hides_network? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb index 44e89804b3..b1433af5e4 100644 --- a/app/controllers/api/v1/accounts/following_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb @@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController end def hide_results? - (@account.user_hides_network? && current_account.id != @account.id) || (current_account && @account.blocking?(current_account)) + (@account.user_hides_network? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts From f0cca7a79fd5151548b3454ef3b46b6efab70ee7 Mon Sep 17 00:00:00 2001 From: ThibG Date: Tue, 31 Dec 2019 00:55:32 +0100 Subject: [PATCH 28/44] Hide blocked users from more places (#12733) * Hide blocked, muted, and blocked-by users from toot favourite lists * Hide blocked, muted, and blocked-by users from toot reblog lists * Hide blocked, muted, and blocked-by users from followers/following (API) * Fix tests * Hide blocked, muted, and blocked-by users from followers/following on public pages --- .../accounts/follower_accounts_controller.rb | 4 ++- .../accounts/following_accounts_controller.rb | 4 ++- .../favourited_by_accounts_controller.rb | 4 ++- .../reblogged_by_accounts_controller.rb | 4 ++- .../follower_accounts_controller.rb | 6 ++++- .../following_accounts_controller.rb | 6 ++++- .../follower_accounts_controller_spec.rb | 27 ++++++++++++++++--- .../following_accounts_controller_spec.rb | 27 ++++++++++++++++--- .../favourited_by_accounts_controller_spec.rb | 20 ++++++++++++-- .../reblogged_by_accounts_controller_spec.rb | 20 ++++++++++++-- .../follower_accounts_controller_spec.rb | 12 +++++++++ .../following_accounts_controller_spec.rb | 12 +++++++++ 12 files changed, 128 insertions(+), 18 deletions(-) diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index 950e9acf0e..e360b8a929 100644 --- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb @@ -21,7 +21,9 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController def load_accounts return [] if hide_results? - default_accounts.merge(paginated_follows).to_a + scope = default_accounts + scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? + scope.merge(paginated_follows).to_a end def hide_results? diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb index b1433af5e4..a405b365f2 100644 --- a/app/controllers/api/v1/accounts/following_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb @@ -21,7 +21,9 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController def load_accounts return [] if hide_results? - default_accounts.merge(paginated_follows).to_a + scope = default_accounts + scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? + scope.merge(paginated_follows).to_a end def hide_results? diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb index 657e578319..99eff360ec 100644 --- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb @@ -17,7 +17,9 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController private def load_accounts - default_accounts.merge(paginated_favourites).to_a + scope = default_accounts + scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? + scope.merge(paginated_favourites).to_a end def default_accounts diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb index 6851099f66..cc285ad231 100644 --- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb @@ -17,7 +17,9 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController private def load_accounts - default_accounts.merge(paginated_statuses).to_a + scope = default_accounts + scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? + scope.merge(paginated_statuses).to_a end def default_accounts diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb index ef183eca7f..7103749ade 100644 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@ -36,7 +36,11 @@ class FollowerAccountsController < ApplicationController private def follows - @follows ||= Follow.where(target_account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account) + return @follows if defined?(@follows) + + scope = Follow.where(target_account: @account) + scope = scope.where.not(account_id: current_account.excluded_from_timeline_account_ids) if user_signed_in? + @follows = scope.recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account) end def page_requested? diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb index fb1eaaa377..6c8fb84d86 100644 --- a/app/controllers/following_accounts_controller.rb +++ b/app/controllers/following_accounts_controller.rb @@ -36,7 +36,11 @@ class FollowingAccountsController < ApplicationController private def follows - @follows ||= Follow.where(account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account) + return @follows if defined?(@follows) + + scope = Follow.where(account: @account) + scope = scope.where.not(target_account_id: current_account.excluded_from_timeline_account_ids) if user_signed_in? + @follows = scope.recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account) end def page_requested? diff --git a/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb b/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb index 75e0570e92..54587187ff 100644 --- a/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb @@ -3,19 +3,38 @@ require 'rails_helper' describe Api::V1::Accounts::FollowerAccountsController do render_views - let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') } + let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') } + let(:account) { Fabricate(:account) } + let(:alice) { Fabricate(:account) } + let(:bob) { Fabricate(:account) } before do - Fabricate(:follow, target_account: user.account) + alice.follow!(account) + bob.follow!(account) allow(controller).to receive(:doorkeeper_token) { token } end describe 'GET #index' do it 'returns http success' do - get :index, params: { account_id: user.account.id, limit: 1 } + get :index, params: { account_id: account.id, limit: 2 } expect(response).to have_http_status(200) end + + it 'returns accounts following the given account' do + get :index, params: { account_id: account.id, limit: 2 } + + expect(body_as_json.size).to eq 2 + expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) + end + + it 'does not return blocked users' do + user.account.block!(bob) + get :index, params: { account_id: account.id, limit: 2 } + + expect(body_as_json.size).to eq 1 + expect(body_as_json[0][:id]).to eq alice.id.to_s + end end end diff --git a/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb b/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb index 7f7105ad3a..a580a73684 100644 --- a/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb @@ -3,19 +3,38 @@ require 'rails_helper' describe Api::V1::Accounts::FollowingAccountsController do render_views - let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') } + let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') } + let(:account) { Fabricate(:account) } + let(:alice) { Fabricate(:account) } + let(:bob) { Fabricate(:account) } before do - Fabricate(:follow, account: user.account) + account.follow!(alice) + account.follow!(bob) allow(controller).to receive(:doorkeeper_token) { token } end describe 'GET #index' do it 'returns http success' do - get :index, params: { account_id: user.account.id, limit: 1 } + get :index, params: { account_id: account.id, limit: 2 } expect(response).to have_http_status(200) end + + it 'returns accounts followed by the given account' do + get :index, params: { account_id: account.id, limit: 2 } + + expect(body_as_json.size).to eq 2 + expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) + end + + it 'does not return blocked users' do + user.account.block!(bob) + get :index, params: { account_id: account.id, limit: 2 } + + expect(body_as_json.size).to eq 1 + expect(body_as_json[0][:id]).to eq alice.id.to_s + end end end diff --git a/spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb b/spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb index 40f75c700f..f053ae5738 100644 --- a/spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb +++ b/spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb @@ -6,6 +6,8 @@ RSpec.describe Api::V1::Statuses::FavouritedByAccountsController, type: :control let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') } let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') } + let(:alice) { Fabricate(:account) } + let(:bob) { Fabricate(:account) } context 'with an oauth token' do before do @@ -16,14 +18,28 @@ RSpec.describe Api::V1::Statuses::FavouritedByAccountsController, type: :control let(:status) { Fabricate(:status, account: user.account) } before do - Fabricate(:favourite, status: status) + Favourite.create!(account: alice, status: status) + Favourite.create!(account: bob, status: status) end it 'returns http success' do - get :index, params: { status_id: status.id, limit: 1 } + get :index, params: { status_id: status.id, limit: 2 } expect(response).to have_http_status(200) expect(response.headers['Link'].links.size).to eq(2) end + + it 'returns accounts who favorited the status' do + get :index, params: { status_id: status.id, limit: 2 } + expect(body_as_json.size).to eq 2 + expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) + end + + it 'does not return blocked users' do + user.account.block!(bob) + get :index, params: { status_id: status.id, limit: 2 } + expect(body_as_json.size).to eq 1 + expect(body_as_json[0][:id]).to eq alice.id.to_s + end end end diff --git a/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb b/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb index d758786dc9..60908b7b38 100644 --- a/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb +++ b/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb @@ -6,6 +6,8 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController, type: :controll let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') } let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') } + let(:alice) { Fabricate(:account) } + let(:bob) { Fabricate(:account) } context 'with an oauth token' do before do @@ -16,14 +18,28 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController, type: :controll let(:status) { Fabricate(:status, account: user.account) } before do - Fabricate(:status, reblog_of_id: status.id) + Fabricate(:status, account: alice, reblog_of_id: status.id) + Fabricate(:status, account: bob, reblog_of_id: status.id) end it 'returns http success' do - get :index, params: { status_id: status.id, limit: 1 } + get :index, params: { status_id: status.id, limit: 2 } expect(response).to have_http_status(200) expect(response.headers['Link'].links.size).to eq(2) end + + it 'returns accounts who reblogged the status' do + get :index, params: { status_id: status.id, limit: 2 } + expect(body_as_json.size).to eq 2 + expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) + end + + it 'does not return blocked users' do + user.account.block!(bob) + get :index, params: { status_id: status.id, limit: 2 } + expect(body_as_json.size).to eq 1 + expect(body_as_json[0][:id]).to eq alice.id.to_s + end end end diff --git a/spec/controllers/follower_accounts_controller_spec.rb b/spec/controllers/follower_accounts_controller_spec.rb index 83032ab646..34a0cf3f48 100644 --- a/spec/controllers/follower_accounts_controller_spec.rb +++ b/spec/controllers/follower_accounts_controller_spec.rb @@ -22,6 +22,18 @@ describe FollowerAccountsController do expect(assigned[0]).to eq follow1 expect(assigned[1]).to eq follow0 end + + it 'does not assign blocked users' do + user = Fabricate(:user) + user.account.block!(follower0) + sign_in(user) + + expect(response).to have_http_status(200) + + assigned = assigns(:follows).to_a + expect(assigned.size).to eq 1 + expect(assigned[0]).to eq follow1 + end end context 'when format is json' do diff --git a/spec/controllers/following_accounts_controller_spec.rb b/spec/controllers/following_accounts_controller_spec.rb index d5e4ee587f..e9a1f597df 100644 --- a/spec/controllers/following_accounts_controller_spec.rb +++ b/spec/controllers/following_accounts_controller_spec.rb @@ -22,6 +22,18 @@ describe FollowingAccountsController do expect(assigned[0]).to eq follow1 expect(assigned[1]).to eq follow0 end + + it 'does not assign blocked users' do + user = Fabricate(:user) + user.account.block!(followee0) + sign_in(user) + + expect(response).to have_http_status(200) + + assigned = assigns(:follows).to_a + expect(assigned.size).to eq 1 + expect(assigned[0]).to eq follow1 + end end context 'when format is json' do From 7930f51fac78804fc7183df26db2ba8c15c30b91 Mon Sep 17 00:00:00 2001 From: Matt Panaro Date: Tue, 31 Dec 2019 15:39:25 -0500 Subject: [PATCH 29/44] refactor IntersectionObserver to observe viewport in single-column mode (#12735) --- app/javascript/mastodon/components/scrollable_list.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js index 6338ccd5c5..e4adabb369 100644 --- a/app/javascript/mastodon/components/scrollable_list.js +++ b/app/javascript/mastodon/components/scrollable_list.js @@ -210,10 +210,13 @@ export default class ScrollableList extends PureComponent { } attachIntersectionObserver () { - this.intersectionObserverWrapper.connect({ + let nodeOptions = { root: this.node, rootMargin: '300% 0px', - }); + }; + + this.intersectionObserverWrapper + .connect(this.props.bindToDocument ? {} : nodeOptions); } detachIntersectionObserver () { From dd8d0c7d9d32854147b3a0cef7322b4eead0995d Mon Sep 17 00:00:00 2001 From: Sasha Sorokin Date: Wed, 1 Jan 2020 04:15:05 +0700 Subject: [PATCH 30/44] Add translation project promotion link (#12736) This commit adds promotional notice on appearance settings about translation project if any other locale than English is used. It allows users to learn and contribute translations to Mastodon. Step ahead, in this commit one unusual string is added - link to a guide. By default it refers to Crowdin project itself, but if any of Mastodon localization teams established their own guide, they can refer it. Or, if Crowdin supports localized domain for language, it can also be put there (e.g. https://fr.crowdin.com/...). --- app/views/settings/preferences/appearance/show.html.haml | 4 ++++ config/locales/en.yml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index 9ed83fb930..d2b05513e3 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -8,6 +8,10 @@ .fields-group.fields-row__column.fields-row__column-6 = f.input :setting_theme, collection: Themes.instance.names, label_method: lambda { |theme| I18n.t("themes.#{theme}", default: theme) }, wrapper: :with_label, include_blank: false, hint: false + - unless I18n.locale == :en + .flash-message{ style: "text-align: unset; color: unset" } + #{t 'appearance.localization.body'} #{content_tag(:a, t('appearance.localization.guide_link_text'), href: t('appearance.localization.guide_link'), target: "_blank", rel: "noopener", style: "text-decoration: underline")} + %h4= t 'appearance.advanced_web_interface' %p.hint= t 'appearance.advanced_web_interface_hint' diff --git a/config/locales/en.yml b/config/locales/en.yml index c7179d304f..42bd81e405 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -581,6 +581,10 @@ en: animations_and_accessibility: Animations and accessibility confirmation_dialogs: Confirmation dialogs discovery: Discovery + localization: + body: Mastodon is translated by volunteers. + guide_link: https://crowdin.com/project/mastodon + guide_link_text: Everyone can contribute. sensitive_content: Sensitive content toot_layout: Toot layout application_mailer: From e8b07657c291c0a984e745974a2bc2fecfb48738 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 2 Jan 2020 17:14:58 +0100 Subject: [PATCH 31/44] Fix uncaught query param encoding errors (#12741) --- .../handle_bad_encoding_middleware.rb | 18 ++++++++++++++++ config/application.rb | 2 ++ config/initializers/rack_attack.rb | 3 --- .../handle_bad_encoding_middleware_spec.rb | 21 +++++++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 app/middleware/handle_bad_encoding_middleware.rb create mode 100644 spec/middleware/handle_bad_encoding_middleware_spec.rb diff --git a/app/middleware/handle_bad_encoding_middleware.rb b/app/middleware/handle_bad_encoding_middleware.rb new file mode 100644 index 0000000000..6fce84b152 --- /dev/null +++ b/app/middleware/handle_bad_encoding_middleware.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true +# See: https://jamescrisp.org/2018/05/28/fixing-invalid-query-parameters-invalid-encoding-in-a-rails-app/ + +class HandleBadEncodingMiddleware + def initialize(app) + @app = app + end + + def call(env) + begin + Rack::Utils.parse_nested_query(env['QUERY_STRING'].to_s) + rescue Rack::Utils::InvalidParameterError + env['QUERY_STRING'] = '' + end + + @app.call(env) + end +end diff --git a/config/application.rb b/config/application.rb index e1f7ae707d..58e59fd51b 100644 --- a/config/application.rb +++ b/config/application.rb @@ -7,6 +7,7 @@ require 'rails/all' Bundler.require(*Rails.groups) require_relative '../app/lib/exceptions' +require_relative '../app/middleware/handle_bad_encoding_middleware' require_relative '../lib/paperclip/lazy_thumbnail' require_relative '../lib/paperclip/gif_transcoder' require_relative '../lib/paperclip/video_transcoder' @@ -118,6 +119,7 @@ module Mastodon config.active_job.queue_adapter = :sidekiq + config.middleware.insert_before Rack::Runtime, HandleBadEncodingMiddleware config.middleware.use Rack::Attack config.middleware.use Rack::Deflater diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb index 273cac9ca3..3cd7ea3a6b 100644 --- a/config/initializers/rack_attack.rb +++ b/config/initializers/rack_attack.rb @@ -46,10 +46,7 @@ class Rack::Attack PROTECTED_PATHS_REGEX = Regexp.union(PROTECTED_PATHS.map { |path| /\A#{Regexp.escape(path)}/ }) - # Always allow requests from localhost - # (blocklist & throttles are skipped) Rack::Attack.safelist('allow from localhost') do |req| - # Requests are allowed if the return value is truthy req.remote_ip == '127.0.0.1' || req.remote_ip == '::1' end diff --git a/spec/middleware/handle_bad_encoding_middleware_spec.rb b/spec/middleware/handle_bad_encoding_middleware_spec.rb new file mode 100644 index 0000000000..8c0d24f182 --- /dev/null +++ b/spec/middleware/handle_bad_encoding_middleware_spec.rb @@ -0,0 +1,21 @@ +require 'rails_helper' + +RSpec.describe HandleBadEncodingMiddleware do + let(:app) { double() } + let(:middleware) { HandleBadEncodingMiddleware.new(app) } + + it "request with query string is unchanged" do + expect(app).to receive(:call).with("PATH" => "/some/path", "QUERY_STRING" => "name=fred") + middleware.call("PATH" => "/some/path", "QUERY_STRING" => "name=fred") + end + + it "request with no query string is unchanged" do + expect(app).to receive(:call).with("PATH" => "/some/path") + middleware.call("PATH" => "/some/path") + end + + it "request with invalid encoding in query string drops query string" do + expect(app).to receive(:call).with("QUERY_STRING" => "", "PATH" => "/some/path") + middleware.call("QUERY_STRING" => "q=%2Fsearch%2Fall%Forder%3Ddescending%26page%3D5%26sort%3Dcreated_at", "PATH" => "/some/path") + end +end From 4fcd1d59a9a6b79b7cfd9aeed85945dc0a817343 Mon Sep 17 00:00:00 2001 From: ThibG Date: Thu, 2 Jan 2020 20:52:39 +0100 Subject: [PATCH 32/44] Fix RefollowWorker not keeping show_reblogs setting (#12707) * Fix RefollowWorker not keeping show_reblogs setting * Fix RefollowWorker --- app/workers/refollow_worker.rb | 9 ++++++--- spec/workers/refollow_worker_spec.rb | 30 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 spec/workers/refollow_worker_spec.rb diff --git a/app/workers/refollow_worker.rb b/app/workers/refollow_worker.rb index 12f2bf671b..9b07ce1b56 100644 --- a/app/workers/refollow_worker.rb +++ b/app/workers/refollow_worker.rb @@ -7,15 +7,18 @@ class RefollowWorker def perform(target_account_id) target_account = Account.find(target_account_id) - return unless target_account.protocol == :activitypub + return unless target_account.activitypub? + + target_account.passive_relationships.where(account: Account.where(domain: nil)).includes(:account).reorder(nil).find_each do |follow| + reblogs = follow.show_reblogs? - target_account.followers.where(domain: nil).reorder(nil).find_each do |follower| # Locally unfollow remote account + follower = follow.account follower.unfollow!(target_account) # Schedule re-follow begin - FollowService.new.call(follower, target_account) + FollowService.new.call(follower, target_account, reblogs: reblogs) rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound, Mastodon::UnexpectedResponseError, HTTP::Error, OpenSSL::SSL::SSLError next end diff --git a/spec/workers/refollow_worker_spec.rb b/spec/workers/refollow_worker_spec.rb new file mode 100644 index 0000000000..29771aa59b --- /dev/null +++ b/spec/workers/refollow_worker_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe RefollowWorker do + subject { described_class.new } + let(:account) { Fabricate(:account, domain: 'example.org', protocol: :activitypub) } + let(:alice) { Fabricate(:account, domain: nil, username: 'alice') } + let(:bob) { Fabricate(:account, domain: nil, username: 'bob') } + + describe 'perform' do + let(:service) { double } + + before do + allow(FollowService).to receive(:new).and_return(service) + allow(service).to receive(:call) + + alice.follow!(account, reblogs: true) + bob.follow!(account, reblogs: false) + end + + it 'calls FollowService for local followers' do + result = subject.perform(account.id) + + expect(result).to be_nil + expect(service).to have_received(:call).with(alice, account, reblogs: true) + expect(service).to have_received(:call).with(bob, account, reblogs: false) + end + end +end From af4be412f5ff66f26058b9041b9549e337ce0d0b Mon Sep 17 00:00:00 2001 From: Matt Panaro Date: Thu, 2 Jan 2020 16:46:42 -0500 Subject: [PATCH 33/44] Fix 12661 (#12744) * Revert "persist last-intersected status update and restore when ScrollableList is restored" This reverts commit 07e26142ef6a8e74bd2ac5e9b461a5a1699bd4c8. accidentally merged spurious code in https://github.com/tootsuite/mastodon/pull/12661. https://github.com/tootsuite/mastodon/pull/12735 removes the slowdown that this code was trying to solve; and other functionality successfully restores the view state of the list * Revert "cache currently-viewing status id to avoid calling redux with identical value" This reverts commit c93df2159fbd3888a5c48d8a8b8ae61dbbc54b89. accidentally merged spurious code in https://github.com/tootsuite/mastodon/pull/12661. https://github.com/tootsuite/mastodon/pull/12735 removes the slowdown that this code was trying to solve; and other functionality successfully restores the view state of the list --- app/javascript/mastodon/actions/timelines.js | 8 -------- .../mastodon/components/intersection_observer_article.js | 6 ------ app/javascript/mastodon/components/scrollable_list.js | 4 ---- app/javascript/mastodon/components/status_list.js | 9 --------- .../features/ui/containers/status_list_container.js | 4 +--- app/javascript/mastodon/reducers/timelines.js | 4 ---- 6 files changed, 1 insertion(+), 34 deletions(-) diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js index 1a634b55d9..bc2ac5e823 100644 --- a/app/javascript/mastodon/actions/timelines.js +++ b/app/javascript/mastodon/actions/timelines.js @@ -17,14 +17,6 @@ export const TIMELINE_LOAD_PENDING = 'TIMELINE_LOAD_PENDING'; export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT'; export const TIMELINE_CONNECT = 'TIMELINE_CONNECT'; -export const CURRENTLY_VIEWING = 'CURRENTLY_VIEWING'; - -export const updateCurrentlyViewing = (timeline, id) => ({ - type: CURRENTLY_VIEWING, - timeline, - id, -}); - export const loadPending = timeline => ({ type: TIMELINE_LOAD_PENDING, timeline, diff --git a/app/javascript/mastodon/components/intersection_observer_article.js b/app/javascript/mastodon/components/intersection_observer_article.js index d475e5d1c0..e453730ba4 100644 --- a/app/javascript/mastodon/components/intersection_observer_article.js +++ b/app/javascript/mastodon/components/intersection_observer_article.js @@ -20,8 +20,6 @@ export default class IntersectionObserverArticle extends React.Component { cachedHeight: PropTypes.number, onHeightChange: PropTypes.func, children: PropTypes.node, - currentlyViewing: PropTypes.number, - updateCurrentlyViewing: PropTypes.func, }; state = { @@ -50,8 +48,6 @@ export default class IntersectionObserverArticle extends React.Component { ); this.componentMounted = true; - - if(id === this.props.currentlyViewing) this.node.scrollIntoView(); } componentWillUnmount () { @@ -64,8 +60,6 @@ export default class IntersectionObserverArticle extends React.Component { handleIntersection = (entry) => { this.entry = entry; - if(entry.intersectionRatio > 0.75 && this.props.updateCurrentlyViewing) this.props.updateCurrentlyViewing(this.id); - scheduleIdleTask(this.calculateHeight); this.setState(this.updateStateAfterIntersection); } diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js index e4adabb369..47a87b149a 100644 --- a/app/javascript/mastodon/components/scrollable_list.js +++ b/app/javascript/mastodon/components/scrollable_list.js @@ -36,8 +36,6 @@ export default class ScrollableList extends PureComponent { emptyMessage: PropTypes.node, children: PropTypes.node, bindToDocument: PropTypes.bool, - currentlyViewing: PropTypes.number, - updateCurrentlyViewing: PropTypes.func, }; static defaultProps = { @@ -314,8 +312,6 @@ export default class ScrollableList extends PureComponent { listLength={childrenCount} intersectionObserverWrapper={this.intersectionObserverWrapper} saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null} - currentlyViewing={this.props.currentlyViewing} - updateCurrentlyViewing={this.props.updateCurrentlyViewing} > {React.cloneElement(child, { getScrollPosition: this.getScrollPosition, diff --git a/app/javascript/mastodon/components/status_list.js b/app/javascript/mastodon/components/status_list.js index 82e069601d..e1b370c913 100644 --- a/app/javascript/mastodon/components/status_list.js +++ b/app/javascript/mastodon/components/status_list.js @@ -26,8 +26,6 @@ export default class StatusList extends ImmutablePureComponent { emptyMessage: PropTypes.node, alwaysPrepend: PropTypes.bool, timelineId: PropTypes.string, - currentlyViewing: PropTypes.number, - updateCurrentlyViewing: PropTypes.func, }; static defaultProps = { @@ -60,12 +58,6 @@ export default class StatusList extends ImmutablePureComponent { this.props.onLoadMore(this.props.statusIds.size > 0 ? this.props.statusIds.last() : undefined); }, 300, { leading: true }) - updateCurrentlyViewingWithCache = (id) => { - if(this.cachedCurrentlyViewing === id) return; - this.cachedCurrentlyViewing = id; - this.props.updateCurrentlyViewing(id); - } - _selectChild (index, align_top) { const container = this.node.node; const element = container.querySelector(`article:nth-of-type(${index + 1}) .focusable`); @@ -87,7 +79,6 @@ export default class StatusList extends ImmutablePureComponent { render () { const { statusIds, featuredStatusIds, shouldUpdateScroll, onLoadMore, timelineId, ...other } = this.props; const { isLoading, isPartial } = other; - other.updateCurrentlyViewing = this.updateCurrentlyViewingWithCache; if (isPartial) { return ; diff --git a/app/javascript/mastodon/features/ui/containers/status_list_container.js b/app/javascript/mastodon/features/ui/containers/status_list_container.js index 33af628ca7..9f6cbf988e 100644 --- a/app/javascript/mastodon/features/ui/containers/status_list_container.js +++ b/app/javascript/mastodon/features/ui/containers/status_list_container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import StatusList from '../../../components/status_list'; -import { scrollTopTimeline, loadPending, updateCurrentlyViewing } from '../../../actions/timelines'; +import { scrollTopTimeline, loadPending } from '../../../actions/timelines'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { createSelector } from 'reselect'; import { debounce } from 'lodash'; @@ -39,7 +39,6 @@ const makeMapStateToProps = () => { isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false), hasMore: state.getIn(['timelines', timelineId, 'hasMore']), numPending: getPendingStatusIds(state, { type: timelineId }).size, - currentlyViewing: state.getIn(['timelines', timelineId, 'currentlyViewing'], -1), }); return mapStateToProps; @@ -57,7 +56,6 @@ const mapDispatchToProps = (dispatch, { timelineId }) => ({ onLoadPending: () => dispatch(loadPending(timelineId)), - updateCurrentlyViewing: id => dispatch(updateCurrentlyViewing(timelineId, id)), }); export default connect(makeMapStateToProps, mapDispatchToProps)(StatusList); diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js index 970db425e8..0d7222e10a 100644 --- a/app/javascript/mastodon/reducers/timelines.js +++ b/app/javascript/mastodon/reducers/timelines.js @@ -9,7 +9,6 @@ import { TIMELINE_CONNECT, TIMELINE_DISCONNECT, TIMELINE_LOAD_PENDING, - CURRENTLY_VIEWING, } from '../actions/timelines'; import { ACCOUNT_BLOCK_SUCCESS, @@ -29,7 +28,6 @@ const initialTimeline = ImmutableMap({ hasMore: true, pendingItems: ImmutableList(), items: ImmutableList(), - currentlyViewing: -1, }); const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, isLoadingRecent, usePendingItems) => { @@ -170,8 +168,6 @@ export default function timelines(state = initialState, action) { initialTimeline, map => map.set('online', false).update(action.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items) ); - case CURRENTLY_VIEWING: - return state.update(action.timeline, initialTimeline, map => map.set('currentlyViewing', action.id)); default: return state; } From dfb57c699c760d74c5c0e1b1d9aad8494c08396a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A8r=20Kessels?= Date: Fri, 3 Jan 2020 02:44:06 +0100 Subject: [PATCH 34/44] Add feature test that tests behaviour of profile name and bio (#12658) * Add feature test that tests behaviour of profile name and bio * Fix rubocop style errors in Login Spec. * DRY log_in_spec by reusing the stories helper Co-authored-by: Eugen Rochko --- spec/features/log_in_spec.rb | 36 +++++++++-------- spec/features/profile_spec.rb | 53 +++++++++++++++++++++++++ spec/support/stories/profile_stories.rb | 45 +++++++++++++++++++++ 3 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 spec/features/profile_spec.rb create mode 100644 spec/support/stories/profile_stories.rb diff --git a/spec/features/log_in_spec.rb b/spec/features/log_in_spec.rb index b874c255b3..de1a6de031 100644 --- a/spec/features/log_in_spec.rb +++ b/spec/features/log_in_spec.rb @@ -1,47 +1,51 @@ -require "rails_helper" +# frozen_string_literal: true + +require 'rails_helper' + +feature 'Log in' do + include ProfileStories -feature "Log in" do given(:email) { "test@example.com" } given(:password) { "password" } given(:confirmed_at) { Time.zone.now } background do - Fabricate(:user, email: email, password: password, confirmed_at: confirmed_at) + as_a_registered_user visit new_user_session_path end subject { page } - scenario "A valid email and password user is able to log in" do - fill_in "user_email", with: email - fill_in "user_password", with: password + scenario 'A valid email and password user is able to log in' do + fill_in 'user_email', with: email + fill_in 'user_password', with: password click_on I18n.t('auth.login') - is_expected.to have_css("div.app-holder") + is_expected.to have_css('div.app-holder') end - scenario "A invalid email and password user is not able to log in" do - fill_in "user_email", with: "invalid_email" - fill_in "user_password", with: "invalid_password" + scenario 'A invalid email and password user is not able to log in' do + fill_in 'user_email', with: 'invalid_email' + fill_in 'user_password', with: 'invalid_password' click_on I18n.t('auth.login') - is_expected.to have_css(".flash-message", text: failure_message("invalid")) + is_expected.to have_css('.flash-message', text: failure_message('invalid')) end context do given(:confirmed_at) { nil } - scenario "A unconfirmed user is able to log in" do - fill_in "user_email", with: email - fill_in "user_password", with: password + scenario 'A unconfirmed user is able to log in' do + fill_in 'user_email', with: email + fill_in 'user_password', with: password click_on I18n.t('auth.login') - is_expected.to have_css("div.admin-wrapper") + is_expected.to have_css('div.admin-wrapper') end end def failure_message(message) keys = User.authentication_keys.map { |key| User.human_attribute_name(key) } - I18n.t("devise.failure.#{message}", authentication_keys: keys.join("support.array.words_connector")) + I18n.t("devise.failure.#{message}", authentication_keys: keys.join('support.array.words_connector')) end end diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb new file mode 100644 index 0000000000..3202167cab --- /dev/null +++ b/spec/features/profile_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'rails_helper' + +feature 'Profile' do + include ProfileStories + + given(:local_domain) { ENV['LOCAL_DOMAIN'] } + + background do + as_a_logged_in_user + with_alice_as_local_user + end + + subject { page } + + scenario 'I can view Annes public account' do + visit account_path('alice') + + is_expected.to have_title("alice (@alice@#{local_domain})") + + within('.public-account-header h1') do + is_expected.to have_content("alice @alice@#{local_domain}") + end + + bio_elem = first('.public-account-bio') + expect(bio_elem).to have_content(alice_bio) + # The bio has hashtags made clickable + expect(bio_elem).to have_link('cryptology') + expect(bio_elem).to have_link('science') + # Nicknames are make clickable + expect(bio_elem).to have_link('@alice') + expect(bio_elem).to have_link('@bob') + # Nicknames not on server are not clickable + expect(bio_elem).not_to have_link('@pepe') + end + + scenario 'I can change my account' do + visit settings_profile_path + fill_in 'Display name', with: 'Bob' + fill_in 'Bio', with: 'Bob is silent' + click_on 'Save changes' + is_expected.to have_content 'Changes successfully saved!' + + # View my own public profile and see the changes + click_link "Bob @bob@#{local_domain}" + + within('.public-account-header h1') do + is_expected.to have_content("Bob @bob@#{local_domain}") + end + expect(first('.public-account-bio')).to have_content('Bob is silent') + end +end diff --git a/spec/support/stories/profile_stories.rb b/spec/support/stories/profile_stories.rb new file mode 100644 index 0000000000..75b413330f --- /dev/null +++ b/spec/support/stories/profile_stories.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module ProfileStories + attr_reader :bob, :alice, :alice_bio + + def as_a_registered_user + @bob = Fabricate( + :user, + email: email, password: password, confirmed_at: confirmed_at, + account: Fabricate(:account, username: 'bob') + ) + end + + def as_a_logged_in_user + as_a_registered_user + visit new_user_session_path + fill_in 'user_email', with: email + fill_in 'user_password', with: password + click_on I18n.t('auth.login') + end + + def with_alice_as_local_user + @alice_bio = '@alice and @bob are fictional characters commonly used as'\ + 'placeholder names in #cryptology, as well as #science and'\ + 'engineering 📖 literature. Not affilated with @pepe.' + + @alice = Fabricate( + :user, + email: 'alice@example.com', password: password, confirmed_at: confirmed_at, + account: Fabricate(:account, username: 'alice', note: @alice_bio) + ) + end + + def confirmed_at + @confirmed_at ||= Time.zone.now + end + + def email + @email ||= 'test@example.com' + end + + def password + @password ||= 'password' + end +end From 9a1f8c34b0f3f622f1e397d574feb09cdd2832b2 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 3 Jan 2020 05:00:17 +0100 Subject: [PATCH 35/44] Fix cache digesting log noise on status embeds (#12750) --- app/views/statuses/embed.html.haml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/views/statuses/embed.html.haml b/app/views/statuses/embed.html.haml index 6f2ec646fe..2f111f53fc 100644 --- a/app/views/statuses/embed.html.haml +++ b/app/views/statuses/embed.html.haml @@ -1,3 +1,2 @@ -- cache @status do - .activity-stream.activity-stream--headless - = render 'status', status: @status, centered: true, autoplay: @autoplay +.activity-stream.activity-stream--headless + = render 'status', status: @status, centered: true, autoplay: @autoplay From 683b263a43afbee8b368e05a6e528b9c201cd268 Mon Sep 17 00:00:00 2001 From: ThibG Date: Fri, 3 Jan 2020 05:01:45 +0100 Subject: [PATCH 36/44] Fix URL search not returning private toots user has access to (#12742) --- app/services/resolve_url_service.rb | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/app/services/resolve_url_service.rb b/app/services/resolve_url_service.rb index 79b1bad0c2..1a2b0d60cb 100644 --- a/app/services/resolve_url_service.rb +++ b/app/services/resolve_url_service.rb @@ -12,6 +12,8 @@ class ResolveURLService < BaseService process_local_url elsif !fetched_resource.nil? process_url + elsif @on_behalf_of.present? + process_url_from_db end end @@ -24,15 +26,19 @@ class ResolveURLService < BaseService status = FetchRemoteStatusService.new.call(resource_url, body) authorize_with @on_behalf_of, status, :show? unless status.nil? status - elsif fetched_resource.nil? && @on_behalf_of.present? - # It may happen that the resource is a private toot, and thus not fetchable, - # but we can return the toot if we already know about it. - status = Status.find_by(uri: @url) || Status.find_by(url: @url) - authorize_with @on_behalf_of, status, :show? unless status.nil? - status end end + def process_url_from_db + # It may happen that the resource is a private toot, and thus not fetchable, + # but we can return the toot if we already know about it. + status = Status.find_by(uri: @url) || Status.find_by(url: @url) + authorize_with @on_behalf_of, status, :show? unless status.nil? + status + rescue Mastodon::NotPermittedError + nil + end + def fetched_resource @fetched_resource ||= FetchResourceService.new.call(@url) end From 91422d35ed0087476b2ec722d4a04649c2da3e38 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 3 Jan 2020 05:28:56 +0100 Subject: [PATCH 37/44] Fix uncaught unknown format errors in host meta controller (#12747) --- app/controllers/well_known/host_meta_controller.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/controllers/well_known/host_meta_controller.rb b/app/controllers/well_known/host_meta_controller.rb index 2e9298c4ae..2fd6bc7cc9 100644 --- a/app/controllers/well_known/host_meta_controller.rb +++ b/app/controllers/well_known/host_meta_controller.rb @@ -8,12 +8,8 @@ module WellKnown def show @webfinger_template = "#{webfinger_url}?resource={uri}" - - respond_to do |format| - format.xml { render content_type: 'application/xrd+xml' } - end - expires_in 3.days, public: true + render content_type: 'application/xrd+xml', formats: [:xml] end end end From e066de9a3cc4f917212e9d9ec30c7e46489d2a69 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 3 Jan 2020 05:29:08 +0100 Subject: [PATCH 38/44] Fix missing authentication call in filters controller (#12746) --- app/controllers/filters_controller.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/filters_controller.rb b/app/controllers/filters_controller.rb index d2e0fb7390..63d9d9cd37 100644 --- a/app/controllers/filters_controller.rb +++ b/app/controllers/filters_controller.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true class FiltersController < ApplicationController - include Authorization - layout 'admin' + before_action :authenticate_user! before_action :set_filters, only: :index before_action :set_filter, only: [:edit, :update, :destroy] before_action :set_body_classes From bf2b425057a168e315c543fa13102615c411a194 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 3 Jan 2020 05:35:46 +0100 Subject: [PATCH 39/44] Fix resource_owner_from_credentials in Doorkeeper initializer (#12743) - Nil error when e-mail not found - LDAP authentication used in place of PAM authentication --- config/initializers/doorkeeper.rb | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index 7784bec629..e03380cec1 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -8,20 +8,15 @@ Doorkeeper.configure do end resource_owner_from_credentials do |_routes| - if Devise.ldap_authentication - user = User.authenticate_with_ldap({ :email => request.params[:username], :password => request.params[:password] }) - end - - if Devise.pam_authentication - user ||= User.authenticate_with_ldap({ :email => request.params[:username], :password => request.params[:password] }) - end + user = User.authenticate_with_ldap(email: request.params[:username], password: request.params[:password]) if Devise.ldap_authentication + user ||= User.authenticate_with_pam(email: request.params[:username], password: request.params[:password]) if Devise.pam_authentication if user.nil? user = User.find_by(email: request.params[:username]) - user = nil unless user.valid_password?(request.params[:password]) + user = nil unless user&.valid_password?(request.params[:password]) end - user if !user&.otp_required_for_login? + user unless user&.otp_required_for_login? end # If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below. From d0c5a63daf1fa24197083d039f73499688e6069e Mon Sep 17 00:00:00 2001 From: Bastien Durel Date: Fri, 3 Jan 2020 11:57:25 +0100 Subject: [PATCH 40/44] fix unresolved external in @clusterws/cws by upgrading it (#12752) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 707db33758..02bbba2a6f 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@babel/preset-react": "^7.7.4", "@babel/runtime": "^7.7.7", "@gamestdio/websocket": "^0.3.2", - "@clusterws/cws": "^0.16.0", + "@clusterws/cws": "^0.16.1", "array-includes": "^3.1.1", "arrow-key-navigation": "^1.1.0", "autoprefixer": "^9.7.3", diff --git a/yarn.lock b/yarn.lock index d4a4657eb5..4c23f8ae5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -795,10 +795,10 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@clusterws/cws@^0.16.0": - version "0.16.0" - resolved "https://registry.yarnpkg.com/@clusterws/cws/-/cws-0.16.0.tgz#f6116cbf3a8b7ad0657916616ce5f8248746b797" - integrity sha512-YeGpAPIdkBsOnAkmFKVMWEjCKDH900U2if0B+nc1imfv+64AIb2JX2xiTA6BLDLppEgWV5c6bpWESjbHCNblHw== +"@clusterws/cws@^0.16.1": + version "0.16.1" + resolved "https://registry.yarnpkg.com/@clusterws/cws/-/cws-0.16.1.tgz#443c47909601e87b881ffb2c4c83cbf27a228487" + integrity sha512-OamMsXwVppfmwX14Ed1msJJN0KNi+VBQh5AkAqUvIGTcJyHcjpsKjU15wS8QumvEewxx9gvGp7aSDop0/R5Gqg== "@cnakazawa/watch@^1.0.3": version "1.0.3" From 413cb7e861c20b1a6e249658d3175bc69bc134c4 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 4 Jan 2020 01:54:07 +0100 Subject: [PATCH 41/44] Fix base64-encoded file uploads not being possible (#12748) Fix #3804, Fix #5776 --- .../admin/custom_emojis_controller.rb | 4 --- app/controllers/api/v1/media_controller.rb | 3 -- app/controllers/application_controller.rb | 1 + .../concerns/obfuscate_filename.rb | 16 ---------- .../settings/profiles_controller.rb | 5 ---- app/models/concerns/attachmentable.rb | 11 +++++++ app/models/media_attachment.rb | 3 ++ config/initializers/paperclip.rb | 2 ++ .../controllers/api/proofs_controller_spec.rb | 5 +--- .../concerns/obfuscate_filename_spec.rb | 30 ------------------- spec/models/account_spec.rb | 1 + spec/models/media_attachment_spec.rb | 18 +++++++++++ .../models/concerns/account_avatar.rb | 20 +++++++++++++ .../models/concerns/account_header.rb | 23 ++++++++++++++ 14 files changed, 80 insertions(+), 62 deletions(-) delete mode 100644 app/controllers/concerns/obfuscate_filename.rb delete mode 100644 spec/controllers/concerns/obfuscate_filename_spec.rb create mode 100644 spec/support/examples/models/concerns/account_header.rb diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb index 2af90f0513..a446465c93 100644 --- a/app/controllers/admin/custom_emojis_controller.rb +++ b/app/controllers/admin/custom_emojis_controller.rb @@ -2,10 +2,6 @@ module Admin class CustomEmojisController < BaseController - include ObfuscateFilename - - obfuscate_filename [:custom_emoji, :image] - def index authorize :custom_emoji, :index? diff --git a/app/controllers/api/v1/media_controller.rb b/app/controllers/api/v1/media_controller.rb index aaa93b6158..81825db155 100644 --- a/app/controllers/api/v1/media_controller.rb +++ b/app/controllers/api/v1/media_controller.rb @@ -4,9 +4,6 @@ class Api::V1::MediaController < Api::BaseController before_action -> { doorkeeper_authorize! :write, :'write:media' } before_action :require_user! - include ObfuscateFilename - obfuscate_filename :file - respond_to :json def create diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3f92053813..0cfa2b3860 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -24,6 +24,7 @@ class ApplicationController < ActionController::Base rescue_from ActionController::InvalidAuthenticityToken, with: :unprocessable_entity rescue_from ActionController::UnknownFormat, with: :not_acceptable rescue_from ActionController::ParameterMissing, with: :bad_request + rescue_from Paperclip::AdapterRegistry::NoHandlerError, with: :bad_request rescue_from ActiveRecord::RecordNotFound, with: :not_found rescue_from Mastodon::NotPermittedError, with: :forbidden rescue_from HTTP::Error, OpenSSL::SSL::SSLError, with: :internal_server_error diff --git a/app/controllers/concerns/obfuscate_filename.rb b/app/controllers/concerns/obfuscate_filename.rb deleted file mode 100644 index 22736ec3ab..0000000000 --- a/app/controllers/concerns/obfuscate_filename.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -module ObfuscateFilename - extend ActiveSupport::Concern - - class_methods do - def obfuscate_filename(path) - before_action do - file = params.dig(*path) - next if file.nil? - - file.original_filename = SecureRandom.hex(8) + File.extname(file.original_filename) - end - end - end -end diff --git a/app/controllers/settings/profiles_controller.rb b/app/controllers/settings/profiles_controller.rb index 8b640cdca1..19a7ce157f 100644 --- a/app/controllers/settings/profiles_controller.rb +++ b/app/controllers/settings/profiles_controller.rb @@ -1,16 +1,11 @@ # frozen_string_literal: true class Settings::ProfilesController < Settings::BaseController - include ObfuscateFilename - layout 'admin' before_action :authenticate_user! before_action :set_account - obfuscate_filename [:account, :avatar] - obfuscate_filename [:account, :header] - def show @account.build_fields end diff --git a/app/models/concerns/attachmentable.rb b/app/models/concerns/attachmentable.rb index 3bbc6453c7..1e8c4806f6 100644 --- a/app/models/concerns/attachmentable.rb +++ b/app/models/concerns/attachmentable.rb @@ -9,6 +9,7 @@ module Attachmentable GIF_MATRIX_LIMIT = 921_600 # 1280x720px included do + before_post_process :obfuscate_file_name before_post_process :set_file_extensions before_post_process :check_image_dimensions before_post_process :set_file_content_type @@ -68,4 +69,14 @@ module Attachmentable rescue Terrapin::CommandLineError '' end + + def obfuscate_file_name + self.class.attachment_definitions.each_key do |attachment_name| + attachment = send(attachment_name) + + next if attachment.blank? + + attachment.instance_write :file_name, SecureRandom.hex(8) + File.extname(attachment.instance_read(:file_name)) + end + end end diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 573ef5dfc1..1fd0adfd02 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -202,9 +202,12 @@ class MediaAttachment < ApplicationRecord end after_commit :reset_parent_cache, on: :update + before_create :prepare_description, unless: :local? before_create :set_shortcode + before_post_process :set_type_and_extension + before_save :set_meta class << self diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb index 5109baff70..8909678d65 100644 --- a/config/initializers/paperclip.rb +++ b/config/initializers/paperclip.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +Paperclip::DataUriAdapter.register + Paperclip.interpolates :filename do |attachment, style| if style == :original attachment.original_filename diff --git a/spec/controllers/api/proofs_controller_spec.rb b/spec/controllers/api/proofs_controller_spec.rb index dbde4927f1..2fe6150052 100644 --- a/spec/controllers/api/proofs_controller_spec.rb +++ b/spec/controllers/api/proofs_controller_spec.rb @@ -85,10 +85,7 @@ describe Api::ProofsController do end it 'has the correct avatar url' do - first_part = 'https://cb6e6126.ngrok.io/system/accounts/avatars/' - last_part = 'original/avatar.gif' - - expect(body_as_json[:avatar]).to match /#{Regexp.quote(first_part)}(?:\d{3,5}\/){3}#{Regexp.quote(last_part)}/ + expect(body_as_json[:avatar]).to match "https://cb6e6126.ngrok.io#{alice.avatar.url}" end end end diff --git a/spec/controllers/concerns/obfuscate_filename_spec.rb b/spec/controllers/concerns/obfuscate_filename_spec.rb deleted file mode 100644 index e06d53c038..0000000000 --- a/spec/controllers/concerns/obfuscate_filename_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe ApplicationController, type: :controller do - controller do - include ObfuscateFilename - - obfuscate_filename :file - - def file - render plain: params[:file]&.original_filename - end - end - - before do - routes.draw { get 'file' => 'anonymous#file' } - end - - it 'obfusticates filename if the given parameter is specified' do - file = fixture_file_upload('files/imports.txt', 'text/plain') - post 'file', params: { file: file } - expect(response.body).to end_with '.txt' - expect(response.body).not_to include 'imports' - end - - it 'does nothing if the given parameter is not specified' do - post 'file' - end -end diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index b2f6234cb9..3cca9b3439 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -823,4 +823,5 @@ RSpec.describe Account, type: :model do end include_examples 'AccountAvatar', :account + include_examples 'AccountHeader', :account end diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb index 7ddfba7ed9..a275621a13 100644 --- a/spec/models/media_attachment_spec.rb +++ b/spec/models/media_attachment_spec.rb @@ -133,6 +133,24 @@ RSpec.describe MediaAttachment, type: :model do expect(media.file.meta["small"]["height"]).to eq 327 expect(media.file.meta["small"]["aspect"]).to eq 490.0 / 327 end + + it 'gives the file a random name' do + expect(media.file_file_name).to_not eq 'attachment.jpg' + end + end + + describe 'base64-encoded jpeg' do + let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('attachment.jpg').read)}" } + let(:media) { MediaAttachment.create(account: Fabricate(:account), file: base64_attachment) } + + it 'saves media attachment' do + expect(media.persisted?).to be true + expect(media.file).to_not be_nil + end + + it 'gives the file a file name' do + expect(media.file_file_name).to_not be_blank + end end describe 'descriptions for remote attachments' do diff --git a/spec/support/examples/models/concerns/account_avatar.rb b/spec/support/examples/models/concerns/account_avatar.rb index f2a8a2459c..2180f52739 100644 --- a/spec/support/examples/models/concerns/account_avatar.rb +++ b/spec/support/examples/models/concerns/account_avatar.rb @@ -16,4 +16,24 @@ shared_examples 'AccountAvatar' do |fabricator| end end end + + describe 'base64-encoded files' do + let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('attachment.jpg').read)}" } + let(:account) { Fabricate(fabricator, avatar: base64_attachment) } + + it 'saves avatar' do + expect(account.persisted?).to be true + expect(account.avatar).to_not be_nil + end + + it 'gives the avatar a file name' do + expect(account.avatar_file_name).to_not be_blank + end + + it 'saves a new avatar under a different file name' do + previous_file_name = account.avatar_file_name + account.update(avatar: base64_attachment) + expect(account.avatar_file_name).to_not eq previous_file_name + end + end end diff --git a/spec/support/examples/models/concerns/account_header.rb b/spec/support/examples/models/concerns/account_header.rb new file mode 100644 index 0000000000..77ee0e6290 --- /dev/null +++ b/spec/support/examples/models/concerns/account_header.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +shared_examples 'AccountHeader' do |fabricator| + describe 'base64-encoded files' do + let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('attachment.jpg').read)}" } + let(:account) { Fabricate(fabricator, header: base64_attachment) } + + it 'saves header' do + expect(account.persisted?).to be true + expect(account.header).to_not be_nil + end + + it 'gives the header a file name' do + expect(account.header_file_name).to_not be_blank + end + + it 'saves a new header under a different file name' do + previous_file_name = account.header_file_name + account.update(header: base64_attachment) + expect(account.header_file_name).to_not eq previous_file_name + end + end +end From aea32f596cc22ddb17a9b8a0bf06deaa40e11db5 Mon Sep 17 00:00:00 2001 From: Shlee Date: Sun, 5 Jan 2020 05:48:18 +0800 Subject: [PATCH 42/44] Gemfile Updates - fixes warnings (#12759) * Update Gemfile.lock * Update Gemfile.lock * Update Gemfile --- Gemfile | 2 +- Gemfile.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index c7ed114cad..c3bc3b8350 100644 --- a/Gemfile +++ b/Gemfile @@ -60,7 +60,7 @@ gem 'httplog', '~> 1.3' gem 'idn-ruby', require: 'idn' gem 'kaminari', '~> 1.1' gem 'link_header', '~> 0.0' -gem 'mime-types', '~> 3.3', require: 'mime/types/columnar' +gem 'mime-types', '~> 3.3.1', require: 'mime/types/columnar' gem 'nilsimsa', git: 'https://github.com/witgo/nilsimsa', ref: 'fd184883048b922b176939f851338d0a4971a532' gem 'nokogiri', '~> 1.10' gem 'nsa', '~> 0.2' diff --git a/Gemfile.lock b/Gemfile.lock index 9610eccd9a..38f0a24af7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -242,7 +242,7 @@ GEM fabrication (2.21.0) faker (2.10.0) i18n (>= 1.6, < 1.8) - faraday (0.15.4) + faraday (1.0.0) multipart-post (>= 1.2, < 3) fast_blank (1.0.0) fastimage (2.1.7) @@ -372,9 +372,9 @@ GEM microformats (4.1.0) json (~> 2.1) nokogiri (~> 1.8, >= 1.8.3) - mime-types (3.3) + mime-types (3.3.1) mime-types-data (~> 3.2015) - mime-types-data (3.2019.0904) + mime-types-data (3.2019.1009) mimemagic (0.3.3) mini_mime (1.0.2) mini_portile2 (2.4.0) From ad08c874614f83fb8a7b76340e19c7f29dd7722b Mon Sep 17 00:00:00 2001 From: Shlee Date: Sun, 5 Jan 2020 05:48:34 +0800 Subject: [PATCH 43/44] Gemfile Updates - Ruby 2.7 prep (#12758) * Update Gemfile * Update Gemfile --- Gemfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index c3bc3b8350..b6e8453421 100644 --- a/Gemfile +++ b/Gemfile @@ -7,7 +7,7 @@ gem 'pkg-config', '~> 1.4' gem 'puma', '~> 4.3' gem 'rails', '~> 5.2.4' -gem 'sprockets', '~> 3.7' +gem 'sprockets', '~> 3.7.2' gem 'thor', '~> 0.20' gem 'hamlit-rails', '~> 0.2' @@ -31,7 +31,7 @@ gem 'browser' gem 'charlock_holmes', '~> 0.7.7' gem 'iso-639' gem 'chewy', '~> 5.1' -gem 'cld3', '~> 3.2.4' +gem 'cld3', '~> 3.2.6' gem 'devise', '~> 4.7' gem 'devise-two-factor', '~> 3.1' @@ -118,7 +118,7 @@ group :test do gem 'capybara', '~> 3.29' gem 'climate_control', '~> 0.2' gem 'faker', '~> 2.10' - gem 'microformats', '~> 4.1' + gem 'microformats', '~> 4.2' gem 'rails-controller-testing', '~> 1.0' gem 'rspec-sidekiq', '~> 3.0' gem 'simplecov', '~> 0.17', require: false From 1e1db2c508faffc41698d0d03a26756c40c10526 Mon Sep 17 00:00:00 2001 From: Shlee Date: Sun, 5 Jan 2020 05:48:57 +0800 Subject: [PATCH 44/44] Gemfile Updates - Others (#12761) * Update Gemfile.lock * Update Gemfile * Update Gemfile.lock * Update Gemfile.lock * Update Gemfile * Update Gemfile.lock --- Gemfile.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 38f0a24af7..2e86eda193 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -185,7 +185,7 @@ GEM crack (0.4.3) safe_yaml (~> 1.0.0) crass (1.0.5) - css_parser (1.7.0) + css_parser (1.7.1) addressable debug_inspector (0.0.3) derailed_benchmarks (1.4.3) @@ -275,8 +275,8 @@ GEM http (~> 3.0) nokogiri (~> 1.8) oj (~> 3.0) - hamlit (2.9.3) - temple (>= 0.8.0) + hamlit (2.11.0) + temple (>= 0.8.2) thor tilt hamlit-rails (0.2.3) @@ -452,7 +452,7 @@ GEM pry (~> 0.10) pry-rails (0.3.9) pry (>= 0.10.4) - public_suffix (4.0.1) + public_suffix (4.0.2) puma (4.3.1) nio4r (~> 2.0) pundit (2.1.0) @@ -529,7 +529,7 @@ GEM redis-store (1.5.0) redis (>= 2.2, < 5) regexp_parser (1.6.0) - request_store (1.4.1) + request_store (1.5.0) rack (>= 1.4) responders (3.0.0) actionpack (>= 5.0) @@ -622,14 +622,14 @@ GEM multi_json (~> 1.8) strong_migrations (0.5.1) activerecord (>= 5) - temple (0.8.1) + temple (0.8.2) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) terrapin (0.6.0) climate_control (>= 0.0.3, < 1.0) thor (0.20.3) thread_safe (0.3.6) - tilt (2.0.9) + tilt (2.0.10) tty-color (0.5.0) tty-command (0.9.0) pastel (~> 0.7.0) @@ -651,7 +651,7 @@ GEM tzinfo (>= 1.0.0) unf (0.1.4) unf_ext - unf_ext (0.0.7.5) + unf_ext (0.0.7.6) unicode-display_width (1.6.0) uniform_notifier (1.12.1) warden (1.2.8)