From d672166b8737b217e8bf6928cbdcf253c7eb818c Mon Sep 17 00:00:00 2001 From: catarak Date: Tue, 14 Jun 2016 16:48:16 -0400 Subject: [PATCH] add login view --- server/config/passport.js | 2 +- server/controllers/session.controller.js | 30 ++++++++++++++++++++ server/controllers/sessions.controller.js | 12 -------- server/routes/session.routes.js | 2 ++ server/server.js | 5 ++-- shared/components/LoginForm/LoginForm.jsx | 22 +++++++++++++++ shared/containers/LoginView/LoginView.jsx | 34 +++++++++++++++++++---- shared/redux/actions/user.js | 12 ++++++++ styles/components/_login.scss | 21 ++++++++++++++ styles/main.scss | 1 + 10 files changed, 119 insertions(+), 22 deletions(-) create mode 100644 server/controllers/session.controller.js delete mode 100644 server/controllers/sessions.controller.js create mode 100644 shared/components/LoginForm/LoginForm.jsx create mode 100644 styles/components/_login.scss diff --git a/server/config/passport.js b/server/config/passport.js index fe6c7c2f..0b78b96c 100644 --- a/server/config/passport.js +++ b/server/config/passport.js @@ -2,7 +2,7 @@ const passport = require('passport'); const GitHubStrategy = require('passport-github').Strategy; const LocalStrategy = require('passport-local').Strategy; -const User = require('../models/user'); +import User from '../models/user' passport.serializeUser((user, done) => { done(null, user.id); diff --git a/server/controllers/session.controller.js b/server/controllers/session.controller.js new file mode 100644 index 00000000..dcd3ebd1 --- /dev/null +++ b/server/controllers/session.controller.js @@ -0,0 +1,30 @@ +import User from '../models/user' +import passport from 'passport' +import path from 'path' + + +export function newSession(req, res, next) { + //eventually, it would be cool to have some isomorphic rendering + res.sendFile(path.resolve(__dirname + '/../../index.html')); +} + +export function destroySession(req, res) { + +} + +export function createSession(req, res, next) { + passport.authenticate('local', (err, user, info) => { + if (err) { return next(err); } + if (!user) { + return res.status(401).send({ error: 'Invalid username or password' }); + } + + req.logIn(user, (err) => { + if (err) { return next(err); } + res.json({ + email: req.user.email, + username: req.user.username + }); + }); + })(req, res, next); +} \ No newline at end of file diff --git a/server/controllers/sessions.controller.js b/server/controllers/sessions.controller.js deleted file mode 100644 index 4547af25..00000000 --- a/server/controllers/sessions.controller.js +++ /dev/null @@ -1,12 +0,0 @@ - -export function newSession(req, res) { - -} - -export function destroySession(req, res) { - -} - -export function createSession(req, res) { - -} \ No newline at end of file diff --git a/server/routes/session.routes.js b/server/routes/session.routes.js index 6cca9a93..241a6146 100644 --- a/server/routes/session.routes.js +++ b/server/routes/session.routes.js @@ -10,4 +10,6 @@ router.route('/login').post(SessionController.createSession); router.route('/logout').get(SessionController.destroySession); +export default router; + //TODO add github authentication stuff diff --git a/server/server.js b/server/server.js index 2f9a651e..95fcc565 100644 --- a/server/server.js +++ b/server/server.js @@ -23,6 +23,7 @@ app.use(webpackHotMiddleware(compiler)); //Import all required modules import serverConfig from './config'; import users from './routes/user.routes'; +import sessions from './routes/session.routes'; //Body parser, cookie parser, sessions, serve public assets @@ -48,6 +49,7 @@ app.use(session({ app.use(passport.initialize()); app.use(passport.session()); app.use('/', users); +app.use('/', sessions); const passportConfig = require('./config/passport'); @@ -62,9 +64,6 @@ mongoose.connection.on('error', () => { app.get("/", function(req, res) { res.sendFile(path.resolve(__dirname + '/../index.html')); }) -app.get("/login", function(req, res) { - res.sendFile(path.resolve(__dirname + '/../index.html')); -}) // start app app.listen(serverConfig.port, (error) => { diff --git a/shared/components/LoginForm/LoginForm.jsx b/shared/components/LoginForm/LoginForm.jsx new file mode 100644 index 00000000..f05a3ab9 --- /dev/null +++ b/shared/components/LoginForm/LoginForm.jsx @@ -0,0 +1,22 @@ +import React from 'react' + +class LoginForm extends React.Component { + render() { + const {fields: {email, password}, handleSubmit } = this.props; + return ( +
+

+ + +

+

+ + +

+ +
+ ) + } +} + +export default LoginForm; \ No newline at end of file diff --git a/shared/containers/LoginView/LoginView.jsx b/shared/containers/LoginView/LoginView.jsx index ff9ab19c..47e6c26d 100644 --- a/shared/containers/LoginView/LoginView.jsx +++ b/shared/containers/LoginView/LoginView.jsx @@ -1,15 +1,37 @@ import React from 'react' +import { bindActionCreators } from 'redux' +import {reduxForm} from 'redux-form' +import * as UserActions from '../../redux/actions/user' +import LoginForm from '../../components/LoginForm/LoginForm' class LoginView extends React.Component { render() { return ( -
- - - -
+
+

Login

+ +
) } } -export default LoginView; \ No newline at end of file +function mapStateToProps(state) { + return { + user: state.user + } +} + +function mapDispatchToProps(dispatch) { + return bindActionCreators(UserActions, dispatch); +} + +function validate(formProps) { + const errors = {}; + return errors; +} + +export default reduxForm({ + form: 'login', + fields: ['email', 'password'], + validate +}, mapStateToProps, mapDispatchToProps)(LoginView); \ No newline at end of file diff --git a/shared/redux/actions/user.js b/shared/redux/actions/user.js index 4c2d2144..59317e90 100644 --- a/shared/redux/actions/user.js +++ b/shared/redux/actions/user.js @@ -18,6 +18,18 @@ export function signUpUser(formValues) { } } +export function loginUser(formValues) { + return function(dispatch) { + axios.post(`${ROOT_URL}/login`, formValues, {withCredentials: true}) + .then(response => { + dispatch({ type: ActionTypes.AUTH_USER, + user: response.data + }); + browserHistory.push('/'); + }) + .catch(response => dispatch(authError(response.data.error))); + } +} export function authError(error) { return { diff --git a/styles/components/_login.scss b/styles/components/_login.scss new file mode 100644 index 00000000..35ffef8b --- /dev/null +++ b/styles/components/_login.scss @@ -0,0 +1,21 @@ +.login { + text-align: center; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; +} + +.login-form__email-label, +.login-form__password-label { + display: none; +} + +.login-form__email-input, +.login-form__password-input { + width: #{300 / $base-font-size}rem; +} + +.login-form__field { + margin: #{20 / $base-font-size}rem 0; +} diff --git a/styles/main.scss b/styles/main.scss index 5cd91b77..1e23ae9d 100644 --- a/styles/main.scss +++ b/styles/main.scss @@ -12,5 +12,6 @@ @import 'components/toolbar'; @import 'components/preferences'; @import 'components/signup'; +@import 'components/login'; @import 'layout/ide';