add login view

This commit is contained in:
catarak 2016-06-14 16:48:16 -04:00
parent 0c54f372c1
commit d672166b87
10 changed files with 119 additions and 22 deletions

View file

@ -2,7 +2,7 @@ const passport = require('passport');
const GitHubStrategy = require('passport-github').Strategy; const GitHubStrategy = require('passport-github').Strategy;
const LocalStrategy = require('passport-local').Strategy; const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/user'); import User from '../models/user'
passport.serializeUser((user, done) => { passport.serializeUser((user, done) => {
done(null, user.id); done(null, user.id);

View file

@ -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);
}

View file

@ -1,12 +0,0 @@
export function newSession(req, res) {
}
export function destroySession(req, res) {
}
export function createSession(req, res) {
}

View file

@ -10,4 +10,6 @@ router.route('/login').post(SessionController.createSession);
router.route('/logout').get(SessionController.destroySession); router.route('/logout').get(SessionController.destroySession);
export default router;
//TODO add github authentication stuff //TODO add github authentication stuff

View file

@ -23,6 +23,7 @@ app.use(webpackHotMiddleware(compiler));
//Import all required modules //Import all required modules
import serverConfig from './config'; import serverConfig from './config';
import users from './routes/user.routes'; import users from './routes/user.routes';
import sessions from './routes/session.routes';
//Body parser, cookie parser, sessions, serve public assets //Body parser, cookie parser, sessions, serve public assets
@ -48,6 +49,7 @@ app.use(session({
app.use(passport.initialize()); app.use(passport.initialize());
app.use(passport.session()); app.use(passport.session());
app.use('/', users); app.use('/', users);
app.use('/', sessions);
const passportConfig = require('./config/passport'); const passportConfig = require('./config/passport');
@ -62,9 +64,6 @@ mongoose.connection.on('error', () => {
app.get("/", function(req, res) { app.get("/", function(req, res) {
res.sendFile(path.resolve(__dirname + '/../index.html')); res.sendFile(path.resolve(__dirname + '/../index.html'));
}) })
app.get("/login", function(req, res) {
res.sendFile(path.resolve(__dirname + '/../index.html'));
})
// start app // start app
app.listen(serverConfig.port, (error) => { app.listen(serverConfig.port, (error) => {

View file

@ -0,0 +1,22 @@
import React from 'react'
class LoginForm extends React.Component {
render() {
const {fields: {email, password}, handleSubmit } = this.props;
return (
<form className="login-form" onSubmit={handleSubmit(this.props.loginUser.bind(this))}>
<p className="login-form__field">
<label className="login-form__email-label" for="email">Email:</label>
<input className="login-form__email-input" id="email" type="text" placeholder="Email" {...email}/>
</p>
<p className="login-form__field">
<label className="signup-form__password-label" for="password">Password:</label>
<input className="signup-form__password-input" id="password" type="password" placeholder="Password" {...password}/>
</p>
<input type="submit" value="Login" />
</form>
)
}
}
export default LoginForm;

View file

@ -1,15 +1,37 @@
import React from 'react' 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 { class LoginView extends React.Component {
render() { render() {
return ( return (
<form> <div className="login">
<input type="text" placeholder="Username or email"/> <h1>Login</h1>
<input type="password" placeholder="Password"/> <LoginForm {...this.props} />
<input type="submit" value="Log In" /> </div>
</form>
) )
} }
} }
export default LoginView; 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);

View file

@ -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) { export function authError(error) {
return { return {

View file

@ -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;
}

View file

@ -12,5 +12,6 @@
@import 'components/toolbar'; @import 'components/toolbar';
@import 'components/preferences'; @import 'components/preferences';
@import 'components/signup'; @import 'components/signup';
@import 'components/login';
@import 'layout/ide'; @import 'layout/ide';