Skip to content

Instantly share code, notes, and snippets.

@kowsheek
Last active November 24, 2017 16:24
Show Gist options
  • Save kowsheek/802b0e0b7a5cc8b59e00e042df0efa3d to your computer and use it in GitHub Desktop.
Save kowsheek/802b0e0b7a5cc8b59e00e042df0efa3d to your computer and use it in GitHub Desktop.
W4D5 notes
'use strict';
const PORT = process.env.PORT || 8080;
const ENV = process.env.ENV || 'development';
const express = require('express');
const bodyParser = require('body-parser');
const session = require('cookie-session');
const flash = require('connect-flash');
const app = express();
const knexConfig = require('./knexfile');
const knex = require('knex')(knexConfig[ENV]);
// set up dev tools
if (ENV === 'development') {
const morgan = require('morgan');
const knexLogger = require('knex-logger');
app.use(morgan('dev'));
app.use(knexLogger(knex));
}
// set up middleware
app.use(session({
name: 'session',
keys: 'alphabrain'
}));
app.use(flash());
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: true }));
// set up services
const userService = require('./userService')(knex);
// set up routes
app.get('/', function (req, res) {
res.render('index', {
errors: req.flash('errors'),
info: req.flash('info'),
user: req.session.user_email
});
});
app.post('/signup', function (req, res) {
let { name, email, password } = req.body;
userService.createUser(name, email, password)
.then(function (user) {
req.session.user_email = user.email;
res.render('index', {
errors: req.flash('errors'),
info: req.flash('info'),
user: req.session.user_email
});
})
.catch(function (err) {
req.flash('errors', err.message);
res.redirect('/');
});
});
app.post('/signin', function (req, res) {
const { email, password } = req.body;
userService.authenticate(email, password)
.then(function (user) {
req.session.user_email = user.email;
res.render('index', {
errors: req.flash('errors'),
info: req.flash('info'),
user: req.session.user_email
});
})
.catch(function (err) {
req.flash('errors', err.message);
res.render('index', {
errors: req.flash('errors'),
info: req.flash('info'),
user: {}
});
});
});
app.listen(PORT, function () {
console.log('App listening at 8080');
});
{
"name": "user-auth",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^1.0.3",
"body-parser": "^1.15.2",
"connect-flash": "^0.1.1",
"cookie-session": "^2.0.0-beta.3",
"ejs": "^2.4.1",
"express": "^4.13.4",
"knex": "^0.11.7",
"pg": "^6.0.2"
},
"devDependencies": {
"morgan": "^1.7.0",
"knex-logger": "^0.1.0",
"nodemon": "^1.9.2"
}
}
exports.up = function (knex, Promise) {
return knex.schema.createTable('users', function (table) {
table.increments();
table.string('name').notNullable();
table.string('email').unique().notNullable();
table.string('password_digest').notNullable();
});
};
exports.down = function (knex, Promise) {
return knex.schema.dropTable('users');
};
const { hash, compare } = require('bcrypt');
module.exports = function (knex) {
let service = {};
service.getUserByEmail = function (email) {
return knex.select()
.where({ email: email })
.from('users')
.first();
};
service.createUser = function (name, email, password) {
return new Promise(function (resolve, reject) {
service.getUserByEmail(email)
.then(function (user) {
if (!user) {
return hash(password, 10);
}
else {
return reject({ message: 'User with email exists' });
}
})
.then(function (passwordDigest) {
return knex('users').insert({
name: name,
email: email,
password_digest: passwordDigest
});
})
.then(function () {
return service.getUserByEmail(email);
})
.then(function (user) {
return resolve(user);
})
.catch(function () {
return reject({ message: 'Unable to create user' });
});
});
};
service.authenticate = function (email, password) {
return new Promise(function (resolve, reject) {
service.getUserByEmail(email)
.then(function (user) {
if (!user) {
return reject('No user found');
}
compare(password, user.password_digest)
.then(function (equal) {
if (equal) {
return resolve(user);
}
else {
return reject({ message: 'Password is incorrect' });
}
}).catch(function () {
return reject({ message: 'Unable to authenticate' });
});
});
});
};
return service;
};
<!DOCTYPE html>
<html lang="en">
<head>
<title>Home</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb"
crossorigin="anonymous" />
</head>
<body>
<div class="container">
<%- include partials/_flash.ejs %>
<div class="jumbotron">
<h1>Welcome</h1>
<h2>
<small>
<% user %>
</small>
</h2>
</div>
<div class="row">
<div class="col-sm-6">
<form class="form" method="POST" action="/signup">
<h2>Register</h2>
<div class="form-group">
<label>Name</label>
<input class="form-control" type="text" name="name" />
</div>
<div class="form-group">
<label>Email</label>
<input class="form-control" type="email" name="email" />
</div>
<div class="form-group">
<label>Password</label>
<input class="form-control" type="password" name="password" />
</div>
<div class="form-group">
<label>Confirm Password</label>
<input class="form-control" type="password" name="passwordConfirm" />
</div>
<div>
<button class="btn btn-primary" type="submit">Register</button>
</div>
</form>
</div>
<div class="col-sm-6">
<form class="form" method="POST" action="/signin">
<h2>Log In</h2>
<div class="form-group">
<label>Email</label>
<input class="form-control" type="email" name="email" />
</div>
<div class="form-group">
<label>Password</label>
<input class="form-control" type="password" name="password" />
</div>
<div>
<button class="btn btn-primary" type="submit">Log in</button>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
<% if (errors.length) { %>
<% errors.forEach((error) => { %>
<p class="error">Error: <%= error %></p>
<% }) %>
<% } %>
<% if (info.length) { %>
<% info.forEach((message) => { %>
<p class="info">Info: <%= message %></p>
<% }) %>
<% } %>

Background

  • Authentication

    • Email & password security
    • Cookies
    • Tokens (JWT)
  • Authorization

    • Roles
    • Permissions
  • Encryption

    • Hashing
    • SALTing

Development environment

  • Loggers
    • morgan
    • knex-logger

Demo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment