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')); | ||||
|     }; | ||||
| } | ||||
|  | ||||
| // 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 { ERROR } from './actions'; | ||||
| import { ERROR, SET_CLIENT } from './actions'; | ||||
|  | ||||
| export default combineReducers({ | ||||
|     error | ||||
|     error, | ||||
|     client | ||||
| }); | ||||
|  | ||||
| function error( | ||||
| @@ -21,3 +22,20 @@ function error( | ||||
|             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 PanelTransition from 'components/auth/PanelTransition'; | ||||
|  | ||||
| import styles from './auth.scss'; | ||||
|  | ||||
| export default class AuthPage extends Component { | ||||
| class AuthPage extends Component { | ||||
|     static displayName = 'AuthPage'; | ||||
|     static propTypes = { | ||||
|         client: PropTypes.shape({ | ||||
|             id: PropTypes.string.isRequired, | ||||
|             name: PropTypes.string.isRequired, | ||||
|             description: PropTypes.string.isRequired | ||||
|         }) | ||||
|     }; | ||||
|  | ||||
|     state = { | ||||
|         isSidebarHidden: false | ||||
|     }; | ||||
|  | ||||
|     render() { | ||||
|         var {isSidebarHidden} = this.state; | ||||
|  | ||||
|         var appInfo = { | ||||
|             name: 'TLauncher', | ||||
|             description: `Лучший альтернативный лаунчер для Minecraft с большим количеством версий и их модификаций, а также возмоностью входа как с лицензионным аккаунтом, так и без него.` | ||||
|         }; | ||||
|         const {isSidebarHidden} = this.state; | ||||
|         const {client} = this.props; | ||||
|  | ||||
|         return ( | ||||
|             <div> | ||||
|                 <div className={isSidebarHidden ? styles.hiddenSidebar : styles.sidebar}> | ||||
|                     <AppInfo {...appInfo} onGoToAuth={this.onGoToAuth} /> | ||||
|                     <AppInfo {...client} onGoToAuth={this.onGoToAuth} /> | ||||
|                 </div> | ||||
|                 <div className={styles.content}> | ||||
|                     <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 AuthPage from 'pages/auth/AuthPage'; | ||||
|  | ||||
| import OAuthInit from 'components/auth/OAuthInit'; | ||||
| import Register from 'components/auth/Register'; | ||||
| import Login from 'components/auth/Login'; | ||||
| import Permissions from 'components/auth/Permissions'; | ||||
| @@ -47,10 +48,10 @@ export default function routesFactory(store) { | ||||
|                 <Route path="/register" components={new Register()} /> | ||||
|                 <Route path="/activation" components={new Activation()} /> | ||||
|                 <Route path="/oauth/permissions" components={new Permissions()} onEnter={checkAuth} /> | ||||
|                 <Route path="/oauth/:id" component={Permissions} /> | ||||
|                 <Route path="/password-change" components={new PasswordChange()} /> | ||||
|             </Route> | ||||
|  | ||||
|             <Route path="oauth" component={OAuthInit} /> | ||||
|             <Route path="logout" component={Logout} /> | ||||
|         </Route> | ||||
|     ); | ||||
|   | ||||
| @@ -2,7 +2,7 @@ function serialize(data) { | ||||
|     return Object.keys(data) | ||||
|         .map( | ||||
|             (keyName) => | ||||
|                 [keyName, data[keyName]] | ||||
|                 [keyName, typeof data[keyName] === 'undefined' ? '' : data[keyName]] | ||||
|                     .map(encodeURIComponent) | ||||
|                     .join('=') | ||||
|         ) | ||||
| @@ -10,6 +10,9 @@ function serialize(data) { | ||||
|         ; | ||||
| } | ||||
|  | ||||
| const toJSON = (resp) => resp.json(); | ||||
| const handleResponse = (resp) => Promise[resp.success ? 'resolve' : 'reject'](resp); | ||||
|  | ||||
| export default { | ||||
|     post(url, data) { | ||||
|         return fetch(url, { | ||||
| @@ -20,8 +23,23 @@ export default { | ||||
|             }, | ||||
|             body: serialize(data) | ||||
|         }) | ||||
|         .then((resp) => resp.json()) | ||||
|         .then((resp) => Promise[resp.success ? 'resolve' : 'reject'](resp)) | ||||
|         .then(toJSON) | ||||
|         .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