This tutorial will walk you through building a simple user management API that fetches data from a file as opposed to a database. With this API, you will be able to list all users, list one user, log in, Signup and Delete a user.
We are going to use node.js to build our server and bcryptjs to hash the passwords. This will be expanded in future to include a database.
What will be covered:
- Setting Up the project
- Creating the file structure
- Setting up environment Variables Optional
- Creating the User Data Module
- Creating the Express Application
- Creating the Controllers
- Creating the Routes
- Mounting the Routes in the Application
- Testing the Endpoints using Postman
Setting Up the Project
- Create a new directory for your project and navigate to it using the command line.
- Initialize a new Node.js project by running
npm init
and following the prompts. You can also usenpm init -y
to skip the prompts. - Install the necessary dependencies by running the following command:
npm install express dotenv bcryptjs
- Express is a web application framework that helps manage servers and routes.
- Dotenv is a library that loads environment variables from a .env file into process.env.
- Bcryptjs Is a library that helps one hash passwords.
At this point, you should have two files(package.json
and package-lock.json
) and the node_modules
folder.
The package.json should have the three dependencies installed in step 3.
Creating the file structure
- Create a file called
server.js
as the entry point of your application. - Create a directory called
controllers
to store your route handlers. - Create a directory called
routes
to store your routes. - Create a file called
.env
to store your environment variables. (Optional) - Create a file called
users.js
to serve as the user data module.
Setting up environment Variables Optional
- Open the
.env
file and define the necessary environment variables. For this project, we'll need the following variables:PORT=4000
- In the
server.js
file, require the dotenv package at the top:
require('dotenv').config();
- Use
process.env
to access the environment variables throughout your application. For example, you can useprocess.env.PORT
to retrieve the port number.
Creating the User Data Module
- In the users.js file, define an array variable to store the user data. Each user should have properties such as id, name, email, and password.
- Export the usersData array using module.exports so that it can be imported and used in other files.
const bcrypt = require('bcryptjs');
const usersData = [
{
id: 1,
name: "John Doe",
email: "john@example.com",
password: bcrypt.hashSync("password123", 10)
},
{
id: 2,
name: "Jane Smith",
email: "jane@example.com",
password: bcrypt.hashSync("secret456", 10)
},
{
id: 3,
name: "Alice Johnson",
email: "alice@example.com",
password: bcrypt.hashSync("qwerty789", 10)
},
{
id: 4,
name: "Bob Williams",
email: "bob@example.com",
password: bcrypt.hashSync("pass1234", 10)
},
{
id: 5,
name: "Sarah Davis",
email: "sarah@example.com",
password: bcrypt.hashSync("password567", 10)
}
];
module.exports = usersData;
Creating the Express Application
- In the
server.js
file, require the necessary packages:
const express = require('express');
const usersRouter = require('./routes/usersRoutes');
- Create an instance of the Express application:
const app = express();
- Set up middleware to parse JSON request bodies:
app.use(express.json());
server.js
require('dotenv').config();
const express = require('express');
const usersRouter = require('./routes/usersRoutes');
const app = express();
app.use(express.json());
app.use('/users', usersRouter);
const port = process.env.PORT || 4000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Creating the Controllers
- In the controllers directory, create a file called
usersController.js
to define the user-related controllers. - Import the usersData module in your controller file using the require
const usersData = require('../users');
- Define the controller functions for each endpoint. #### usersController.js
const usersData = require('../users');
const bcrypt = require('bcryptjs');
// Display all users
const getAllUsers = (req, res) => {
const hashedUsers = usersData.map(user => ({
...user,
password: bcrypt.hashSync(user.password, 10)
}));
res.json(hashedUsers);
};
// Display one user by ID
const getUserById = (req, res) => {
const { id } = req.params;
const user = usersData.find(user => user.id === parseInt(id));
if (user) {
const hashedUser = { ...user, password: bcrypt.hashSync(user.password, 10) };
res.json(hashedUser);
} else {
res.status(404).json({ message: 'User not found' });
}
};
// Login
const login = (req, res) => {
const { email, password } = req.body;
const user = usersData.find(user => user.email === email);
if (user && bcrypt.compareSync(password, user.password)) {
res.json({ message: 'Login successful' });
} else {
res.status(401).json({ message: 'Invalid credentials' });
}
};
// Signup
const signup = (req, res) => {
const { name, email, password } = req.body;
const id = usersData.length + 1;
const newUser = { id, name, email, password };
usersData.push(newUser);
res.status(201).json({ message: 'Signup successful' });
};
// Delete user by email
const deleteUserByEmail = (req, res) => {
const { email } = req.params;
const index = usersData.findIndex(user => user.email === email);
if (index !== -1) {
usersData.splice(index, 1);
res.json({ message: 'User deleted successfully' });
} else {
res.status(404).json({ message: 'User not found' });
}
};
module.exports = {
getAllUsers,
getUserById,
login,
signup,
deleteUserByEmail
};
Creating the Routes
- In the routes directory, create a file called
usersRoutes.js
to define the user-related routes. - In the
usersRoutes.js
file, require the necessary packages.
const express = require('express');
const router = express.Router();
const usersController = require('../controllers/usersController');
- Define the route handlers for each endpoint.
// Display all users
router.get('/', usersController.getAllUsers);
// Display one user by ID
router.get('/:id', usersController.getUserById);
// Login
router.post('/login', usersController.login);
// Signup
router.post('/signup', usersController.signup);
// Delete user by email
router.delete('/:email', usersController.deleteUserByEmail);
- Export the router from the file.
module.exports = router;
usersRoutes.js
const express = require('express');
const router = express.Router();
const usersController = require('../controllers/usersController');
// Display all users
router.get('/', usersController.getAllUsers);
// Display one user by ID
router.get('/:id', usersController.getUserById);
// Login
router.post('/login', usersController.login);
// Signup
router.post('/signup', usersController.signup);
// Delete user by email
router.delete('/:email', usersController.deleteUserByEmail);
module.exports = router;
Mounting the Routes in the Application
- In the
server.js
file, mount the usersRouter to a base path.
app.use('/users', usersRouter);
-
Start the server and listen for incoming requests.
const port = process.env.PORT || 4000; app.listen(port, () => { console.log(`Server is running on port ${port}`); });
Testing the Endpoints using Postman
Let’s test the endpoints in Postman and verify that everything is working as intended.
Start the server by running node server.js
or nodemon server.js
-
Display all users: Send a GET request to
http://localhost:4000/users
. This endpoint will return an array of all users, with hashed passwords.
-
Display one user by ID: Send a GET request to
http://localhost:4000/users/1
to retrieve the user with ID 1. This endpoint will return the user object with a hashed password. Replace 1 with the desired user ID.
-
Login: Send a POST request to
http://localhost:3000/users/login
with the following request body in JSON format:
{
"email": "jane@example.com",
"password": "secret456"
}
-
Signup: Send a POST request to
http://localhost:4000/users/signup
with the following request body in JSON format:
{
"name": "Jane Smith",
"email": "jane@example.com",
"password": "secret456"
}
Replace the values with the desired name, email, and password. If the signup is successful, the response will contain the message Signup successful.
-
Delete a user by email: Send a DELETE request to
http://localhost:4000/users/bob@example.com
to delete the user with the email bob@example.com. Replace the email address with that of the user you want to delete. If the user exists, the response will contain the message User deleted successfully.
Congratulations! You have created and tested a user management API using Node.js, Express and Postman. The API will hash passwords and provide the specified endpoints for user management.