diff --git a/app/soapbox/actions/auth.js b/app/soapbox/actions/auth.js index 9549abead..ee496450b 100644 --- a/app/soapbox/actions/auth.js +++ b/app/soapbox/actions/auth.js @@ -18,6 +18,7 @@ import { createApp } from 'soapbox/actions/apps'; import { obtainOAuthToken, revokeOAuthToken } from 'soapbox/actions/oauth'; import sourceCode from 'soapbox/utils/code'; import { getFeatures } from 'soapbox/utils/features'; +import { isStandalone } from 'soapbox/utils/state'; export const SWITCH_ACCOUNT = 'SWITCH_ACCOUNT'; @@ -177,6 +178,7 @@ export function logOut(intl) { return (dispatch, getState) => { const state = getState(); const account = getLoggedInAccount(state); + const standalone = isStandalone(state); const params = { client_id: state.getIn(['auth', 'app', 'client_id']), @@ -185,7 +187,7 @@ export function logOut(intl) { }; return dispatch(revokeOAuthToken(params)).finally(() => { - dispatch({ type: AUTH_LOGGED_OUT, account }); + dispatch({ type: AUTH_LOGGED_OUT, account, standalone }); dispatch(snackbar.success(intl.formatMessage(messages.loggedOut))); }); }; diff --git a/app/soapbox/actions/external_auth.js b/app/soapbox/actions/external_auth.js index f3b52650a..da680c488 100644 --- a/app/soapbox/actions/external_auth.js +++ b/app/soapbox/actions/external_auth.js @@ -9,7 +9,7 @@ import { baseClient } from '../api'; import { createApp } from 'soapbox/actions/apps'; import { obtainOAuthToken } from 'soapbox/actions/oauth'; -import { authLoggedIn, verifyCredentials } from 'soapbox/actions/auth'; +import { authLoggedIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; import { parseBaseURL } from 'soapbox/utils/auth'; import { getFeatures } from 'soapbox/utils/features'; import sourceCode from 'soapbox/utils/code'; @@ -73,6 +73,7 @@ export function loginWithCode(code) { return dispatch(obtainOAuthToken(params, baseURL)) .then(token => dispatch(authLoggedIn(token))) .then(({ access_token }) => dispatch(verifyCredentials(access_token, baseURL))) + .then(account => dispatch(switchAccount(account.id))) .then(() => window.location.href = '/'); }; } diff --git a/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_page-test.js.snap b/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_page-test.js.snap index 82586223c..041b1741d 100644 --- a/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_page-test.js.snap +++ b/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_page-test.js.snap @@ -1,129 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` renders correctly on load 1`] = ` -
-
-
-
- -
-
- -
-

- - Trouble logging in? - -

-
-
-
- -
-
-`; +exports[` renders correctly on load 1`] = `null`; -exports[` renders correctly on load 2`] = ` -
-
-
-
- -
-
- -
-

- - Trouble logging in? - -

-
-
-
- -
-
-`; +exports[` renders correctly on load 2`] = `null`; diff --git a/app/soapbox/features/auth_login/components/login_page.js b/app/soapbox/features/auth_login/components/login_page.js index 8bd797c52..8cdb07ee0 100644 --- a/app/soapbox/features/auth_login/components/login_page.js +++ b/app/soapbox/features/auth_login/components/login_page.js @@ -6,10 +6,12 @@ import { injectIntl } from 'react-intl'; import LoginForm from './login_form'; import OtpAuthForm from './otp_auth_form'; import { logIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; +import { isStandalone } from 'soapbox/utils/state'; const mapStateToProps = state => ({ me: state.get('me'), isLoading: false, + standalone: isStandalone(state), }); export default @connect(mapStateToProps) @@ -55,8 +57,11 @@ class LoginPage extends ImmutablePureComponent { } render() { + const { standalone } = this.props; const { isLoading, mfa_auth_needed, mfa_token, shouldRedirect } = this.state; + if (standalone) return ; + if (shouldRedirect) return ; if (mfa_auth_needed) return ; diff --git a/app/soapbox/features/public_layout/index.js b/app/soapbox/features/public_layout/index.js index 621e9c25b..09dc1f263 100644 --- a/app/soapbox/features/public_layout/index.js +++ b/app/soapbox/features/public_layout/index.js @@ -9,19 +9,7 @@ import Footer from './components/footer'; import LandingPage from '../landing_page'; import AboutPage from '../about'; import { getSoapboxConfig } from 'soapbox/actions/soapbox'; -import { isPrerendered } from 'soapbox/precheck'; - -const validInstance = state => { - const v = state.getIn(['instance', 'version']); - return v && typeof v === 'string' && v !== '0.0.0'; -}; - -const isStandalone = state => { - const hasInstance = validInstance(state); - const instanceFetchFailed = state.getIn(['meta', 'instance_fetch_failed']); - - return !isPrerendered && !hasInstance && instanceFetchFailed; -}; +import { isStandalone } from 'soapbox/utils/state'; const mapStateToProps = (state, props) => ({ soapbox: getSoapboxConfig(state), diff --git a/app/soapbox/reducers/auth.js b/app/soapbox/reducers/auth.js index 42aaa586f..a3b669dd0 100644 --- a/app/soapbox/reducers/auth.js +++ b/app/soapbox/reducers/auth.js @@ -261,7 +261,10 @@ const userSwitched = (oldState, state) => { }; const maybeReload = (oldState, state, action) => { - if (userSwitched(oldState, state)) { + const loggedOutStandalone = action.type === AUTH_LOGGED_OUT && action.standalone; + const switched = userSwitched(oldState, state); + + if (switched || loggedOutStandalone) { reload(state); } }; diff --git a/app/soapbox/utils/state.js b/app/soapbox/utils/state.js index 9809c25fa..9c69e9043 100644 --- a/app/soapbox/utils/state.js +++ b/app/soapbox/utils/state.js @@ -1,4 +1,13 @@ +/** + * State: general Redux state utility functions. + * @module soapbox/utils/state + */ + import { getSoapboxConfig } from'soapbox/actions/soapbox'; +import { createSelector } from 'reselect'; +import { isPrerendered } from 'soapbox/precheck'; +import { isURL } from 'soapbox/utils/auth'; +import { BACKEND_URL } from 'soapbox/build_config'; export const displayFqn = state => { const soapbox = getSoapboxConfig(state); @@ -8,3 +17,15 @@ export const displayFqn = state => { export const federationRestrictionsDisclosed = state => { return state.hasIn(['instance', 'pleroma', 'metadata', 'federation', 'mrf_policies']); }; + +/** + * Determine whether Soapbox FE is running in standalone mode. + * Standalone mode runs separately from any backend and can login anywhere. + * @param {object} state + * @returns {boolean} + */ +export const isStandalone = state => createSelector([ + state => state.getIn(['meta', 'instance_fetch_failed'], false), +], instanceFetchFailed => { + return isURL(BACKEND_URL) ? false : (!isPrerendered && instanceFetchFailed); +});