From 1287de1b83c45a972248a1375078f63f61009109 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 21 Jan 2018 13:20:00 +0100 Subject: [PATCH 1/5] Fix invalid value passed to full_asset_url in mailers (#6312) --- app/views/notification_mailer/_status.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/notification_mailer/_status.html.haml b/app/views/notification_mailer/_status.html.haml index 85f9294e936..727e914dcc3 100644 --- a/app/views/notification_mailer/_status.html.haml +++ b/app/views/notification_mailer/_status.html.haml @@ -19,7 +19,7 @@ %tbody %tr %td{ align: 'left', width: 48 } - = image_tag full_asset_url(status.account.avatar), alt:'' + = image_tag full_asset_url(status.account.avatar.url), alt:'' %td{ align: 'left' } %bdi= display_name(status.account) = "@#{status.account.acct}" From 31d148588737e5e5dc8aada7913884f226831fd1 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 21 Jan 2018 13:20:20 +0100 Subject: [PATCH 2/5] Display number of follow requests in getting started menu, and (#6313) if notifications column is not mounted, also display number of unread notifications there. --- .../features/getting_started/index.js | 37 +++++++++++++++++-- .../features/ui/components/column_link.js | 7 +++- .../styles/mastodon/components.scss | 11 ++++++ 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js index ee789e18096..3a875169e74 100644 --- a/app/javascript/mastodon/features/getting_started/index.js +++ b/app/javascript/mastodon/features/getting_started/index.js @@ -8,6 +8,8 @@ import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { me } from '../../initial_state'; +import { fetchFollowRequests } from '../../actions/accounts'; +import { List as ImmutableList } from 'immutable'; const messages = defineMessages({ heading: { id: 'getting_started.heading', defaultMessage: 'Getting started' }, @@ -32,9 +34,25 @@ const messages = defineMessages({ const mapStateToProps = state => ({ myAccount: state.getIn(['accounts', me]), columns: state.getIn(['settings', 'columns']), + unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size, + unreadNotifications: state.getIn(['notifications', 'unread']), }); -@connect(mapStateToProps) +const mapDispatchToProps = dispatch => ({ + fetchFollowRequests: () => dispatch(fetchFollowRequests()), +}); + +const badgeDisplay = (number, limit) => { + if (number === 0) { + return undefined; + } else if (limit && number >= limit) { + return `${limit}+`; + } else { + return number; + } +}; + +@connect(mapStateToProps, mapDispatchToProps) @injectIntl export default class GettingStarted extends ImmutablePureComponent { @@ -43,10 +61,21 @@ export default class GettingStarted extends ImmutablePureComponent { myAccount: ImmutablePropTypes.map.isRequired, columns: ImmutablePropTypes.list, multiColumn: PropTypes.bool, + fetchFollowRequests: PropTypes.func.isRequired, + unreadFollowRequests: PropTypes.number, + unreadNotifications: PropTypes.number, }; + componentDidMount () { + const { myAccount, fetchFollowRequests } = this.props; + + if (myAccount.get('locked')) { + fetchFollowRequests(); + } + } + render () { - const { intl, myAccount, columns, multiColumn } = this.props; + const { intl, myAccount, columns, multiColumn, unreadFollowRequests, unreadNotifications } = this.props; const navItems = []; @@ -56,7 +85,7 @@ export default class GettingStarted extends ImmutablePureComponent { } if (!columns.find(item => item.get('id') === 'NOTIFICATIONS')) { - navItems.push(); + navItems.push(); } if (!columns.find(item => item.get('id') === 'COMMUNITY')) { @@ -74,7 +103,7 @@ export default class GettingStarted extends ImmutablePureComponent { ); if (myAccount.get('locked')) { - navItems.push(); + navItems.push(); } if (multiColumn) { diff --git a/app/javascript/mastodon/features/ui/components/column_link.js b/app/javascript/mastodon/features/ui/components/column_link.js index a906162135e..25c2d1cf860 100644 --- a/app/javascript/mastodon/features/ui/components/column_link.js +++ b/app/javascript/mastodon/features/ui/components/column_link.js @@ -2,12 +2,15 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Link } from 'react-router-dom'; -const ColumnLink = ({ icon, text, to, href, method }) => { +const ColumnLink = ({ icon, text, to, href, method, badge }) => { + const badgeElement = typeof badge !== 'undefined' ? {badge} : null; + if (href) { return ( {text} + {badgeElement} ); } else { @@ -15,6 +18,7 @@ const ColumnLink = ({ icon, text, to, href, method }) => { {text} + {badgeElement} ); } @@ -26,6 +30,7 @@ ColumnLink.propTypes = { to: PropTypes.string, href: PropTypes.string, method: PropTypes.string, + badge: PropTypes.node, }; export default ColumnLink; diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 4a9a379a8e2..55cb40c320d 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -2070,6 +2070,17 @@ margin-right: 5px; } +.column-link__badge { + display: inline-block; + border-radius: 4px; + font-size: 12px; + line-height: 19px; + font-weight: 500; + background: $ui-base-color; + padding: 4px 8px; + margin: -6px 10px; +} + .column-subheading { background: $ui-base-color; color: $ui-base-lighter-color; From 112b1fa265f650c01eef2578e286214e3d82dcac Mon Sep 17 00:00:00 2001 From: Aboobacker MK Date: Sun, 21 Jan 2018 17:51:28 +0530 Subject: [PATCH 3/5] Redirect to 2FA creation page when otp_secret is not available (#6314) --- Gemfile.lock | 2 +- .../two_factor_authentication/confirmations_controller.rb | 5 +++++ .../confirmations_controller_spec.rb | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 788da17fed7..69ed3097b83 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -70,7 +70,7 @@ GEM coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) - binding_of_caller (0.7.3) + binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) bootsnap (1.1.5) msgpack (~> 1.0) diff --git a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb index 4cf62db13ef..8d534960d4b 100644 --- a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb +++ b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb @@ -6,6 +6,7 @@ module Settings layout 'admin' before_action :authenticate_user! + before_action :ensure_otp_secret def new prepare_two_factor_form @@ -38,6 +39,10 @@ module Settings @provision_url = current_user.otp_provisioning_uri(current_user.email, issuer: Rails.configuration.x.local_domain) @qrcode = RQRCode::QRCode.new(@provision_url) end + + def ensure_otp_secret + redirect_to settings_two_factor_authentication_path unless current_user.otp_secret + end end end end diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb index 0676d61613f..aee82a3d856 100644 --- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb @@ -6,6 +6,7 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do render_views let(:user) { Fabricate(:user, email: 'local-part@domain', otp_secret: 'thisisasecretforthespecofnewview') } + let(:user_without_otp_secret) { Fabricate(:user, email: 'local-part@domain') } shared_examples 'renders :new' do it 'renders the new view' do @@ -33,6 +34,12 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do get :new expect(response).to redirect_to('/auth/sign_in') end + + it 'redirects if user do not have otp_secret' do + sign_in user_without_otp_secret, scope: :user + get :new + expect(response).to redirect_to('/settings/two_factor_authentication') + end end describe 'POST #create' do From d613dda91d1f1595f73a967eb01c41b07cddacbe Mon Sep 17 00:00:00 2001 From: ThibG Date: Sun, 21 Jan 2018 13:22:31 +0100 Subject: [PATCH 4/5] =?UTF-8?q?Fix=20assets=20loading=20when=20WEB=5FDOMAI?= =?UTF-8?q?N=20=E2=89=A0=20LOCAL=5FDOMAIN=20(#6319)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since 872a0d5bd801c998d911f7da582a60d2f714a710, assets URL are absolute and not relative. Unfortunately, the domain used to build such URLs is the wrong one: LOCAL_DOMAIN, and not WEB_DOMAIN, where the assets are stored. --- config/webpack/configuration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/webpack/configuration.js b/config/webpack/configuration.js index 26747e76b37..07af743f71f 100644 --- a/config/webpack/configuration.js +++ b/config/webpack/configuration.js @@ -27,7 +27,7 @@ function formatPublicPath(host = '', path = '') { const output = { path: resolve('public', settings.public_output_path), - publicPath: formatPublicPath(env.ASSET_HOST || env.LOCAL_DOMAIN, settings.public_output_path), + publicPath: formatPublicPath(env.ASSET_HOST || env.WEB_DOMAIN || env.LOCAL_DOMAIN, settings.public_output_path), }; module.exports = { From cfd2b06821a12f6b4aae427dbb9e6707d1cff9dc Mon Sep 17 00:00:00 2001 From: codl Date: Sun, 21 Jan 2018 13:23:17 +0100 Subject: [PATCH 5/5] fix filter search index being too strict when looking for line breaks (#6318) --- app/javascript/mastodon/reducers/statuses.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/reducers/statuses.js b/app/javascript/mastodon/reducers/statuses.js index 5120b2b67da..cc0d4dacdca 100644 --- a/app/javascript/mastodon/reducers/statuses.js +++ b/app/javascript/mastodon/reducers/statuses.js @@ -54,7 +54,7 @@ const normalizeStatus = (state, status) => { normalStatus.reblog = status.reblog.id; } - const searchContent = [status.spoiler_text, status.content].join('\n\n').replace(/
/g, '\n').replace(/<\/p>

/g, '\n\n'); + const searchContent = [status.spoiler_text, status.content].join('\n\n').replace(//g, '\n').replace(/<\/p>

/g, '\n\n'); const emojiMap = normalStatus.emojis.reduce((obj, emoji) => { obj[`:${emoji.shortcode}:`] = emoji;