<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<div class="container">
<div class="row">
<h2>Node js Express App with all feature in single file</h2>
</div>
</div>
const express = require('express');
const bcrypt = require('bcrypt');
const JWT = require('jsonwebtoken');
const mongoose = require('mongoose');
const multer = require('multer');
const cors = require('cors');
const path = require('path');
require('dotenv').config();
const redis = require('redis');
const { default: axios } = require('axios');
const app = express();
//Connect to redis
const client = redis.createClient({
url: process.env.REDIS_URL || 'redis://localhost:6379'
});
client.connect();
client.on('connect', () => {
console.log('Connected to Redis!!');
});
client.on('error', (err) => {
console.log('Redis error:', err);
});
// CORS Options (optional)
const corsOptions = {
origin: '*', // Change this to your frontend origin
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
credentials: true,
optionsSuccessStatus: 200
};
app.use(cors(corsOptions));
// Parse application/json
app.use(express.json());
// Ensure the environment variable is set correctly
console.log("MongoDB URL:", process.env.URL);
// Connection with MongoDB
const connectDb = async () => {
try {
await mongoose.connect(process.env.URL);
console.log("Connected to MongoDB!");
} catch (err) {
console.error("Failed to connect to MongoDB!");
}
};
connectDb();
// Response Handling
const successResponse = (res, code, data) => {
res.status(code).json({
success: true,
data
});
}
const errorResponse = (res, code, data) => {
res.status(code).json({
success: false,
data
});
}
// Authentication
const authenticateUser = async (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return errorResponse(res, 404, 'Token not found!!')
}
try {
let verifyToken = await JWT.verify(token, process.env.JWTSECRET);
if (verifyToken.Role === 'user') {
req.user = verifyToken;
next()
} else {
return errorResponse(res, 404, 'Unauthorized!!')
}
} catch (error) {
return errorResponse(res, 404, 'Unauthorized!!')
}
}
const authenticateAdmin = async (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return errorResponse(res, 404, 'Token not found!!')
}
try {
let verifyToken = await JWT.verify(token, process.env.JWTSECRET);
if (verifyToken.Role === 'admin') {
req.user = verifyToken;
next()
} else {
return errorResponse(res, 404, 'Unauthorized!!')
}
} catch (error) {
return errorResponse(res, 404, 'Unauthorized!!')
}
}
// Serve static files from the 'upload' directory
app.use('/uploads', express.static(path.join(__dirname, 'uploads')));
// Upload File using Multer
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, 'uploads')); // Path to 'upload' directory
},
filename: function (req, file, cb) {
const ext = path.extname(file.originalname);
cb(null, file.fieldname + '-' + Date.now() + ext);
}
});
const fileFilter = (req, file, cb) => {
// Check file type
if (file.mimetype === 'image/png' || file.mimetype === 'image/jpeg') {
cb(null, true); // Accept file
} else {
cb(new Error('Only .png and .jpeg formats are allowed!'), false); // Reject file
}
}
const upload = multer({
storage: storage,
fileFilter: fileFilter
});
//Create Error response
app.use((err, req, res, next) => {
if (err) {
return errorResponse(res, 400, err.message); // Handle Multer errors
}
next(); // If no error, pass to next middleware
});
// Create User Model
const UserSchema = mongoose.Schema({
name: { type: String, default: "User" },
email: { type: String, required: true },
password: { type: String, required: true },
role: { type: String, enum: ['user', 'admin'], default: 'user' },
image: { type: String, default: null },
});
const User = mongoose.model('users', UserSchema);
// Create User in Db
app.post('/register', async (req, res) => {
const { name, email, password, role } = req.body;
try {
if (!(role === 'admin' || role === 'user')) return errorResponse(res, 404, 'Incorrect Role!!');
let exists = await User.findOne({ email });
if (exists) {
return errorResponse(res, 404, 'Email already exists!!');
}
let hashPass = await bcrypt.hash(password, 10);
let createNewUser = new User({
name, email, password: hashPass, role
});
let saveuser = await createNewUser.save();
// Clear the cache to force refresh
await client.del('all_users');
return successResponse(res, 200, saveuser);
} catch (error) {
return errorResponse(res, 500, 'Internal server error');
}
});
//Get login by user and admin
app.post('/login', async (req, res) => {
const { email, password } = req.body;
let exists = await User.findOne({ email });
if (!exists) {
return errorResponse(res, 404, 'User not found!!');
}
let comparePass = await bcrypt.compare(password, exists.password);
if (!comparePass) {
return errorResponse(res, 404, 'Password not matched!!');
} else {
let token = await JWT.sign({ id: exists._id, Role: exists.role }, process.env.JWTSECRET, { expiresIn: '1hr' });
return successResponse(res, 200, { ...exists.toObject(), token });
}
});
//Get all users based on admin auth
app.get('/users', authenticateAdmin, async (req, res) => {
const cacheKey = 'all_users';
// Check if data is in Redis cache
const cachedData = await client.get(cacheKey);
if (cachedData) {
// If data exists in cache, return it
return successResponse(res, 200, JSON.parse(cachedData));
}
// If data is not cached, fetch it from MongoDB
let users = await User.find({});
if (!users) {
return errorResponse(res, 404, 'No users found!!');
}
// Cache the data in Redis and set an expiration time (e.g., 3600 seconds = 1 hour)
await client.set(cacheKey, JSON.stringify(users), { EX: 3600 }); // Cache expiration time
return successResponse(res, 200, users);
});
//Uploading File
app.post('/fileupload', upload.single('image'), async (req, res) => {
const { id } = req.body;
try {
if (!id) return errorResponse(res, 404, 'Id is Required!!');
let exists = await User.findOne({ _id: id });
if (!exists) {
return errorResponse(res, 404, 'No user found!!');
}
if (!req.file) return errorResponse(res, 400, 'No file uploaded!');
let saveResponse = await User.updateOne(
{ _id: exists._id },
{ $set: { image: `http://localhost:${PORT}/uploads/${req.file.filename}` } }, // Save the URL
{ upsert: true }
);
return successResponse(res, 200, { ...saveResponse, message: 'File uploaded successfully' });
} catch (error) {
console.error('Error:', error);
return errorResponse(res, 500, 'Internal Server Error!!');
}
});
//Get all users based on admin auth
app.get('/testing', async (req, res) => {
const cacheKey = 'testing';
// // Check if data is in Redis cache
const cachedData = await client.get(cacheKey);
if (cachedData) {
// If data exists in cache, return it
return successResponse(res, 200, JSON.parse(cachedData));
}
let dummyData = await axios.get('https://dummyjson.com/products');
if (!dummyData) {
return errorResponse(res, 404, 'No users found!!');
}
// Cache the data in Redis and set an expiration time (e.g., 3600 seconds = 1 hour)
await client.set(cacheKey, JSON.stringify(dummyData.data.products), { EX: 3600 }); // Cache expiration time
return successResponse(res, 200, dummyData.data.products);
});
//For Testing Purpose | Project is Running on Browser or Not
app.get('/', (req, res) => {
res.write('Project is running smoothly!!');
res.end();
});
// Server Listen On Port
const PORT = process.env.PORT || 4400;
app.listen(PORT, () => {
console.log(`Project is running on http://localhost:${PORT}`);
});