├── .gitignore
├── public
├── text
│ └── data.txt
├── img
│ └── img1.jpg
└── css
│ └── style.css
├── config
├── roles_list.js
├── allowedOrigins.js
├── dbConn.js
└── corsOptions.js
├── routes
├── auth.js
├── logout.js
├── register.js
├── refresh.js
├── root.js
└── api
│ └── employees.js
├── model
├── employees.json
└── users.json
├── middleware
├── errorHandler.js
├── credentials.js
├── verifyRoles.js
├── verifyJWT.js
└── logEvents.js
├── views
├── 404.html
└── index.html
├── package.json
├── README.md
├── logs
└── reqLog.txt
├── controllers
├── refreshTokenController.js
├── logoutController.js
├── registerController.js
├── authController.js
└── employeesController.js
└── server.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env
3 |
--------------------------------------------------------------------------------
/public/text/data.txt:
--------------------------------------------------------------------------------
1 | Just some random text.
--------------------------------------------------------------------------------
/public/img/img1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitdagray/mongodb_mongoose_intro/HEAD/public/img/img1.jpg
--------------------------------------------------------------------------------
/config/roles_list.js:
--------------------------------------------------------------------------------
1 | const ROLES_LIST = {
2 | "Admin": 5150,
3 | "Editor": 1984,
4 | "User": 2001
5 | }
6 |
7 | module.exports = ROLES_LIST
--------------------------------------------------------------------------------
/config/allowedOrigins.js:
--------------------------------------------------------------------------------
1 | const allowedOrigins = [
2 | 'https://www.yoursite.com',
3 | 'http://127.0.0.1:5500',
4 | 'http://localhost:3500'
5 | ];
6 |
7 | module.exports = allowedOrigins;
--------------------------------------------------------------------------------
/routes/auth.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const router = express.Router();
3 | const authController = require('../controllers/authController');
4 |
5 | router.post('/', authController.handleLogin);
6 |
7 | module.exports = router;
--------------------------------------------------------------------------------
/model/employees.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 1,
4 | "firstname": "Dave",
5 | "lastname": "Gray"
6 | },
7 | {
8 | "id": 2,
9 | "firstname": "John",
10 | "lastname": "Smith"
11 | }
12 | ]
--------------------------------------------------------------------------------
/routes/logout.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const router = express.Router();
3 | const logoutController = require('../controllers/logoutController');
4 |
5 | router.get('/', logoutController.handleLogout);
6 |
7 | module.exports = router;
--------------------------------------------------------------------------------
/routes/register.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const router = express.Router();
3 | const registerController = require('../controllers/registerController');
4 |
5 | router.post('/', registerController.handleNewUser);
6 |
7 | module.exports = router;
--------------------------------------------------------------------------------
/routes/refresh.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const router = express.Router();
3 | const refreshTokenController = require('../controllers/refreshTokenController');
4 |
5 | router.get('/', refreshTokenController.handleRefreshToken);
6 |
7 | module.exports = router;
--------------------------------------------------------------------------------
/routes/root.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const router = express.Router();
3 | const path = require('path');
4 |
5 | router.get('^/$|/index(.html)?', (req, res) => {
6 | res.sendFile(path.join(__dirname, '..', 'views', 'index.html'));
7 | });
8 |
9 | module.exports = router;
--------------------------------------------------------------------------------
/public/css/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-size: 36px;
9 | min-height: 100vh;
10 | color: #fff;
11 | background-color: #000;
12 | display: grid;
13 | place-content: center;
14 | }
15 |
--------------------------------------------------------------------------------
/middleware/errorHandler.js:
--------------------------------------------------------------------------------
1 | const { logEvents } = require('./logEvents');
2 |
3 | const errorHandler = (err, req, res, next) => {
4 | logEvents(`${err.name}: ${err.message}`, 'errLog.txt');
5 | console.error(err.stack)
6 | res.status(500).send(err.message);
7 | }
8 |
9 | module.exports = errorHandler;
--------------------------------------------------------------------------------
/middleware/credentials.js:
--------------------------------------------------------------------------------
1 | const allowedOrigins = require('../config/allowedOrigins');
2 |
3 | const credentials = (req, res, next) => {
4 | const origin = req.headers.origin;
5 | if (allowedOrigins.includes(origin)) {
6 | res.header('Access-Control-Allow-Credentials', true);
7 | }
8 | next();
9 | }
10 |
11 | module.exports = credentials
--------------------------------------------------------------------------------
/config/dbConn.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 |
3 | const connectDB = async () => {
4 | try {
5 | await mongoose.connect(process.env.DATABASE_URI, {
6 | useUnifiedTopology: true,
7 | useNewUrlParser: true
8 | });
9 | } catch (err) {
10 | console.error(err);
11 | }
12 | }
13 |
14 | module.exports = connectDB
--------------------------------------------------------------------------------
/views/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 404
9 |
10 |
11 |
12 |
13 | 404
14 |
15 |
16 |
--------------------------------------------------------------------------------
/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Index
9 |
10 |
11 |
12 |
13 | Index
14 |
15 |
16 |
--------------------------------------------------------------------------------
/config/corsOptions.js:
--------------------------------------------------------------------------------
1 | const allowedOrigins = require('./allowedOrigins');
2 |
3 | const corsOptions = {
4 | origin: (origin, callback) => {
5 | if (allowedOrigins.indexOf(origin) !== -1 || !origin) {
6 | callback(null, true)
7 | } else {
8 | callback(new Error('Not allowed by CORS'));
9 | }
10 | },
11 | optionsSuccessStatus: 200
12 | }
13 |
14 | module.exports = corsOptions;
--------------------------------------------------------------------------------
/middleware/verifyRoles.js:
--------------------------------------------------------------------------------
1 | const verifyRoles = (...allowedRoles) => {
2 | return (req, res, next) => {
3 | if (!req?.roles) return res.sendStatus(401);
4 | const rolesArray = [...allowedRoles];
5 | const result = req.roles.map(role => rolesArray.includes(role)).find(val => val === true);
6 | if (!result) return res.sendStatus(401);
7 | next();
8 | }
9 | }
10 |
11 | module.exports = verifyRoles
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "13tut",
3 | "version": "1.0.0",
4 | "description": "MongoDB tutorial",
5 | "main": "server.js",
6 | "scripts": {
7 | "start": "node server",
8 | "dev": "nodemon server"
9 | },
10 | "author": "Dave Gray",
11 | "license": "ISC",
12 | "dependencies": {
13 | "bcrypt": "^5.0.1",
14 | "cookie-parser": "^1.4.5",
15 | "cors": "^2.8.5",
16 | "date-fns": "^2.23.0",
17 | "dotenv": "^10.0.0",
18 | "express": "^4.17.1",
19 | "jsonwebtoken": "^8.5.1",
20 | "mongoose": "^6.0.11",
21 | "uuid": "^8.3.2"
22 | },
23 | "devDependencies": {
24 | "nodemon": "^2.0.12"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/middleware/verifyJWT.js:
--------------------------------------------------------------------------------
1 | const jwt = require('jsonwebtoken');
2 |
3 | const verifyJWT = (req, res, next) => {
4 | const authHeader = req.headers.authorization || req.headers.Authorization;
5 | if (!authHeader?.startsWith('Bearer ')) return res.sendStatus(401);
6 | const token = authHeader.split(' ')[1];
7 | jwt.verify(
8 | token,
9 | process.env.ACCESS_TOKEN_SECRET,
10 | (err, decoded) => {
11 | if (err) return res.sendStatus(403); //invalid token
12 | req.user = decoded.UserInfo.username;
13 | req.roles = decoded.UserInfo.roles;
14 | next();
15 | }
16 | );
17 | }
18 |
19 | module.exports = verifyJWT
--------------------------------------------------------------------------------
/routes/api/employees.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const router = express.Router();
3 | const employeesController = require('../../controllers/employeesController');
4 | const ROLES_LIST = require('../../config/roles_list');
5 | const verifyRoles = require('../../middleware/verifyRoles');
6 |
7 | router.route('/')
8 | .get(employeesController.getAllEmployees)
9 | .post(verifyRoles(ROLES_LIST.Admin, ROLES_LIST.Editor), employeesController.createNewEmployee)
10 | .put(verifyRoles(ROLES_LIST.Admin, ROLES_LIST.Editor), employeesController.updateEmployee)
11 | .delete(verifyRoles(ROLES_LIST.Admin), employeesController.deleteEmployee);
12 |
13 | router.route('/:id')
14 | .get(employeesController.getEmployee);
15 |
16 | module.exports = router;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # "Node JS Tutorial Series - MongoDB with Mongoose"
2 |
3 | ✅ [Check out my YouTube Channel with all of my tutorials](https://www.youtube.com/DaveGrayTeachesCode).
4 |
5 | **Description:**
6 |
7 | This repository shares the code applied during the Youtube tutorial. The tutorial is part of a [Node.js & Express for Beginners Playlist](https://www.youtube.com/playlist?list=PL0Zuz27SZ-6PFkIxaJ6Xx_X46avTM1aYw) on my channel.
8 |
9 | [YouTube Tutorial](https://youtu.be/-PdjUx9JZ2E) for this repository.
10 |
11 | I suggest completing my [8 hour JavaScript course tutorial video](https://youtu.be/EfAl9bwzVZk) if you are new to Javascript.
12 |
13 | ### Academic Honesty
14 |
15 | **DO NOT COPY FOR AN ASSIGNMENT** - Avoid plagiargism and adhere to the spirit of this [Academic Honesty Policy](https://www.freecodecamp.org/news/academic-honesty-policy/).
16 |
--------------------------------------------------------------------------------
/model/users.json:
--------------------------------------------------------------------------------
1 | [{"username":"dave1","roles":{"User":2001},"password":"$2b$10$oEbHZlazDHE1YnnJ4XdpGuGh9a/JZOO7Xe6WZtRRsSMgprxMXnKza","refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImRhdmUxIiwiaWF0IjoxNjMzOTkyMjkwLCJleHAiOjE2MzQwNzg2OTB9.U85HVX_gcDZkHHSRWeo7AHfIe7q9i03dGW2ed3fHqAk"},{"username":"walt2","roles":{"User":2001,"Editor":1984},"password":"$2b$10$cvfmz./teMWDccIMChAxZ.HqgL3eoQGYTm1z9lGy5iRf8D7NNargC","refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IndhbHQyIiwiaWF0IjoxNjMzOTkyNDU2LCJleHAiOjE2MzQwNzg4NTZ9.wRVJbN7_67JyTW9PALMWWEsO4BMkehyy5kXq6WilvWc"},{"username":"walt1","roles":{"User":2001,"Editor":1984,"Admin":5150},"password":"$2b$10$33Q9jtAoaXC4aUX9Bjihxum2BHG.ENB6JyoCvPjnuXpITtUd8x8/y","refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IndhbHQxIiwiaWF0IjoxNjMzOTkyNTY0LCJleHAiOjE2MzQwNzg5NjR9.gE2CgbtEuqE42LeJ4dP6APmqyGTNBh53WXVyDdP47yM"}]
--------------------------------------------------------------------------------
/middleware/logEvents.js:
--------------------------------------------------------------------------------
1 | const { format } = require('date-fns');
2 | const { v4: uuid } = require('uuid');
3 |
4 | const fs = require('fs');
5 | const fsPromises = require('fs').promises;
6 | const path = require('path');
7 |
8 | const logEvents = async (message, logName) => {
9 | const dateTime = `${format(new Date(), 'yyyyMMdd\tHH:mm:ss')}`;
10 | const logItem = `${dateTime}\t${uuid()}\t${message}\n`;
11 |
12 | try {
13 | if (!fs.existsSync(path.join(__dirname, '..', 'logs'))) {
14 | await fsPromises.mkdir(path.join(__dirname, '..', 'logs'));
15 | }
16 |
17 | await fsPromises.appendFile(path.join(__dirname, '..', 'logs', logName), logItem);
18 | } catch (err) {
19 | console.log(err);
20 | }
21 | }
22 |
23 | const logger = (req, res, next) => {
24 | logEvents(`${req.method}\t${req.headers.origin}\t${req.url}`, 'reqLog.txt');
25 | console.log(`${req.method} ${req.path}`);
26 | next();
27 | }
28 |
29 | module.exports = { logger, logEvents };
30 |
--------------------------------------------------------------------------------
/logs/reqLog.txt:
--------------------------------------------------------------------------------
1 | 20211011 17:44:50 9c6f8dae-33e6-4e75-aa26-9705f6f63c24 POST undefined /auth
2 | 20211011 17:45:07 a1c02ef1-8bb5-4e11-a7db-7dc3e9fb742b GET undefined /employees
3 | 20211011 17:45:19 fc1f8b2b-064a-4751-be68-59442092914d POST undefined /employees
4 | 20211011 17:46:56 98a170c4-3830-48f9-bc19-ac2f80c42d54 POST undefined /auth
5 | 20211011 17:47:10 0a3231e2-3083-42b8-bf71-2e699508452b POST undefined /employees
6 | 20211011 17:47:26 b880f8d2-4af3-4f8a-acfc-64635b35b81f DELETE undefined /employees
7 | 20211011 17:47:36 f0fe0150-44a9-4f1c-a7d7-ec8e4ce8d1dd POST undefined /auth
8 | 20211011 17:47:52 6b9200a7-d769-4464-a404-423b67b5cf0c DELETE undefined /employees
9 | 20211011 17:48:48 bcdb46f9-4364-4d9c-97f8-55795cd8c413 POST undefined /auth
10 | 20211011 17:49:03 d692da66-f505-444c-8fa6-5b87ef9972c3 DELETE undefined /employees
11 | 20211011 17:49:24 2b74f46b-65d3-4041-9c87-65e0982d46ad POST undefined /auth
12 | 20211011 17:49:38 32899fb9-23b8-49fc-95ac-631462d7174c POST undefined /employees
13 | 20211011 17:49:44 df0482cf-3962-4078-9a8e-b4712e1d8658 DELETE undefined /employees
14 |
--------------------------------------------------------------------------------
/controllers/refreshTokenController.js:
--------------------------------------------------------------------------------
1 | const usersDB = {
2 | users: require('../model/users.json'),
3 | setUsers: function (data) { this.users = data }
4 | }
5 | const jwt = require('jsonwebtoken');
6 |
7 | const handleRefreshToken = (req, res) => {
8 | const cookies = req.cookies;
9 | if (!cookies?.jwt) return res.sendStatus(401);
10 | const refreshToken = cookies.jwt;
11 |
12 | const foundUser = usersDB.users.find(person => person.refreshToken === refreshToken);
13 | if (!foundUser) return res.sendStatus(403); //Forbidden
14 | // evaluate jwt
15 | jwt.verify(
16 | refreshToken,
17 | process.env.REFRESH_TOKEN_SECRET,
18 | (err, decoded) => {
19 | if (err || foundUser.username !== decoded.username) return res.sendStatus(403);
20 | const roles = Object.values(foundUser.roles);
21 | const accessToken = jwt.sign(
22 | {
23 | "UserInfo": {
24 | "username": decoded.username,
25 | "roles": roles
26 | }
27 | },
28 | process.env.ACCESS_TOKEN_SECRET,
29 | { expiresIn: '30s' }
30 | );
31 | res.json({ accessToken })
32 | }
33 | );
34 | }
35 |
36 | module.exports = { handleRefreshToken }
--------------------------------------------------------------------------------
/controllers/logoutController.js:
--------------------------------------------------------------------------------
1 | const usersDB = {
2 | users: require('../model/users.json'),
3 | setUsers: function (data) { this.users = data }
4 | }
5 | const fsPromises = require('fs').promises;
6 | const path = require('path');
7 |
8 | const handleLogout = async (req, res) => {
9 | // On client, also delete the accessToken
10 |
11 | const cookies = req.cookies;
12 | if (!cookies?.jwt) return res.sendStatus(204); //No content
13 | const refreshToken = cookies.jwt;
14 |
15 | // Is refreshToken in db?
16 | const foundUser = usersDB.users.find(person => person.refreshToken === refreshToken);
17 | if (!foundUser) {
18 | res.clearCookie('jwt', { httpOnly: true, sameSite: 'None', secure: true });
19 | return res.sendStatus(204);
20 | }
21 |
22 | // Delete refreshToken in db
23 | const otherUsers = usersDB.users.filter(person => person.refreshToken !== foundUser.refreshToken);
24 | const currentUser = { ...foundUser, refreshToken: '' };
25 | usersDB.setUsers([...otherUsers, currentUser]);
26 | await fsPromises.writeFile(
27 | path.join(__dirname, '..', 'model', 'users.json'),
28 | JSON.stringify(usersDB.users)
29 | );
30 |
31 | res.clearCookie('jwt', { httpOnly: true, sameSite: 'None', secure: true });
32 | res.sendStatus(204);
33 | }
34 |
35 | module.exports = { handleLogout }
--------------------------------------------------------------------------------
/controllers/registerController.js:
--------------------------------------------------------------------------------
1 | const usersDB = {
2 | users: require('../model/users.json'),
3 | setUsers: function (data) { this.users = data }
4 | }
5 | const fsPromises = require('fs').promises;
6 | const path = require('path');
7 | const bcrypt = require('bcrypt');
8 |
9 | const handleNewUser = async (req, res) => {
10 | const { user, pwd } = req.body;
11 | if (!user || !pwd) return res.status(400).json({ 'message': 'Username and password are required.' });
12 | // check for duplicate usernames in the db
13 | const duplicate = usersDB.users.find(person => person.username === user);
14 | if (duplicate) return res.sendStatus(409); //Conflict
15 | try {
16 | //encrypt the password
17 | const hashedPwd = await bcrypt.hash(pwd, 10);
18 | //store the new user
19 | const newUser = {
20 | "username": user,
21 | "roles": { "User": 2001 },
22 | "password": hashedPwd
23 | };
24 | usersDB.setUsers([...usersDB.users, newUser]);
25 | await fsPromises.writeFile(
26 | path.join(__dirname, '..', 'model', 'users.json'),
27 | JSON.stringify(usersDB.users)
28 | );
29 | console.log(usersDB.users);
30 | res.status(201).json({ 'success': `New user ${user} created!` });
31 | } catch (err) {
32 | res.status(500).json({ 'message': err.message });
33 | }
34 | }
35 |
36 | module.exports = { handleNewUser };
--------------------------------------------------------------------------------
/controllers/authController.js:
--------------------------------------------------------------------------------
1 | const usersDB = {
2 | users: require('../model/users.json'),
3 | setUsers: function (data) { this.users = data }
4 | }
5 | const bcrypt = require('bcrypt');
6 |
7 | const jwt = require('jsonwebtoken');
8 | const fsPromises = require('fs').promises;
9 | const path = require('path');
10 |
11 | const handleLogin = async (req, res) => {
12 | const { user, pwd } = req.body;
13 | if (!user || !pwd) return res.status(400).json({ 'message': 'Username and password are required.' });
14 | const foundUser = usersDB.users.find(person => person.username === user);
15 | if (!foundUser) return res.sendStatus(401); //Unauthorized
16 | // evaluate password
17 | const match = await bcrypt.compare(pwd, foundUser.password);
18 | if (match) {
19 | const roles = Object.values(foundUser.roles);
20 | // create JWTs
21 | const accessToken = jwt.sign(
22 | {
23 | "UserInfo": {
24 | "username": foundUser.username,
25 | "roles": roles
26 | }
27 | },
28 | process.env.ACCESS_TOKEN_SECRET,
29 | { expiresIn: '30s' }
30 | );
31 | const refreshToken = jwt.sign(
32 | { "username": foundUser.username },
33 | process.env.REFRESH_TOKEN_SECRET,
34 | { expiresIn: '1d' }
35 | );
36 | // Saving refreshToken with current user
37 | const otherUsers = usersDB.users.filter(person => person.username !== foundUser.username);
38 | const currentUser = { ...foundUser, refreshToken };
39 | usersDB.setUsers([...otherUsers, currentUser]);
40 | await fsPromises.writeFile(
41 | path.join(__dirname, '..', 'model', 'users.json'),
42 | JSON.stringify(usersDB.users)
43 | );
44 | res.cookie('jwt', refreshToken, { httpOnly: true, sameSite: 'None', secure: true, maxAge: 24 * 60 * 60 * 1000 });
45 | res.json({ accessToken });
46 | } else {
47 | res.sendStatus(401);
48 | }
49 | }
50 |
51 | module.exports = { handleLogin };
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config();
2 | const express = require('express');
3 | const app = express();
4 | const path = require('path');
5 | const cors = require('cors');
6 | const corsOptions = require('./config/corsOptions');
7 | const { logger } = require('./middleware/logEvents');
8 | const errorHandler = require('./middleware/errorHandler');
9 | const verifyJWT = require('./middleware/verifyJWT');
10 | const cookieParser = require('cookie-parser');
11 | const credentials = require('./middleware/credentials');
12 | const mongoose = require('mongoose');
13 | const connectDB = require('./config/dbConn');
14 | const PORT = process.env.PORT || 3500;
15 |
16 | // Connect to MongoDB
17 | connectDB();
18 |
19 | // custom middleware logger
20 | app.use(logger);
21 |
22 | // Handle options credentials check - before CORS!
23 | // and fetch cookies credentials requirement
24 | app.use(credentials);
25 |
26 | // Cross Origin Resource Sharing
27 | app.use(cors(corsOptions));
28 |
29 | // built-in middleware to handle urlencoded form data
30 | app.use(express.urlencoded({ extended: false }));
31 |
32 | // built-in middleware for json
33 | app.use(express.json());
34 |
35 | //middleware for cookies
36 | app.use(cookieParser());
37 |
38 | //serve static files
39 | app.use('/', express.static(path.join(__dirname, '/public')));
40 |
41 | // routes
42 | app.use('/', require('./routes/root'));
43 | app.use('/register', require('./routes/register'));
44 | app.use('/auth', require('./routes/auth'));
45 | app.use('/refresh', require('./routes/refresh'));
46 | app.use('/logout', require('./routes/logout'));
47 |
48 | app.use(verifyJWT);
49 | app.use('/employees', require('./routes/api/employees'));
50 |
51 | app.all('*', (req, res) => {
52 | res.status(404);
53 | if (req.accepts('html')) {
54 | res.sendFile(path.join(__dirname, 'views', '404.html'));
55 | } else if (req.accepts('json')) {
56 | res.json({ "error": "404 Not Found" });
57 | } else {
58 | res.type('txt').send("404 Not Found");
59 | }
60 | });
61 |
62 | app.use(errorHandler);
63 |
64 | mongoose.connection.once('open', () => {
65 | console.log('Connected to MongoDB');
66 | app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
67 | });
--------------------------------------------------------------------------------
/controllers/employeesController.js:
--------------------------------------------------------------------------------
1 | const data = {
2 | employees: require('../model/employees.json'),
3 | setEmployees: function (data) { this.employees = data }
4 | }
5 |
6 | const getAllEmployees = (req, res) => {
7 | res.json(data.employees);
8 | }
9 |
10 | const createNewEmployee = (req, res) => {
11 | const newEmployee = {
12 | id: data.employees?.length ? data.employees[data.employees.length - 1].id + 1 : 1,
13 | firstname: req.body.firstname,
14 | lastname: req.body.lastname
15 | }
16 |
17 | if (!newEmployee.firstname || !newEmployee.lastname) {
18 | return res.status(400).json({ 'message': 'First and last names are required.' });
19 | }
20 |
21 | data.setEmployees([...data.employees, newEmployee]);
22 | res.status(201).json(data.employees);
23 | }
24 |
25 | const updateEmployee = (req, res) => {
26 | const employee = data.employees.find(emp => emp.id === parseInt(req.body.id));
27 | if (!employee) {
28 | return res.status(400).json({ "message": `Employee ID ${req.body.id} not found` });
29 | }
30 | if (req.body.firstname) employee.firstname = req.body.firstname;
31 | if (req.body.lastname) employee.lastname = req.body.lastname;
32 | const filteredArray = data.employees.filter(emp => emp.id !== parseInt(req.body.id));
33 | const unsortedArray = [...filteredArray, employee];
34 | data.setEmployees(unsortedArray.sort((a, b) => a.id > b.id ? 1 : a.id < b.id ? -1 : 0));
35 | res.json(data.employees);
36 | }
37 |
38 | const deleteEmployee = (req, res) => {
39 | const employee = data.employees.find(emp => emp.id === parseInt(req.body.id));
40 | if (!employee) {
41 | return res.status(400).json({ "message": `Employee ID ${req.body.id} not found` });
42 | }
43 | const filteredArray = data.employees.filter(emp => emp.id !== parseInt(req.body.id));
44 | data.setEmployees([...filteredArray]);
45 | res.json(data.employees);
46 | }
47 |
48 | const getEmployee = (req, res) => {
49 | const employee = data.employees.find(emp => emp.id === parseInt(req.params.id));
50 | if (!employee) {
51 | return res.status(400).json({ "message": `Employee ID ${req.params.id} not found` });
52 | }
53 | res.json(employee);
54 | }
55 |
56 | module.exports = {
57 | getAllEmployees,
58 | createNewEmployee,
59 | updateEmployee,
60 | deleteEmployee,
61 | getEmployee
62 | }
--------------------------------------------------------------------------------