Auth: rudimentary API baseURL support

This commit is contained in:
Alex Gleason 2021-08-21 20:41:29 -05:00
parent d236b61c96
commit fcaf19df76
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
4 changed files with 37 additions and 12 deletions

View file

@ -4,7 +4,7 @@ import { importFetchedAccount } from './importer';
import snackbar from 'soapbox/actions/snackbar'; import snackbar from 'soapbox/actions/snackbar';
import { createAccount } from 'soapbox/actions/accounts'; import { createAccount } from 'soapbox/actions/accounts';
import { fetchMeSuccess, fetchMeFail } from 'soapbox/actions/me'; import { fetchMeSuccess, fetchMeFail } from 'soapbox/actions/me';
import { getLoggedInAccount } from 'soapbox/utils/auth'; import { getLoggedInAccount, parseBaseURL } from 'soapbox/utils/auth';
import { createApp } from 'soapbox/actions/apps'; import { createApp } from 'soapbox/actions/apps';
import { obtainOAuthToken, revokeOAuthToken } from 'soapbox/actions/oauth'; import { obtainOAuthToken, revokeOAuthToken } from 'soapbox/actions/oauth';
@ -144,11 +144,13 @@ export function otpVerify(code, mfa_token) {
}; };
} }
export function verifyCredentials(token) { export function verifyCredentials(token, accountUrl) {
const baseURL = parseBaseURL(accountUrl);
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch({ type: VERIFY_CREDENTIALS_REQUEST }); dispatch({ type: VERIFY_CREDENTIALS_REQUEST });
return baseClient(token).get('/api/v1/accounts/verify_credentials').then(({ data: account }) => { return baseClient(token, baseURL).get('/api/v1/accounts/verify_credentials').then(({ data: account }) => {
dispatch(importFetchedAccount(account)); dispatch(importFetchedAccount(account));
dispatch({ type: VERIFY_CREDENTIALS_SUCCESS, token, account }); dispatch({ type: VERIFY_CREDENTIALS_SUCCESS, token, account });
if (account.id === getState().get('me')) dispatch(fetchMeSuccess(account)); if (account.id === getState().get('me')) dispatch(fetchMeSuccess(account));
@ -208,7 +210,7 @@ export function fetchOwnAccounts() {
state.getIn(['auth', 'users']).forEach(user => { state.getIn(['auth', 'users']).forEach(user => {
const account = state.getIn(['accounts', user.get('id')]); const account = state.getIn(['accounts', user.get('id')]);
if (!account) { if (!account) {
dispatch(verifyCredentials(user.get('access_token'))); dispatch(verifyCredentials(user.get('access_token'), user.get('url')));
} }
}); });
}; };

View file

@ -29,14 +29,16 @@ const getMeToken = state => {
export function fetchMe() { export function fetchMe() {
return (dispatch, getState) => { return (dispatch, getState) => {
const token = getMeToken(getState()); const state = getState();
const token = getMeToken(state);
const accountUrl = getMeUrl(state);
if (!token) { if (!token) {
dispatch({ type: ME_FETCH_SKIP }); return noOp(); dispatch({ type: ME_FETCH_SKIP }); return noOp();
} }
dispatch(fetchMeRequest()); dispatch(fetchMeRequest());
return dispatch(verifyCredentials(token)).catch(error => { return dispatch(verifyCredentials(token, accountUrl)).catch(error => {
dispatch(fetchMeFail(error)); dispatch(fetchMeFail(error));
}); });
}; };

View file

@ -2,7 +2,8 @@
import axios from 'axios'; import axios from 'axios';
import LinkHeader from 'http-link-header'; import LinkHeader from 'http-link-header';
import { getAccessToken, getAppToken } from 'soapbox/utils/auth'; import { getAccessToken, getAppToken, parseBaseURL } from 'soapbox/utils/auth';
import { createSelector } from 'reselect';
export const getLinks = response => { export const getLinks = response => {
const value = response.headers.link; const value = response.headers.link;
@ -10,8 +11,7 @@ export const getLinks = response => {
return LinkHeader.parse(value); return LinkHeader.parse(value);
}; };
const getToken = (getState, authType) => { const getToken = (state, authType) => {
const state = getState();
return authType === 'app' ? getAppToken(state) : getAccessToken(state); return authType === 'app' ? getAppToken(state) : getAccessToken(state);
}; };
@ -23,8 +23,17 @@ const maybeParseJSON = data => {
} }
}; };
export const baseClient = accessToken => { const getAuthBaseURL = createSelector([
(state, me) => state.getIn(['accounts', me, 'url']),
(state, me) => state.getIn(['auth', 'me']),
], (accountUrl, authUserUrl) => {
const baseURL = parseBaseURL(accountUrl) || parseBaseURL(authUserUrl);
return baseURL !== window.location.origin ? baseURL : '';
});
export const baseClient = (accessToken, baseURL = '') => {
return axios.create({ return axios.create({
baseURL,
headers: Object.assign(accessToken ? { headers: Object.assign(accessToken ? {
'Authorization': `Bearer ${accessToken}`, 'Authorization': `Bearer ${accessToken}`,
} : {}), } : {}),
@ -34,6 +43,10 @@ export const baseClient = accessToken => {
}; };
export default (getState, authType = 'user') => { export default (getState, authType = 'user') => {
const accessToken = getToken(getState, authType); const state = getState();
return baseClient(accessToken); const accessToken = getToken(state, authType);
const me = state.get('me');
const baseURL = getAuthBaseURL(state, me);
return baseClient(accessToken, baseURL);
}; };

View file

@ -11,6 +11,14 @@ export const isURL = url => {
} }
}; };
export const parseBaseURL = url => {
try {
return new URL(url).origin;
} catch {
return '';
}
};
export const getLoggedInAccount = state => { export const getLoggedInAccount = state => {
const me = state.get('me'); const me = state.get('me');
return state.getIn(['accounts', me]); return state.getIn(['accounts', me]);