diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f4d40229d3353b..222412dd8e0e4a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -34,7 +34,6 @@ class ApplicationController < ActionController::Base helper_method :limited_federation_mode? helper_method :body_class_string helper_method :skip_csrf_meta_tags? - helper_method :sso_redirect rescue_from ActionController::ParameterMissing, Paperclip::AdapterRegistry::NoHandlerError, with: :bad_request rescue_from Mastodon::NotPermittedError, with: :forbidden @@ -88,7 +87,11 @@ def skip_csrf_meta_tags? end def after_sign_out_path_for(_resource_or_scope) - root_path + if ENV['OMNIAUTH_ONLY'] == 'true' && ENV['OIDC_ENABLED'] == 'true' + '/auth/auth/openid_connect/logout' + else + new_user_session_path + end end protected @@ -145,10 +148,6 @@ def omniauth_only? ENV['OMNIAUTH_ONLY'] == 'true' end - def sso_redirect - "/auth/auth/#{Devise.omniauth_providers[0]}" if ENV['OMNIAUTH_ONLY'] == 'true' && Devise.omniauth_providers.length == 1 - end - def sso_account_settings ENV.fetch('SSO_ACCOUNT_SETTINGS', nil) end diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index d593ad98fa0337..8212e2e630ba31 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -11,9 +11,6 @@ class Auth::SessionsController < Devise::SessionsController skip_before_action :require_functional! skip_before_action :update_user_sign_in - # Allow any client to call /auth/sign_out via a delete call - skip_before_action :verify_authenticity_token, only: [:destroy] - prepend_before_action :check_suspicious!, only: [:create] include TwoFactorAuthenticationConcern diff --git a/app/javascript/mastodon/components/column_back_button.jsx b/app/javascript/mastodon/components/column_back_button.jsx index 8d0f25d95e7ddf..74a03b093ab8cc 100644 --- a/app/javascript/mastodon/components/column_back_button.jsx +++ b/app/javascript/mastodon/components/column_back_button.jsx @@ -4,7 +4,7 @@ import { createPortal } from 'react-dom'; import { FormattedMessage } from 'react-intl'; -import { Icon } from 'mastodon/components/icon'; +import { Icon } from 'mastodon/components/icon'; export default class ColumnBackButton extends PureComponent { @@ -30,7 +30,7 @@ export default class ColumnBackButton extends PureComponent { } }; - render() { + render () { const { multiColumn } = this.props; const component = ( diff --git a/app/javascript/mastodon/containers/status_container.jsx b/app/javascript/mastodon/containers/status_container.jsx index f2bba3bdcbee6d..7a7cd9880f0325 100644 --- a/app/javascript/mastodon/containers/status_container.jsx +++ b/app/javascript/mastodon/containers/status_container.jsx @@ -77,7 +77,7 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ - onReply(status, router) { + onReply (status, router) { dispatch((_, getState) => { let state = getState(); @@ -87,8 +87,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ modalProps: { message: intl.formatMessage(messages.replyMessage), confirm: intl.formatMessage(messages.replyConfirm), - onConfirm: () => dispatch(replyCompose(status, router)) - }, + onConfirm: () => dispatch(replyCompose(status, router)) }, })); } else { dispatch(replyCompose(status, router)); @@ -96,7 +95,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }); }, - onModalReblog(status, privacy) { + onModalReblog (status, privacy) { if (status.get('reblogged')) { dispatch(unreblog(status)); } else { @@ -104,7 +103,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onReblog(status, e) { + onReblog (status, e) { if ((e && e.shiftKey) || !boostModal) { this.onModalReblog(status); } else { @@ -112,7 +111,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onFavourite(status) { + onFavourite (status) { if (status.get('favourited')) { dispatch(unfavourite(status)); } else { @@ -120,7 +119,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onBookmark(status) { + onBookmark (status) { if (status.get('bookmarked')) { dispatch(unbookmark(status)); } else { @@ -128,7 +127,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onPin(status) { + onPin (status) { if (status.get('pinned')) { dispatch(unpin(status)); } else { @@ -136,7 +135,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onEmbed(status) { + onEmbed (status) { dispatch(openModal({ modalType: 'EMBED', modalProps: { @@ -146,7 +145,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ })); }, - onDelete(status, history, withRedraft = false) { + onDelete (status, history, withRedraft = false) { if (!deleteModal) { dispatch(deleteStatus(status.get('id'), history, withRedraft)); } else { @@ -161,7 +160,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onEdit(status, history) { + onEdit (status, history) { dispatch((_, getState) => { let state = getState(); if (state.getIn(['compose', 'text']).trim().length !== 0) { @@ -179,7 +178,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }); }, - onTranslate(status) { + onTranslate (status) { if (status.get('translation')) { dispatch(undoStatusTranslation(status.get('id'), status.get('poll'))); } else { @@ -187,54 +186,54 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onDirect(account, router) { + onDirect (account, router) { dispatch(directCompose(account, router)); }, - onMention(account, router) { + onMention (account, router) { dispatch(mentionCompose(account, router)); }, - onOpenMedia(statusId, media, index, lang) { + onOpenMedia (statusId, media, index, lang) { dispatch(openModal({ modalType: 'MEDIA', modalProps: { statusId, media, index, lang }, })); }, - onOpenVideo(statusId, media, lang, options) { + onOpenVideo (statusId, media, lang, options) { dispatch(openModal({ modalType: 'VIDEO', modalProps: { statusId, media, lang, options }, })); }, - onBlock(status) { + onBlock (status) { const account = status.get('account'); dispatch(initBlockModal(account)); }, - onUnblock(account) { + onUnblock (account) { dispatch(unblockAccount(account.get('id'))); }, - onReport(status) { + onReport (status) { dispatch(initReport(status.get('account'), status)); }, - onAddFilter(status) { + onAddFilter (status) { dispatch(initAddFilter(status, { contextType })); }, - onMute(account) { + onMute (account) { dispatch(initMuteModal(account)); }, - onUnmute(account) { + onUnmute (account) { dispatch(unmuteAccount(account.get('id'))); }, - onMuteConversation(status) { + onMuteConversation (status) { if (status.get('muted')) { dispatch(unmuteStatus(status.get('id'))); } else { @@ -242,7 +241,7 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onToggleHidden(status) { + onToggleHidden (status) { if (status.get('hidden')) { dispatch(revealStatus(status.get('id'))); } else { @@ -250,11 +249,11 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ } }, - onToggleCollapsed(status, isCollapsed) { + onToggleCollapsed (status, isCollapsed) { dispatch(toggleStatusCollapse(status.get('id'), isCollapsed)); }, - onBlockDomain(domain) { + onBlockDomain (domain) { dispatch(openModal({ modalType: 'CONFIRM', modalProps: { @@ -265,15 +264,15 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ })); }, - onUnblockDomain(domain) { + onUnblockDomain (domain) { dispatch(unblockDomain(domain)); }, - deployPictureInPicture(status, type, mediaProps) { + deployPictureInPicture (status, type, mediaProps) { dispatch(deployPictureInPicture(status.get('id'), status.getIn(['account', 'id']), type, mediaProps)); }, - onInteractionModal(type, status) { + onInteractionModal (type, status) { dispatch(openModal({ modalType: 'INTERACTION', modalProps: { diff --git a/app/javascript/mastodon/features/compose/components/language_dropdown.jsx b/app/javascript/mastodon/features/compose/components/language_dropdown.jsx index 672a5bc293e100..13d1c2e1a7cd97 100644 --- a/app/javascript/mastodon/features/compose/components/language_dropdown.jsx +++ b/app/javascript/mastodon/features/compose/components/language_dropdown.jsx @@ -48,7 +48,7 @@ class LanguageDropdownMenu extends PureComponent { } }; - componentDidMount() { + componentDidMount () { document.addEventListener('click', this.handleDocumentClick, { capture: true }); document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); @@ -62,7 +62,7 @@ class LanguageDropdownMenu extends PureComponent { }); } - componentWillUnmount() { + componentWillUnmount () { document.removeEventListener('click', this.handleDocumentClick, { capture: true }); document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); } @@ -79,7 +79,7 @@ class LanguageDropdownMenu extends PureComponent { this.setState({ searchValue: target.value }); }; - search() { + search () { const { languages, value, frequentlyUsedLanguages } = this.props; const { searchValue } = this.state; @@ -109,7 +109,7 @@ class LanguageDropdownMenu extends PureComponent { }).map(result => result.obj); } - frequentlyUsed() { + frequentlyUsed () { const { languages, value } = this.props; const current = languages.find(lang => lang[0] === value); const results = []; @@ -136,32 +136,32 @@ class LanguageDropdownMenu extends PureComponent { let element = null; - switch (e.key) { - case 'Escape': - onClose(); - break; - case 'Enter': - this.handleClick(e); - break; - case 'ArrowDown': - element = this.listNode.childNodes[index + 1] || this.listNode.firstChild; - break; - case 'ArrowUp': + switch(e.key) { + case 'Escape': + onClose(); + break; + case 'Enter': + this.handleClick(e); + break; + case 'ArrowDown': + element = this.listNode.childNodes[index + 1] || this.listNode.firstChild; + break; + case 'ArrowUp': + element = this.listNode.childNodes[index - 1] || this.listNode.lastChild; + break; + case 'Tab': + if (e.shiftKey) { element = this.listNode.childNodes[index - 1] || this.listNode.lastChild; - break; - case 'Tab': - if (e.shiftKey) { - element = this.listNode.childNodes[index - 1] || this.listNode.lastChild; - } else { - element = this.listNode.childNodes[index + 1] || this.listNode.firstChild; - } - break; - case 'Home': - element = this.listNode.firstChild; - break; - case 'End': - element = this.listNode.lastChild; - break; + } else { + element = this.listNode.childNodes[index + 1] || this.listNode.firstChild; + } + break; + case 'Home': + element = this.listNode.firstChild; + break; + case 'End': + element = this.listNode.lastChild; + break; } if (element) { @@ -177,33 +177,33 @@ class LanguageDropdownMenu extends PureComponent { let element = null; - switch (e.key) { - case 'Tab': - case 'ArrowDown': - element = this.listNode.firstChild; + switch(e.key) { + case 'Tab': + case 'ArrowDown': + element = this.listNode.firstChild; - if (element) { - element.focus(); - e.preventDefault(); - e.stopPropagation(); - } + if (element) { + element.focus(); + e.preventDefault(); + e.stopPropagation(); + } - break; - case 'Enter': - element = this.listNode.firstChild; + break; + case 'Enter': + element = this.listNode.firstChild; - if (element) { - onChange(element.getAttribute('data-index')); - onClose(); - } - break; - case 'Escape': - if (searchValue !== '') { - e.preventDefault(); - this.handleClear(); - } + if (element) { + onChange(element.getAttribute('data-index')); + onClose(); + } + break; + case 'Escape': + if (searchValue !== '') { + e.preventDefault(); + this.handleClear(); + } - break; + break; } }; @@ -221,7 +221,7 @@ class LanguageDropdownMenu extends PureComponent { ); }; - render() { + render () { const { intl } = this.props; const { searchValue } = this.state; const isSearching = searchValue !== ''; @@ -294,7 +294,7 @@ class LanguageDropdown extends PureComponent { this.setState({ placement: state.placement }); }; - render() { + render () { const { value, intl, frequentlyUsedLanguages } = this.props; const { open, placement } = this.state; diff --git a/app/javascript/mastodon/features/interaction_modal/index.jsx b/app/javascript/mastodon/features/interaction_modal/index.jsx index 6971eacaf7d7be..2a9fa0e33ef943 100644 --- a/app/javascript/mastodon/features/interaction_modal/index.jsx +++ b/app/javascript/mastodon/features/interaction_modal/index.jsx @@ -12,7 +12,7 @@ import { throttle, escapeRegExp } from 'lodash'; import { openModal, closeModal } from 'mastodon/actions/modal'; import api from 'mastodon/api'; import Button from 'mastodon/components/button'; -import { Icon } from 'mastodon/components/icon'; +import { Icon } from 'mastodon/components/icon'; import { registrationsOpen, sso_redirect } from 'mastodon/initial_state'; const messages = defineMessages({ @@ -21,15 +21,15 @@ const messages = defineMessages({ const mapStateToProps = (state, { accountId }) => ({ displayNameHtml: state.getIn(['accounts', accountId, 'display_name_html']), - signupUrl: state.getIn(['server', 'server', 'registrations', 'url'], null) || '/auth/auth/openid_connect', + signupUrl: state.getIn(['server', 'server', 'registrations', 'url'], null) || '/auth/sign_up', }); const mapDispatchToProps = (dispatch) => ({ onSignupClick() { dispatch(closeModal({ - modalType: undefined, - ignoreFocus: false, - })); + modalType: undefined, + ignoreFocus: false, + })); dispatch(openModal({ modalType: 'CLOSED_REGISTRATIONS' })); }, }); @@ -57,7 +57,7 @@ const valueToDomain = value => { } catch { return undefined; } - // If the user writes their full handle including username + // If the user writes their full handle including username } else if (value.includes('@')) { if (value.replace(/^@/, '').split('@').length > 2) { return undefined; @@ -127,7 +127,7 @@ class LoginForm extends React.PureComponent { try { new URL(url); return true; - } catch (_) { + } catch(_) { return false; } }; @@ -166,11 +166,11 @@ class LoginForm extends React.PureComponent { } }; - componentDidMount() { + componentDidMount () { window.addEventListener('message', this.handleMessage); } - componentWillUnmount() { + componentWillUnmount () { window.removeEventListener('message', this.handleMessage); } @@ -200,38 +200,38 @@ class LoginForm extends React.PureComponent { handleKeyDown = (e) => { const { options, selectedOption } = this.state; - switch (e.key) { - case 'ArrowDown': - e.preventDefault(); + switch(e.key) { + case 'ArrowDown': + e.preventDefault(); - if (options.length > 0) { - this.setState({ selectedOption: Math.min(selectedOption + 1, options.length - 1) }); - } + if (options.length > 0) { + this.setState({ selectedOption: Math.min(selectedOption + 1, options.length - 1) }); + } - break; - case 'ArrowUp': - e.preventDefault(); + break; + case 'ArrowUp': + e.preventDefault(); - if (options.length > 0) { - this.setState({ selectedOption: Math.max(selectedOption - 1, -1) }); - } + if (options.length > 0) { + this.setState({ selectedOption: Math.max(selectedOption - 1, -1) }); + } - break; - case 'Enter': - e.preventDefault(); + break; + case 'Enter': + e.preventDefault(); - if (selectedOption === -1) { - this.handleSubmit(); - } else if (options.length > 0) { - this.setState({ value: options[selectedOption], error: false }, () => this.handleSubmit()); - } + if (selectedOption === -1) { + this.handleSubmit(); + } else if (options.length > 0) { + this.setState({ value: options[selectedOption], error: false }, () => this.handleSubmit()); + } - break; + break; } }; handleOptionClick = e => { - const index = Number(e.currentTarget.getAttribute('data-index')); + const index = Number(e.currentTarget.getAttribute('data-index')); const option = this.state.options[index]; e.preventDefault(); @@ -264,7 +264,7 @@ class LoginForm extends React.PureComponent { }); }, 200, { leading: true, trailing: true }); - render() { + render () { const { intl } = this.props; const { value, expanded, options, selectedOption, error, isSubmitting } = this.state; const domain = (valueToDomain(value) || '').trim(); @@ -276,7 +276,7 @@ class LoginForm extends React.PureComponent {