From 1155dc08352c3aa1cb763729122c34a3db6e64ec 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 ba2eac8824a85aa9541f8070ed7bcd22b9982cc8 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 31f7c3fc5d9bf24fc79f3246a0de2cc907ecb34d 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 162dc845a04741f15d0d8ca70e17f1ee9ed38841 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 0e8c0287d01d270238aeb7f25c6337b2bcb8afba 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 7a81346d5557053425bc8cf942b05eff0e93fe15 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 7e074610a6651d499267e976f45aadce8cd60d96 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 ca78b1473ec6ea10ea0b42916dc1240371437027 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 353c94910bf02e2cd7f82ae47a55af3164926b3d 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 6e9e8d89fa0dbfe9c3c683c7e7dede8a54d3b6d3 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 e7d3495874bd60d426815c8a9df24ef6e8df5a52 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 54e6c1c47e6294b9c07ab5e74c31998728cac53b 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 0242f8ae8b28c69a03a8475f3edc362fabeeb95a 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 ed34c0401a9c8964a80f865bc84c0424dfafac6a 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 3902b7677ab1aea953532a715bc0f5b81c679a9e 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 a80fb33be4bae46621885038111ec5675e53b332 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 6245075158f5bf79a329e16b9b1622a790524b4b 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 9fe5ba82c533f54db2d0311f68f91f742caf4ec3 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 a2fe2e98eee537eb4d769d2d751fc5afa79e049b 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 333009d8b1c8d9b7476e91500e9371edde5bd911 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 a439fc7f72fa4598635e8388e09ea90cdcb6b6c3 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 d5f93ea6186100f8882f62737611536f66e8d1be 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 5c8a8bf798d33bc7a3b7645cf1e729ccf3ca6e57 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 108e390d231159a6dc3509f8aece1c325296e0c3 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 bb27ca14ef5e2b0b3108c476a62a0e6d559e070a 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 b2f81060b75e5128279cd3f85f55de0982e8f35b 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 f86ee4b59f25727d248609e0afe277a4f69f6be7 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) + 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 - it 'creates a mention' do - expect(remote_user.mentions.where(status: status).count).to eq 1 - end + 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") } - it 'sends activity to the inbox' do - expect(a_request(:post, remote_user.inbox_url)).to have_been_made.once + 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 2999c955968c8d8a6b4a35d13f9b4e7f6769b014 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 3b3bdc7293493735a2169d3377a5a5b7d9006497 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 2a5da8c9613b0ef6659edc60831b4fe8e84f3fc8 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 9edab7afafd6f6db9338ada83a84b2ef14f397a9 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 09d54d1f626163fcc6e282544dfc9939fd3cdfd3 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 aa138ea350dfb2a47ef0b29eff811c6da402a830 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 9cbbc50fcdfe2ec852107b1757d92d54b862a91a 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 6c1ba513ee00443cba684adfe41f62567bd6bb21 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 6a8c8dc6fb67f58f5aadc082fe49d0fcdc5e47ed 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 e4d75f238b751329f1d9729046cc65b7b363c7d8 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 83deae5bd7adf37550bb8e14d1ec696a84555c39 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 47293419034ed64e5d75e8f60621824762edb967 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 59c697a30cae2d50e5be2dd273e5c3956b2a2d6e 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 500276c99bfba2a74e177f46d27d020e3f06a719 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 49b2f7c0a2aa41b1da77b652415078e19fcdcad8 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 882a7d3d1413cae361a618f6686169c5aa599d54 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 3537bb1b5246c148ca31fa4d24750879cdd84e63 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 2ecc7802caf4d272191a7fd582fc97996f750827 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)