diff --git a/index.js b/index.js index 44d0503..711892f 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ require('dotenv').config(); const express = require('express'); const bodyParser = require('body-parser'); +const { check, validationResult } = require('express-validator'); const connection = require('./db'); const app = express(); @@ -25,6 +26,95 @@ app.get('/api/users', (req, res) => { }); }); +const userValidationMiddlewares = [ + // email must be valid + check('email').isEmail(), + // password must be at least 8 chars long + check('password').isLength({ min: 8 }), + // let's assume a name should be 2 chars long + check('name').isLength({ min: 2 }), +]; + +app.post( + '/api/users', + userValidationMiddlewares, + (req, res) => { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }); + } + // send an SQL query to get all users + return connection.query('INSERT INTO user SET ?', req.body, (err, results) => { + if (err) { + // If an error has occurred, then the client is informed of the error + return res.status(500).json({ + error: err.message, + sql: err.sql, + }); + } + // We use the insertId attribute of results to build the WHERE clause + return connection.query('SELECT * FROM user WHERE id = ?', results.insertId, (err2, records) => { + if (err2) { + return res.status(500).json({ + error: err2.message, + sql: err2.sql, + }); + } + // If all went well, records is an array, from which we use the 1st item + const insertedUser = records[0]; + // Extract all the fields *but* password as a new object (user) + const { password, ...user } = insertedUser; + // Get the host + port (localhost:3000) from the request headers + const host = req.get('host'); + // Compute the full location, e.g. http://localhost:3000/api/users/132 + // This will help the client know where the new resource can be found! + const location = `http://${host}${req.url}/${user.id}`; + return res + .status(200) + .set('Location', location) + .json(user); + }); + }); + }, +); + +app.put( + '/api/users/:id', + userValidationMiddlewares, + (req, res) => { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }); + } + const { email, password, name } = req.body; + return connection.query('UPDATE user SET email=?, password=?, name=? WHERE id=?', [email, password, name, req.params.id], (err, results) => { + if (err) { + // If an error has occurred, then the client is informed of the error + return res.status(500).json({ + error: err.message, + sql: err.sql, + }); + } + return connection.query('SELECT * FROM user WHERE id = ?', req.params.id, (err2, update) => { + if (err2) { + return res.status(500).json({ + error: err2.message, + sql: err2.sql, + }); + } + const updatedUser = update[0]; + const { password, ...user } = updatedUser; + const host = req.get('host'); + const location = { location: `http://${host}${req.url}` }; + const updatedUserWithLocation = { ...user, ...location }; + return res + .status(200) + .json(updatedUserWithLocation); + }); + }); + }, +); + app.listen(process.env.PORT, (err) => { if (err) { throw new Error('Something bad happened...'); diff --git a/package-lock.json b/package-lock.json index 497a612..6390dde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -863,6 +863,15 @@ "vary": "~1.1.2" } }, + "express-validator": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.3.1.tgz", + "integrity": "sha512-YQHQKP/zlUTN6d38uWwXgK3At5phK6R24pOB/ImWisMUz/U/1AC3ZXMgiZYhtH4ViYJ6UAiV0/nj8s1Qs3kmvw==", + "requires": { + "lodash": "^4.17.15", + "validator": "^11.1.0" + } + }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -1413,8 +1422,7 @@ "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "lowercase-keys": { "version": "1.0.1", @@ -2561,6 +2569,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "validator": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-11.1.0.tgz", + "integrity": "sha512-qiQ5ktdO7CD6C/5/mYV4jku/7qnqzjrxb3C/Q5wR3vGGinHTgJZN/TdFT3ZX4vXhX2R1PXx42fB1cn5W+uJ4lg==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index fa9b1df..3d337a8 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "body-parser": "^1.19.0", "dotenv": "^8.2.0", "express": "^4.17.1", + "express-validator": "^6.3.1", "mysql": "^2.17.1" }, "devDependencies": {