├── .gitignore ├── index.js ├── knexfile.js ├── migrations ├── 20170504155313_create_user_table.js └── 20170504165046_encrypt_user_password.js ├── package.json ├── public ├── app.js └── index.html └── store.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const bodyParser = require('body-parser') 3 | const store = require('./store') 4 | const app = express() 5 | app.use(express.static('public')) 6 | app.use(bodyParser.json()) 7 | app.post('/createUser', (req, res) => { 8 | store 9 | .createUser({ 10 | username: req.body.username, 11 | password: req.body.password 12 | }) 13 | .then(() => res.sendStatus(200)) 14 | }) 15 | app.post('/login', (req, res) => { 16 | store 17 | .authenticate({ 18 | username: req.body.username, 19 | password: req.body.password 20 | }) 21 | .then(({ success }) => { 22 | if (success) res.sendStatus(200) 23 | else res.sendStatus(401) 24 | }) 25 | }) 26 | app.listen(7555, () => { 27 | console.log('Server running on http://localhost:7555') 28 | }) 29 | -------------------------------------------------------------------------------- /knexfile.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | client: 'mysql', 3 | connection: { 4 | user: 'root', 5 | password: 'password', 6 | database: 'tutorial_node_database' 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /migrations/20170504155313_create_user_table.js: -------------------------------------------------------------------------------- 1 | exports.up = function (knex) { 2 | return knex.schema.createTable('user', function (t) { 3 | t.increments('id').primary() 4 | t.string('username').notNullable() 5 | t.string('password').notNullable() 6 | t.timestamps(false, true) 7 | }) 8 | } 9 | 10 | exports.down = function (knex) { 11 | return knex.schema.dropTableIfExists('user') 12 | } 13 | -------------------------------------------------------------------------------- /migrations/20170504165046_encrypt_user_password.js: -------------------------------------------------------------------------------- 1 | const { saltHashPassword } = require('../store') 2 | 3 | exports.up = async function up (knex) { 4 | await knex.schema.table('user', t => { 5 | t.string('salt').notNullable() 6 | t.string('encrypted_password').notNullable() 7 | }) 8 | const users = await knex('user') 9 | await Promise.all(users.map(convertPassword)) 10 | await knex.schema.table('user', t => { 11 | t.dropColumn('password') 12 | }) 13 | 14 | function convertPassword (user) { 15 | const { salt, hash } = saltHashPassword(user.password) 16 | return knex('user') 17 | .where({ id: user.id }) 18 | .update({ 19 | salt, 20 | encrypted_password: hash 21 | }) 22 | } 23 | } 24 | 25 | exports.down = function down (knex) { 26 | return knex.schema.table('user', t => { 27 | t.dropColumn('salt') 28 | t.dropColumn('encrypted_password') 29 | t.string('password').notNullable() 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tutorial-node-database", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/roberttod/tutorial-node-database.git" 12 | }, 13 | "author": "", 14 | "license": "ISC", 15 | "bugs": { 16 | "url": "https://github.com/roberttod/tutorial-node-database/issues" 17 | }, 18 | "homepage": "https://github.com/roberttod/tutorial-node-database#readme", 19 | "dependencies": { 20 | "body-parser": "^1.17.1", 21 | "express": "^4.15.2", 22 | "knex": "^0.13.0", 23 | "mysql": "^2.13.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /public/app.js: -------------------------------------------------------------------------------- 1 | const CreateUser = document.querySelector('.CreateUser') 2 | CreateUser.addEventListener('submit', (e) => { 3 | e.preventDefault() 4 | const username = CreateUser.querySelector('.username').value 5 | const password = CreateUser.querySelector('.password').value 6 | post('/createUser', { username, password }) 7 | }) 8 | 9 | const Login = document.querySelector('.Login') 10 | Login.addEventListener('submit', (e) => { 11 | e.preventDefault() 12 | const username = Login.querySelector('.username').value 13 | const password = Login.querySelector('.password').value 14 | post('/login', { username, password }) 15 | .then(({ status }) => { 16 | if (status === 200) alert('login success') 17 | else alert('login failed') 18 | }) 19 | }) 20 | 21 | function post (path, data) { 22 | return window.fetch(path, { 23 | method: 'POST', 24 | headers: { 25 | 'Accept': 'application/json', 26 | 'Content-Type': 'application/json' 27 | }, 28 | body: JSON.stringify(data) 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |