diff --git a/app/soapbox/actions/auth.js b/app/soapbox/actions/auth.js
index dde684f77..65c1dc0f5 100644
--- a/app/soapbox/actions/auth.js
+++ b/app/soapbox/actions/auth.js
@@ -18,6 +18,7 @@ import KVStore from 'soapbox/storage/kv_store';
import { getLoggedInAccount, parseBaseURL } from 'soapbox/utils/auth';
import sourceCode from 'soapbox/utils/code';
import { getFeatures } from 'soapbox/utils/features';
+import { getQuirks } from 'soapbox/utils/quirks';
import { isStandalone } from 'soapbox/utils/state';
import api, { baseClient } from '../api';
@@ -62,6 +63,10 @@ function createAppAndToken() {
function createAuthApp() {
return (dispatch, getState) => {
+ // Mitra: skip creating the app
+ const quirks = getQuirks(getState().get('instance'));
+ if (quirks.skipsAppCreation) return dispatch(noOp());
+
const params = {
client_name: sourceCode.displayName,
redirect_uris: 'urn:ietf:wg:oauth:2.0:oob',
@@ -213,10 +218,13 @@ export function logIn(intl, username, password) {
};
}
-export function ethereumLogin() {
+export function ethereumLogin(instance, baseURL) {
return (dispatch, getState) => {
+ instance = (instance || getState().get('instance'));
+
const { ethereum } = window;
- const loginMessage = getState().getIn(['instance', 'login_message']);
+ const { scopes } = getFeatures(instance);
+ const loginMessage = instance.get('login_message');
return ethereum.request({ method: 'eth_requestAccounts' }).then(walletAddresses => {
const [walletAddress] = walletAddresses;
@@ -227,15 +235,14 @@ export function ethereumLogin() {
wallet_address: walletAddress.toLowerCase(),
password: signature,
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
- scope: getScopes(getState()),
+ scope: scopes,
};
// Note: skips app creation
// TODO: add to quirks.js for Mitra
- return dispatch(obtainOAuthToken(params)).then(token => {
- dispatch(authLoggedIn(token));
- return dispatch(verifyCredentials(token.access_token));
- });
+ return dispatch(obtainOAuthToken(params, baseURL))
+ .then(token => dispatch(authLoggedIn(token)))
+ .then(({ access_token }) => dispatch(verifyCredentials(access_token, baseURL)));
});
});
};
diff --git a/app/soapbox/actions/external_auth.js b/app/soapbox/actions/external_auth.js
index b3258ab70..35af6699e 100644
--- a/app/soapbox/actions/external_auth.js
+++ b/app/soapbox/actions/external_auth.js
@@ -9,11 +9,12 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { createApp } from 'soapbox/actions/apps';
-import { authLoggedIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth';
+import { authLoggedIn, verifyCredentials, switchAccount, ethereumLogin } from 'soapbox/actions/auth';
import { obtainOAuthToken } from 'soapbox/actions/oauth';
import { parseBaseURL } from 'soapbox/utils/auth';
import sourceCode from 'soapbox/utils/code';
import { getFeatures } from 'soapbox/utils/features';
+import { getQuirks } from 'soapbox/utils/quirks';
import { baseClient } from '../api';
@@ -32,36 +33,65 @@ const fetchExternalInstance = baseURL => {
});
};
-export function createAppAndRedirect(host) {
+function createExternalApp(instance, baseURL) {
+ return (dispatch, getState) => {
+ const { scopes } = getFeatures(instance);
+
+ const params = {
+ client_name: sourceCode.displayName,
+ redirect_uris: `${window.location.origin}/auth/external`,
+ website: sourceCode.homepage,
+ scopes,
+ };
+
+ return dispatch(createApp(params, baseURL));
+ };
+}
+
+function externalAuthorize(instance, baseURL) {
+ return (dispatch, getState) => {
+ const { scopes } = getFeatures(instance);
+
+ return dispatch(createExternalApp(instance, baseURL)).then(app => {
+ const { client_id, redirect_uri } = app;
+
+ const query = new URLSearchParams({
+ client_id,
+ redirect_uri,
+ response_type: 'code',
+ scope: scopes,
+ });
+
+ localStorage.setItem('soapbox:external:app', JSON.stringify(app));
+ localStorage.setItem('soapbox:external:baseurl', baseURL);
+ localStorage.setItem('soapbox:external:scopes', scopes);
+
+ window.location.href = `${baseURL}/oauth/authorize?${query.toString()}`;
+ });
+ };
+}
+
+function externalEthereumLogin(instance, baseURL) {
+ return (dispatch, getState) => {
+ return dispatch(ethereumLogin(instance, baseURL))
+ .then(account => dispatch(switchAccount(account.id)))
+ .then(() => window.location.href = '/');
+ };
+}
+
+export function externalLogin(host) {
return (dispatch, getState) => {
const baseURL = parseBaseURL(host) || parseBaseURL(`https://${host}`);
return fetchExternalInstance(baseURL).then(instance => {
- const { scopes } = getFeatures(instance);
+ const features = getFeatures(instance);
+ const quirks = getQuirks(instance);
- const params = {
- client_name: sourceCode.displayName,
- redirect_uris: `${window.location.origin}/auth/external`,
- website: sourceCode.homepage,
- scopes,
- };
-
- return dispatch(createApp(params, baseURL)).then(app => {
- const { client_id, redirect_uri } = app;
-
- const query = new URLSearchParams({
- client_id,
- redirect_uri,
- response_type: 'code',
- scope: scopes,
- });
-
- localStorage.setItem('soapbox:external:app', JSON.stringify(app));
- localStorage.setItem('soapbox:external:baseurl', baseURL);
- localStorage.setItem('soapbox:external:scopes', scopes);
-
- window.location.href = `${baseURL}/oauth/authorize?${query.toString()}`;
- });
+ if (features.ethereumLogin && quirks.ethereumLoginOnly) {
+ return dispatch(externalEthereumLogin(instance, baseURL));
+ } else {
+ return dispatch(externalAuthorize(instance, baseURL));
+ }
});
};
}
diff --git a/app/soapbox/features/auth_login/components/login_page.js b/app/soapbox/features/auth_login/components/login_page.js
index d6de2ca3d..ca16c2a81 100644
--- a/app/soapbox/features/auth_login/components/login_page.js
+++ b/app/soapbox/features/auth_login/components/login_page.js
@@ -4,25 +4,18 @@ import { injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom';
-import { ethereumLogin } from 'soapbox/actions/auth';
import { logIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth';
import { fetchInstance } from 'soapbox/actions/instance';
-import { getFeatures } from 'soapbox/utils/features';
import { isStandalone } from 'soapbox/utils/state';
import LoginForm from './login_form';
import OtpAuthForm from './otp_auth_form';
-const mapStateToProps = state => {
- const instance = state.get('instance');
-
- return {
- me: state.get('me'),
- isLoading: false,
- standalone: isStandalone(state),
- features: getFeatures(instance),
- };
-};
+const mapStateToProps = state => ({
+ me: state.get('me'),
+ isLoading: false,
+ standalone: isStandalone(state),
+});
export default @connect(mapStateToProps)
@injectIntl
@@ -69,18 +62,8 @@ class LoginPage extends ImmutablePureComponent {
event.preventDefault();
}
- handleEthereumLogin = e => {
- const { dispatch } = this.props;
-
- dispatch(ethereumLogin())
- .then(() => this.setState({ shouldRedirect: true }))
- .catch(console.error);
-
- e.preventDefault();
- };
-
render() {
- const { standalone, features } = this.props;
+ const { standalone } = this.props;
const { isLoading, mfa_auth_needed, mfa_token, shouldRedirect } = this.state;
if (standalone) return ;
@@ -89,11 +72,7 @@ class LoginPage extends ImmutablePureComponent {
if (mfa_auth_needed) return ;
- if (features.ethereumLogin) {
- return ;
- } else {
- return ;
- }
+ return ;
}
}
diff --git a/app/soapbox/features/external_login/components/external_login_form.js b/app/soapbox/features/external_login/components/external_login_form.js
index c5da61efb..83a9ccf87 100644
--- a/app/soapbox/features/external_login/components/external_login_form.js
+++ b/app/soapbox/features/external_login/components/external_login_form.js
@@ -3,7 +3,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { injectIntl, FormattedMessage, defineMessages } from 'react-intl';
import { connect } from 'react-redux';
-import { createAppAndRedirect, loginWithCode } from 'soapbox/actions/external_auth';
+import { externalLogin, loginWithCode } from 'soapbox/actions/external_auth';
import LoadingIndicator from 'soapbox/components/loading_indicator';
import { SimpleForm, FieldsGroup, TextInput } from 'soapbox/features/forms';
@@ -31,7 +31,7 @@ class ExternalLoginForm extends ImmutablePureComponent {
this.setState({ isLoading: true });
- dispatch(createAppAndRedirect(host))
+ dispatch(externalLogin(host))
.then(() => this.setState({ isLoading: false }))
.catch(() => this.setState({ isLoading: false }));
}
diff --git a/app/soapbox/utils/quirks.js b/app/soapbox/utils/quirks.js
index 764b10e26..e3ec5e651 100644
--- a/app/soapbox/utils/quirks.js
+++ b/app/soapbox/utils/quirks.js
@@ -1,12 +1,17 @@
-import { parseVersion } from './features';
+import { createSelector } from 'reselect';
+
+import { parseVersion, PLEROMA, MITRA } from './features';
// For solving bugs between API implementations
-export const getQuirks = instance => {
- const v = parseVersion(instance.get('version'));
+export const getQuirks = createSelector([
+ instance => parseVersion(instance.get('version')),
+], (v) => {
return {
- invertedPagination: v.software === 'Pleroma',
+ invertedPagination: v.software === PLEROMA,
+ skipsAppCreation: v.software === MITRA,
+ ethereumLoginOnly: v.software === MITRA,
};
-};
+});
export const getNextLinkName = getState =>
getQuirks(getState().get('instance')).invertedPagination ? 'prev' : 'next';