mirror of
https://github.com/elyby/accounts-frontend.git
synced 2025-05-31 14:11:58 +05:30
Интеграция appInfo с API
This commit is contained in:
42
src/components/auth/OAuthInit.jsx
Normal file
42
src/components/auth/OAuthInit.jsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { oAuthValidate } from 'components/auth/actions';
|
||||||
|
|
||||||
|
class OAuthInit extends Component {
|
||||||
|
static displayName = 'OAuthInit';
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
query: PropTypes.shape({
|
||||||
|
client_id: PropTypes.string.isRequired,
|
||||||
|
redirect_uri: PropTypes.string.isRequired,
|
||||||
|
response_type: PropTypes.string.isRequired,
|
||||||
|
scope: PropTypes.string.isRequired,
|
||||||
|
state: PropTypes.string
|
||||||
|
}),
|
||||||
|
validate: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
const {query} = this.props;
|
||||||
|
|
||||||
|
this.props.validate({
|
||||||
|
clientId: query.client_id,
|
||||||
|
redirectUrl: query.redirect_uri,
|
||||||
|
responseType: query.response_type,
|
||||||
|
scope: query.scope,
|
||||||
|
state: query.state
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <span />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect((state) => ({
|
||||||
|
query: state.routing.location.query
|
||||||
|
}), {
|
||||||
|
validate: oAuthValidate
|
||||||
|
})(OAuthInit);
|
@@ -107,3 +107,45 @@ export function logout() {
|
|||||||
dispatch(routeActions.push('/login'));
|
dispatch(routeActions.push('/login'));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: move to oAuth actions?
|
||||||
|
// test request: /oauth?client_id=ely&redirect_uri=http%3A%2F%2Fely.by&response_type=code&scope=minecraft_server_session
|
||||||
|
export function oAuthValidate({clientId, redirectUrl, responseType, scope, state}) {
|
||||||
|
return (dispatch) =>
|
||||||
|
request.get(
|
||||||
|
'/api/oauth/validate',
|
||||||
|
{
|
||||||
|
client_id: clientId,
|
||||||
|
redirect_uri: redirectUrl,
|
||||||
|
response_type: responseType,
|
||||||
|
scope,
|
||||||
|
state
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((resp) => {
|
||||||
|
dispatch(setClient(resp.client));
|
||||||
|
dispatch(routeActions.push('/oauth/permissions'));
|
||||||
|
})
|
||||||
|
.catch((resp = {}) => { // TODO
|
||||||
|
if (resp.statusCode === 400 && resp.error === 'invalid_request') {
|
||||||
|
alert(`Invalid request (${resp.parameter} required).`);
|
||||||
|
}
|
||||||
|
if (resp.statusCode === 401 && resp.error === 'invalid_client') {
|
||||||
|
alert('Can not find application you are trying to authorize.');
|
||||||
|
}
|
||||||
|
if (resp.statusCode === 400 && resp.error === 'unsupported_response_type') {
|
||||||
|
alert(`Invalid response type '${resp.parameter}'.`);
|
||||||
|
}
|
||||||
|
if (resp.statusCode === 400 && resp.error === 'invalid_scope') {
|
||||||
|
alert(`Invalid scope '${resp.parameter}'.`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SET_CLIENT = 'set_client';
|
||||||
|
export function setClient({id, name, description}) {
|
||||||
|
return {
|
||||||
|
type: SET_CLIENT,
|
||||||
|
payload: {id, name, description}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
|
|
||||||
import { ERROR } from './actions';
|
import { ERROR, SET_CLIENT } from './actions';
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
error
|
error,
|
||||||
|
client
|
||||||
});
|
});
|
||||||
|
|
||||||
function error(
|
function error(
|
||||||
@@ -21,3 +22,20 @@ function error(
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function client(
|
||||||
|
state = null,
|
||||||
|
{type, payload = {}}
|
||||||
|
) {
|
||||||
|
switch (type) {
|
||||||
|
case SET_CLIENT:
|
||||||
|
return {
|
||||||
|
id: payload.id,
|
||||||
|
name: payload.name,
|
||||||
|
description: payload.description
|
||||||
|
};
|
||||||
|
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1,29 +1,34 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import AppInfo from 'components/auth/AppInfo';
|
import AppInfo from 'components/auth/AppInfo';
|
||||||
import PanelTransition from 'components/auth/PanelTransition';
|
import PanelTransition from 'components/auth/PanelTransition';
|
||||||
|
|
||||||
import styles from './auth.scss';
|
import styles from './auth.scss';
|
||||||
|
|
||||||
export default class AuthPage extends Component {
|
class AuthPage extends Component {
|
||||||
static displayName = 'AuthPage';
|
static displayName = 'AuthPage';
|
||||||
|
static propTypes = {
|
||||||
|
client: PropTypes.shape({
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
|
description: PropTypes.string.isRequired
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
isSidebarHidden: false
|
isSidebarHidden: false
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var {isSidebarHidden} = this.state;
|
const {isSidebarHidden} = this.state;
|
||||||
|
const {client} = this.props;
|
||||||
var appInfo = {
|
|
||||||
name: 'TLauncher',
|
|
||||||
description: `Лучший альтернативный лаунчер для Minecraft с большим количеством версий и их модификаций, а также возмоностью входа как с лицензионным аккаунтом, так и без него.`
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={isSidebarHidden ? styles.hiddenSidebar : styles.sidebar}>
|
<div className={isSidebarHidden ? styles.hiddenSidebar : styles.sidebar}>
|
||||||
<AppInfo {...appInfo} onGoToAuth={this.onGoToAuth} />
|
<AppInfo {...client} onGoToAuth={this.onGoToAuth} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
<PanelTransition {...this.props} />
|
<PanelTransition {...this.props} />
|
||||||
@@ -38,3 +43,8 @@ export default class AuthPage extends Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default connect((state) => ({
|
||||||
|
client: state.auth.client
|
||||||
|
}))(AuthPage);
|
||||||
|
@@ -5,6 +5,7 @@ import RootPage from 'pages/root/RootPage';
|
|||||||
import IndexPage from 'pages/index/IndexPage';
|
import IndexPage from 'pages/index/IndexPage';
|
||||||
import AuthPage from 'pages/auth/AuthPage';
|
import AuthPage from 'pages/auth/AuthPage';
|
||||||
|
|
||||||
|
import OAuthInit from 'components/auth/OAuthInit';
|
||||||
import Register from 'components/auth/Register';
|
import Register from 'components/auth/Register';
|
||||||
import Login from 'components/auth/Login';
|
import Login from 'components/auth/Login';
|
||||||
import Permissions from 'components/auth/Permissions';
|
import Permissions from 'components/auth/Permissions';
|
||||||
@@ -47,10 +48,10 @@ export default function routesFactory(store) {
|
|||||||
<Route path="/register" components={new Register()} />
|
<Route path="/register" components={new Register()} />
|
||||||
<Route path="/activation" components={new Activation()} />
|
<Route path="/activation" components={new Activation()} />
|
||||||
<Route path="/oauth/permissions" components={new Permissions()} onEnter={checkAuth} />
|
<Route path="/oauth/permissions" components={new Permissions()} onEnter={checkAuth} />
|
||||||
<Route path="/oauth/:id" component={Permissions} />
|
|
||||||
<Route path="/password-change" components={new PasswordChange()} />
|
<Route path="/password-change" components={new PasswordChange()} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
|
<Route path="oauth" component={OAuthInit} />
|
||||||
<Route path="logout" component={Logout} />
|
<Route path="logout" component={Logout} />
|
||||||
</Route>
|
</Route>
|
||||||
);
|
);
|
||||||
|
@@ -2,7 +2,7 @@ function serialize(data) {
|
|||||||
return Object.keys(data)
|
return Object.keys(data)
|
||||||
.map(
|
.map(
|
||||||
(keyName) =>
|
(keyName) =>
|
||||||
[keyName, data[keyName]]
|
[keyName, typeof data[keyName] === 'undefined' ? '' : data[keyName]]
|
||||||
.map(encodeURIComponent)
|
.map(encodeURIComponent)
|
||||||
.join('=')
|
.join('=')
|
||||||
)
|
)
|
||||||
@@ -10,6 +10,9 @@ function serialize(data) {
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toJSON = (resp) => resp.json();
|
||||||
|
const handleResponse = (resp) => Promise[resp.success ? 'resolve' : 'reject'](resp);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
post(url, data) {
|
post(url, data) {
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
@@ -20,8 +23,23 @@ export default {
|
|||||||
},
|
},
|
||||||
body: serialize(data)
|
body: serialize(data)
|
||||||
})
|
})
|
||||||
.then((resp) => resp.json())
|
.then(toJSON)
|
||||||
.then((resp) => Promise[resp.success ? 'resolve' : 'reject'](resp))
|
.then(handleResponse)
|
||||||
|
;
|
||||||
|
},
|
||||||
|
get(url, data) {
|
||||||
|
if (typeof data === 'object') {
|
||||||
|
const separator = url.indexOf('?') === -1 ? '?' : '&';
|
||||||
|
url += separator + serialize(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(url, {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(toJSON)
|
||||||
|
.then(handleResponse)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user