kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Merge branch 'app-actions-refactor' into 'develop'
Auth: refactor actions: apps, security, oauth See merge request soapbox-pub/soapbox-fe!680groups^2
commit
d236b61c96
|
@ -0,0 +1,35 @@
|
||||||
|
import { baseClient } from '../api';
|
||||||
|
|
||||||
|
export const APP_CREATE_REQUEST = 'APP_CREATE_REQUEST';
|
||||||
|
export const APP_CREATE_SUCCESS = 'APP_CREATE_SUCCESS';
|
||||||
|
export const APP_CREATE_FAIL = 'APP_CREATE_FAIL';
|
||||||
|
|
||||||
|
export const APP_VERIFY_CREDENTIALS_REQUEST = 'APP_VERIFY_CREDENTIALS_REQUEST';
|
||||||
|
export const APP_VERIFY_CREDENTIALS_SUCCESS = 'APP_VERIFY_CREDENTIALS_SUCCESS';
|
||||||
|
export const APP_VERIFY_CREDENTIALS_FAIL = 'APP_VERIFY_CREDENTIALS_FAIL';
|
||||||
|
|
||||||
|
export function createApp(params) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: APP_CREATE_REQUEST, params });
|
||||||
|
return baseClient().post('/api/v1/apps', params).then(({ data: app }) => {
|
||||||
|
dispatch({ type: APP_CREATE_SUCCESS, params, app });
|
||||||
|
return app;
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch({ type: APP_CREATE_FAIL, params, error });
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function verifyAppCredentials(token) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: APP_VERIFY_CREDENTIALS_REQUEST, token });
|
||||||
|
return baseClient(token).get('/api/v1/apps/verify_credentials').then(({ data: app }) => {
|
||||||
|
dispatch({ type: APP_VERIFY_CREDENTIALS_SUCCESS, token, app });
|
||||||
|
return app;
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch({ type: APP_VERIFY_CREDENTIALS_FAIL, token, error });
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ 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 } from 'soapbox/utils/auth';
|
||||||
|
import { createApp } from 'soapbox/actions/apps';
|
||||||
|
import { obtainOAuthToken, revokeOAuthToken } from 'soapbox/actions/oauth';
|
||||||
|
|
||||||
export const SWITCH_ACCOUNT = 'SWITCH_ACCOUNT';
|
export const SWITCH_ACCOUNT = 'SWITCH_ACCOUNT';
|
||||||
|
|
||||||
|
@ -33,14 +35,6 @@ export const CHANGE_PASSWORD_REQUEST = 'CHANGE_PASSWORD_REQUEST';
|
||||||
export const CHANGE_PASSWORD_SUCCESS = 'CHANGE_PASSWORD_SUCCESS';
|
export const CHANGE_PASSWORD_SUCCESS = 'CHANGE_PASSWORD_SUCCESS';
|
||||||
export const CHANGE_PASSWORD_FAIL = 'CHANGE_PASSWORD_FAIL';
|
export const CHANGE_PASSWORD_FAIL = 'CHANGE_PASSWORD_FAIL';
|
||||||
|
|
||||||
export const FETCH_TOKENS_REQUEST = 'FETCH_TOKENS_REQUEST';
|
|
||||||
export const FETCH_TOKENS_SUCCESS = 'FETCH_TOKENS_SUCCESS';
|
|
||||||
export const FETCH_TOKENS_FAIL = 'FETCH_TOKENS_FAIL';
|
|
||||||
|
|
||||||
export const REVOKE_TOKEN_REQUEST = 'REVOKE_TOKEN_REQUEST';
|
|
||||||
export const REVOKE_TOKEN_SUCCESS = 'REVOKE_TOKEN_SUCCESS';
|
|
||||||
export const REVOKE_TOKEN_FAIL = 'REVOKE_TOKEN_FAIL';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
loggedOut: { id: 'auth.logged_out', defaultMessage: 'Logged out.' },
|
loggedOut: { id: 'auth.logged_out', defaultMessage: 'Logged out.' },
|
||||||
invalidCredentials: { id: 'auth.invalid_credentials', defaultMessage: 'Wrong username or password' },
|
invalidCredentials: { id: 'auth.invalid_credentials', defaultMessage: 'Wrong username or password' },
|
||||||
|
@ -50,7 +44,7 @@ const noOp = () => () => new Promise(f => f());
|
||||||
|
|
||||||
function createAppAndToken() {
|
function createAppAndToken() {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
return dispatch(createApp()).then(() => {
|
return dispatch(createAuthApp()).then(() => {
|
||||||
return dispatch(createAppToken());
|
return dispatch(createAppToken());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -61,14 +55,16 @@ const appName = () => {
|
||||||
return `SoapboxFE_${timestamp}`; // TODO: Add commit hash
|
return `SoapboxFE_${timestamp}`; // TODO: Add commit hash
|
||||||
};
|
};
|
||||||
|
|
||||||
function createApp() {
|
function createAuthApp() {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
return api(getState, 'app').post('/api/v1/apps', {
|
const params = {
|
||||||
client_name: appName(),
|
client_name: appName(),
|
||||||
redirect_uris: 'urn:ietf:wg:oauth:2.0:oob',
|
redirect_uris: 'urn:ietf:wg:oauth:2.0:oob',
|
||||||
scopes: 'read write follow push admin',
|
scopes: 'read write follow push admin',
|
||||||
}).then(response => {
|
};
|
||||||
return dispatch(authAppCreated(response.data));
|
|
||||||
|
return dispatch(createApp(params)).then(app => {
|
||||||
|
return dispatch({ type: AUTH_APP_CREATED, app });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -77,13 +73,15 @@ function createAppToken() {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const app = getState().getIn(['auth', 'app']);
|
const app = getState().getIn(['auth', 'app']);
|
||||||
|
|
||||||
return api(getState, 'app').post('/oauth/token', {
|
const params = {
|
||||||
client_id: app.get('client_id'),
|
client_id: app.get('client_id'),
|
||||||
client_secret: app.get('client_secret'),
|
client_secret: app.get('client_secret'),
|
||||||
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
|
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
|
||||||
grant_type: 'client_credentials',
|
grant_type: 'client_credentials',
|
||||||
}).then(response => {
|
};
|
||||||
return dispatch(authAppAuthorized(response.data));
|
|
||||||
|
return dispatch(obtainOAuthToken(params)).then(token => {
|
||||||
|
return dispatch({ type: AUTH_APP_AUTHORIZED, app, token });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -91,14 +89,17 @@ function createAppToken() {
|
||||||
function createUserToken(username, password) {
|
function createUserToken(username, password) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const app = getState().getIn(['auth', 'app']);
|
const app = getState().getIn(['auth', 'app']);
|
||||||
return api(getState, 'app').post('/oauth/token', {
|
|
||||||
|
const params = {
|
||||||
client_id: app.get('client_id'),
|
client_id: app.get('client_id'),
|
||||||
client_secret: app.get('client_secret'),
|
client_secret: app.get('client_secret'),
|
||||||
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
|
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
|
||||||
grant_type: 'password',
|
grant_type: 'password',
|
||||||
username: username,
|
username: username,
|
||||||
password: password,
|
password: password,
|
||||||
}).then(({ data: token }) => {
|
};
|
||||||
|
|
||||||
|
return dispatch(obtainOAuthToken(params)).then(token => {
|
||||||
dispatch(authLoggedIn(token));
|
dispatch(authLoggedIn(token));
|
||||||
return token;
|
return token;
|
||||||
});
|
});
|
||||||
|
@ -112,14 +113,16 @@ export function refreshUserToken() {
|
||||||
|
|
||||||
if (!refreshToken) return dispatch(noOp());
|
if (!refreshToken) return dispatch(noOp());
|
||||||
|
|
||||||
return api(getState, 'app').post('/oauth/token', {
|
const params = {
|
||||||
client_id: app.get('client_id'),
|
client_id: app.get('client_id'),
|
||||||
client_secret: app.get('client_secret'),
|
client_secret: app.get('client_secret'),
|
||||||
refresh_token: refreshToken,
|
refresh_token: refreshToken,
|
||||||
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
|
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
|
||||||
grant_type: 'refresh_token',
|
grant_type: 'refresh_token',
|
||||||
}).then(response => {
|
};
|
||||||
dispatch(authLoggedIn(response.data));
|
|
||||||
|
return dispatch(obtainOAuthToken(params)).then(token => {
|
||||||
|
dispatch(authLoggedIn(token));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -179,11 +182,13 @@ export function logOut(intl) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const account = getLoggedInAccount(state);
|
const account = getLoggedInAccount(state);
|
||||||
|
|
||||||
return api(getState).post('/oauth/revoke', {
|
const params = {
|
||||||
client_id: state.getIn(['auth', 'app', 'client_id']),
|
client_id: state.getIn(['auth', 'app', 'client_id']),
|
||||||
client_secret: state.getIn(['auth', 'app', 'client_secret']),
|
client_secret: state.getIn(['auth', 'app', 'client_secret']),
|
||||||
token: state.getIn(['auth', 'users', account.get('url'), 'access_token']),
|
token: state.getIn(['auth', 'users', account.get('url'), 'access_token']),
|
||||||
}).finally(() => {
|
};
|
||||||
|
|
||||||
|
return dispatch(revokeOAuthToken(params)).finally(() => {
|
||||||
dispatch({ type: AUTH_LOGGED_OUT, account });
|
dispatch({ type: AUTH_LOGGED_OUT, account });
|
||||||
dispatch(snackbar.success(intl.formatMessage(messages.loggedOut)));
|
dispatch(snackbar.success(intl.formatMessage(messages.loggedOut)));
|
||||||
});
|
});
|
||||||
|
@ -296,42 +301,6 @@ export function changePassword(oldPassword, newPassword, confirmation) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchOAuthTokens() {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
dispatch({ type: FETCH_TOKENS_REQUEST });
|
|
||||||
return api(getState).get('/api/oauth_tokens.json').then(response => {
|
|
||||||
dispatch({ type: FETCH_TOKENS_SUCCESS, tokens: response.data });
|
|
||||||
}).catch(error => {
|
|
||||||
dispatch({ type: FETCH_TOKENS_FAIL });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function revokeOAuthToken(id) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
dispatch({ type: REVOKE_TOKEN_REQUEST, id });
|
|
||||||
return api(getState).delete(`/api/oauth_tokens/${id}`).then(response => {
|
|
||||||
dispatch({ type: REVOKE_TOKEN_SUCCESS, id });
|
|
||||||
}).catch(error => {
|
|
||||||
dispatch({ type: REVOKE_TOKEN_FAIL, id });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function authAppCreated(app) {
|
|
||||||
return {
|
|
||||||
type: AUTH_APP_CREATED,
|
|
||||||
app,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function authAppAuthorized(app) {
|
|
||||||
return {
|
|
||||||
type: AUTH_APP_AUTHORIZED,
|
|
||||||
app,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function authLoggedIn(token) {
|
export function authLoggedIn(token) {
|
||||||
return {
|
return {
|
||||||
type: AUTH_LOGGED_IN,
|
type: AUTH_LOGGED_IN,
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { baseClient } from '../api';
|
||||||
|
|
||||||
|
export const OAUTH_TOKEN_CREATE_REQUEST = 'OAUTH_TOKEN_CREATE_REQUEST';
|
||||||
|
export const OAUTH_TOKEN_CREATE_SUCCESS = 'OAUTH_TOKEN_CREATE_SUCCESS';
|
||||||
|
export const OAUTH_TOKEN_CREATE_FAIL = 'OAUTH_TOKEN_CREATE_FAIL';
|
||||||
|
|
||||||
|
export const OAUTH_TOKEN_REVOKE_REQUEST = 'OAUTH_TOKEN_REVOKE_REQUEST';
|
||||||
|
export const OAUTH_TOKEN_REVOKE_SUCCESS = 'OAUTH_TOKEN_REVOKE_SUCCESS';
|
||||||
|
export const OAUTH_TOKEN_REVOKE_FAIL = 'OAUTH_TOKEN_REVOKE_FAIL';
|
||||||
|
|
||||||
|
export function obtainOAuthToken(params) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: OAUTH_TOKEN_CREATE_REQUEST, params });
|
||||||
|
return baseClient().post('/oauth/token', params).then(({ data: token }) => {
|
||||||
|
dispatch({ type: OAUTH_TOKEN_CREATE_SUCCESS, params, token });
|
||||||
|
return token;
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch({ type: OAUTH_TOKEN_CREATE_FAIL, params, error });
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function revokeOAuthToken(params) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: OAUTH_TOKEN_REVOKE_REQUEST, params });
|
||||||
|
return baseClient().post('/oauth/revoke', params).then(({ data }) => {
|
||||||
|
dispatch({ type: OAUTH_TOKEN_REVOKE_SUCCESS, params, data });
|
||||||
|
return data;
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch({ type: OAUTH_TOKEN_REVOKE_FAIL, params, error });
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
import api from '../api';
|
||||||
|
|
||||||
|
export const FETCH_TOKENS_REQUEST = 'FETCH_TOKENS_REQUEST';
|
||||||
|
export const FETCH_TOKENS_SUCCESS = 'FETCH_TOKENS_SUCCESS';
|
||||||
|
export const FETCH_TOKENS_FAIL = 'FETCH_TOKENS_FAIL';
|
||||||
|
|
||||||
|
export const REVOKE_TOKEN_REQUEST = 'REVOKE_TOKEN_REQUEST';
|
||||||
|
export const REVOKE_TOKEN_SUCCESS = 'REVOKE_TOKEN_SUCCESS';
|
||||||
|
export const REVOKE_TOKEN_FAIL = 'REVOKE_TOKEN_FAIL';
|
||||||
|
|
||||||
|
export function fetchOAuthTokens() {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: FETCH_TOKENS_REQUEST });
|
||||||
|
return api(getState).get('/api/oauth_tokens.json').then(({ data: tokens }) => {
|
||||||
|
dispatch({ type: FETCH_TOKENS_SUCCESS, tokens });
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch({ type: FETCH_TOKENS_FAIL });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function revokeOAuthTokenById(id) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: REVOKE_TOKEN_REQUEST, id });
|
||||||
|
return api(getState).delete(`/api/oauth_tokens/${id}`).then(() => {
|
||||||
|
dispatch({ type: REVOKE_TOKEN_SUCCESS, id });
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch({ type: REVOKE_TOKEN_FAIL, id });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
|
@ -15,10 +15,9 @@ import {
|
||||||
import {
|
import {
|
||||||
changeEmail,
|
changeEmail,
|
||||||
changePassword,
|
changePassword,
|
||||||
fetchOAuthTokens,
|
|
||||||
revokeOAuthToken,
|
|
||||||
deleteAccount,
|
deleteAccount,
|
||||||
} from 'soapbox/actions/auth';
|
} from 'soapbox/actions/auth';
|
||||||
|
import { fetchOAuthTokens, revokeOAuthTokenById } from 'soapbox/actions/security';
|
||||||
import { fetchUserMfaSettings } from '../../actions/mfa';
|
import { fetchUserMfaSettings } from '../../actions/mfa';
|
||||||
import snackbar from 'soapbox/actions/snackbar';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import { changeSetting, getSettings } from 'soapbox/actions/settings';
|
import { changeSetting, getSettings } from 'soapbox/actions/settings';
|
||||||
|
@ -306,7 +305,7 @@ class AuthTokenList extends ImmutablePureComponent {
|
||||||
|
|
||||||
handleRevoke = id => {
|
handleRevoke = id => {
|
||||||
return e => {
|
return e => {
|
||||||
this.props.dispatch(revokeOAuthToken(id));
|
this.props.dispatch(revokeOAuthTokenById(id));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -222,7 +222,7 @@ const reducer = (state, action) => {
|
||||||
case AUTH_APP_CREATED:
|
case AUTH_APP_CREATED:
|
||||||
return state.set('app', fromJS(action.app));
|
return state.set('app', fromJS(action.app));
|
||||||
case AUTH_APP_AUTHORIZED:
|
case AUTH_APP_AUTHORIZED:
|
||||||
return state.update('app', ImmutableMap(), app => app.merge(fromJS(action.app)));
|
return state.update('app', ImmutableMap(), app => app.merge(fromJS(action.token)));
|
||||||
case AUTH_LOGGED_IN:
|
case AUTH_LOGGED_IN:
|
||||||
return importToken(state, action.token);
|
return importToken(state, action.token);
|
||||||
case AUTH_LOGGED_OUT:
|
case AUTH_LOGGED_OUT:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {
|
import {
|
||||||
FETCH_TOKENS_SUCCESS,
|
FETCH_TOKENS_SUCCESS,
|
||||||
REVOKE_TOKEN_SUCCESS,
|
REVOKE_TOKEN_SUCCESS,
|
||||||
} from '../actions/auth';
|
} from '../actions/security';
|
||||||
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
|
||||||
|
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
|
|
Ładowanie…
Reference in New Issue