From b94d0383cac59d74c7076c6668cb0b71ff3d2270 Mon Sep 17 00:00:00 2001 From: Balthazar GRONON Date: Fri, 2 Oct 2015 16:52:57 +0200 Subject: [PATCH] feat(user): add basic auth service and lognup page --- actions/userLognup.js | 3 ++ app.js | 2 + components/Header.js | 39 ++++++++++++++---- components/pages/Game.js | 2 +- components/pages/Login.js | 46 +++++++++++++++++++++ package.json | 5 ++- routes.js | 7 ++++ stores/AuthStore.js | 79 ++++++++++++++++++++++++++++++++++++ webpack.config.js | 3 ++ webpack.config.production.js | 3 ++ 10 files changed, 179 insertions(+), 10 deletions(-) create mode 100644 actions/userLognup.js create mode 100644 components/pages/Login.js create mode 100644 stores/AuthStore.js diff --git a/actions/userLognup.js b/actions/userLognup.js new file mode 100644 index 0000000..f29ef2d --- /dev/null +++ b/actions/userLognup.js @@ -0,0 +1,3 @@ +export default function userLogin (context, payload) { + context.dispatch('USER_LOGNUP', payload); +} diff --git a/app.js b/app.js index 0d0e1ec..afb2cc2 100644 --- a/app.js +++ b/app.js @@ -3,11 +3,13 @@ import Application from './components/Application'; import ApplicationStore from './stores/ApplicationStore'; import RouteStore from './stores/RouteStore'; import GameStore from './stores/GameStore'; +import AuthStore from './stores/AuthStore'; const app = new Fluxible({ component: Application }); app.registerStore(RouteStore); app.registerStore(GameStore); +app.registerStore(AuthStore); app.registerStore(ApplicationStore); export default app; diff --git a/components/Header.js b/components/Header.js index 13b8b2c..6910721 100644 --- a/components/Header.js +++ b/components/Header.js @@ -1,7 +1,10 @@ import React from 'react'; import { NavLink } from 'fluxible-router'; -export default class Header extends React.Component { +import connectToStores from 'fluxible-addons-react/connectToStores'; +import AuthStore from '../stores/AuthStore'; + +class Header extends React.Component { render () { return ( @@ -15,16 +18,36 @@ export default class Header extends React.Component {
-
- 530 -
-
-
-
-
+ + {this.props.isLogged && ( +
+
+ 530 +
+
+
+
+
+
+ )} + + {!this.props.isLogged && ( + + Login + + )} +
); } } + +export default connectToStores(Header, [AuthStore], (context) => { + let authStore = context.getStore(AuthStore); + return { + isLogged: authStore.isLogged(), + user: authStore.getUser() + }; +}); diff --git a/components/pages/Game.js b/components/pages/Game.js index def1f69..65e3d29 100644 --- a/components/pages/Game.js +++ b/components/pages/Game.js @@ -50,7 +50,7 @@ class Game extends React.Component { this.increment(); } - render() { + render () { let isFinished = this.state.currentWordIndex >= this.props.text.words.length; diff --git a/components/pages/Login.js b/components/pages/Login.js new file mode 100644 index 0000000..518a9bd --- /dev/null +++ b/components/pages/Login.js @@ -0,0 +1,46 @@ +import React from 'react'; + +import connectToStores from 'fluxible-addons-react/connectToStores'; +import AuthStore from '../../stores/AuthStore'; + +import userLognup from '../../actions/userLognup'; + +class Login extends React.Component { + + constructor (props) { + super(props); + this.state = { email: '' }; + } + + lognup () { + this.props.context.executeAction(userLognup, this.state.email); + } + + handleInput (e) { + if (e.which === 13) { return this.lognup(); } + this.setState({ email: e.target.value }); + } + + render () { + return ( +
+

Enter your email to login.

+ +

{this.props.lognupMessage}

+
+ ); + } + +} + +export default connectToStores(Login, [AuthStore], (context) => { + let authStore = context.getStore(AuthStore); + return { + isLogged: authStore.isLogged(), + lognupMessage: authStore.getLognupMessage() + }; +}); diff --git a/package.json b/package.json index 9eb3337..a1c4da2 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,8 @@ "react": "^0.13.0", "serialize-javascript": "^1.0.0", "serve-favicon": "^2.1.6", - "validator": "^4.0.6" + "validator": "^4.0.6", + "whatwg-fetch": "^0.9.0" }, "devDependencies": { "autoprefixer-loader": "^3.1.0", @@ -44,7 +45,9 @@ "bundle-loader": "^0.5.0", "css-loader": "^0.18.0", "eslint": "^0.24.0", + "exports-loader": "^0.6.2", "extract-text-webpack-plugin": "^0.8.2", + "imports-loader": "^0.6.4", "json-loader": "^0.5.1", "node-sass": "^3.3.3", "nodemon": "^1.2.1", diff --git a/routes.js b/routes.js index db5b777..13b0a18 100644 --- a/routes.js +++ b/routes.js @@ -6,6 +6,13 @@ export default { title: 'Home', handler: require('./components/pages/Home') }, + login: { + path: '/login', + method: 'get', + page: 'login', + title: 'Login', + handler: require('./components/pages/Login') + }, game: { path: '/game', method: 'get', diff --git a/stores/AuthStore.js b/stores/AuthStore.js new file mode 100644 index 0000000..6d47da7 --- /dev/null +++ b/stores/AuthStore.js @@ -0,0 +1,79 @@ +import BaseStore from 'fluxible/addons/BaseStore'; + +export default class AuthStore extends BaseStore { + + static getToken () { + let val = '; ' + document.cookie; + let parts = val.split('; token='); + if (parts.length !== 2) { return null; } + return parts.pop().split(';').shift(); + } + + constructor (dispatcher) { + super(dispatcher); + this._user = null; + this._jwt = null; + this._lognupMessage = null; + } + + handleLognup (email) { + + fetch('/api/users', { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ email }) + }) + .then(res => { return res.json(); }) + .then(data => { + this._lognupMessage = data.message; + this.emitChange(); + }); + + } + + handleLogin () { + fetch('/api/users/me', { + method: 'GET', + headers: { Authorization: 'Bearer ' + 'tttt' } + }) + .then(user => { + console.log(user); + }) + .catch(err => { + console.log(err); + }); + this._jwt = jwt; + this._user = {}; + this.emitChange(); + } + + handleLogout () { + this._jwt = null; + this._user = null; + this.emitChange(); + } + + getUser () { + return this._user; + } + + getLognupMessage () { + return this._lognupMessage; + } + + isLogged () { + return !!this._user; + } + +} + +AuthStore.storeName = 'AuthStore'; + +AuthStore.handlers = { + USER_LOGNUP: 'handleLognup', + USER_LOGIN: 'handleLogin', + USER_LOGOUT: 'handleLogout' +}; diff --git a/webpack.config.js b/webpack.config.js index f38221a..38b43b5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -46,6 +46,9 @@ var webpackConfig = { NODE_ENV: JSON.stringify(process.env.NODE_ENV), BROWSER: JSON.stringify(true) } + }), + new webpack.ProvidePlugin({ + fetch: 'imports?this=>global!exports?global.fetch!whatwg-fetch' }) ], devtool: 'eval' diff --git a/webpack.config.production.js b/webpack.config.production.js index 480cb6c..5ef43cb 100644 --- a/webpack.config.production.js +++ b/webpack.config.production.js @@ -43,6 +43,9 @@ var webpackConfig = { compress: { warnings: false } + }), + new webpack.ProvidePlugin({ + fetch: 'imports?this=>global!exports?global.fetch!whatwg-fetch' }) ] };