Skip to content

Commit

Permalink
Merge pull request #127 from rishabh7923/v2
Browse files Browse the repository at this point in the history
Authentication for Regular User's
  • Loading branch information
sudo-dpkg authored Nov 9, 2024
2 parents a7a09c2 + deaae37 commit 1b6120f
Show file tree
Hide file tree
Showing 12 changed files with 261 additions and 254 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ npm install

Create a `.env` file in the root directory and add the following line:
```bash
ADMIN_USERNAME=username of admins seprarated by ","

MONGODB_URI=mongodb://localhost:27017/bloglog
EMAIL_USERNAME=
EMAIL_APP_PASSWORD=
Expand Down
12 changes: 12 additions & 0 deletions server/middlewares/admin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = (req, res, next) => {
try {
if (req.user.admin) {
next();
} else {
res.status(403).json({ message: 'Forbidden' });
}
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Internal Server Error' });
}
}
19 changes: 19 additions & 0 deletions server/middlewares/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const jwt = require('jsonwebtoken');
const jwtSecret = process.env.JWT_SECRET;


module.exports = (req, res, next) => {
const token = req.cookies.user.token;

if (!token) {
return res.status(401).json({ message: 'Unauthorized' });
}

try {
const decoded = jwt.verify(token, jwtSecret);
req.user = { id: decoded.id, username: decoded.username, admin: decoded.admin };
next();
} catch (error) {
res.status(401).json({ message: 'Unauthorized' });
}
}
File renamed without changes.
5 changes: 5 additions & 0 deletions server/middlewares/restrictAuthRoute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = (req, res, next) => {
const token = req.cookies.token;
if (!token) return next();
return res.status(200).redirect('/')
}
180 changes: 14 additions & 166 deletions server/routes/admin.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
const express = require('express');
const router = express.Router();
const Post = require('../models/Post');
const User = require('../models/User');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const passport = require('passport'); // Added passport import
const { validateRegistration, validatePost } = require('../validations/authValidator');

const { validatePost } = require('../middlewares/authValidator');
const { CloudinaryStorage } = require('multer-storage-cloudinary');


const adminLayout = '../views/layouts/admin';
const jwtSecret = process.env.JWT_SECRET;
const multer = require('multer');
const cloudinary = require('cloudinary').v2;
const { CloudinaryStorage } = require('multer-storage-cloudinary');

const authMiddleware = require('../middlewares/auth');
const adminMiddleware = require('../middlewares/admin');

cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
Expand All @@ -35,37 +34,6 @@ const storage = new CloudinaryStorage({
const upload = multer({ storage });


/**
* Check whether the user is signed in or not
* and makes the /admin route available only those users who are NOT logged
*/

const restrictAuthRouteMiddleware = (req, res, next) => {
const token = req.cookies.token;
if (!token) return next();
return res.status(200).redirect('/')
}


/**
* Authentication Middleware
*/
const authMiddleware = (req, res, next) => {
const token = req.cookies.token;

if (!token) {
return res.status(401).json({ message: 'Unauthorized' });
}

try {
const decoded = jwt.verify(token, jwtSecret);
req.userId = decoded.userId;
next();
} catch (error) {
res.status(401).json({ message: 'Unauthorized' });
}
};

/**
* GET /
* Admin - Login Page
Expand All @@ -76,49 +44,12 @@ router.use((req, res, next) => {
next(); // Call the next middleware or route handler
});

router.get('/admin', restrictAuthRouteMiddleware, async (req, res) => {
try {
const locals = {
title: 'Admin',
description: 'Simple Blog created with NodeJs, Express & MongoDb.',
};

res.render('admin/index', { locals, layout: adminLayout });
} catch (error) {
console.log(error);
}
});

/**
* POST /admin
* Admin Login Route with Passport Authentication
*/
router.post('/admin', async (req, res, next) => {
passport.authenticate('local', async (err, user, info) => {
if (err) {
return res.status(500).json({ message: 'Internal server error' });
}
if (!user) {
return res.status(401).json({ message: 'Unauthorized' });
}
req.logIn(user, async (err) => {
if (err) {
return res.status(500).json({ message: 'Error logging in' });
}

const token = jwt.sign({ userId: user._id }, jwtSecret, { expiresIn: '1h' });
res.cookie('token', token, { httpOnly: true });
return res.redirect('/dashboard'); // Now redirect to dashboard
});
})(req, res, next);
});


/**
* GET /dashboard
* Admin Dashboard Route
*/
router.get('/dashboard', authMiddleware, async (req, res) => {
router.get('/dashboard', authMiddleware, adminMiddleware, async (req, res) => {
const locals = {
title: 'Dashboard',
user: req.cookies.token,
Expand All @@ -127,16 +58,17 @@ router.get('/dashboard', authMiddleware, async (req, res) => {

const posts = await Post.find(); // Fetch all posts

res.render('admin/dashboard', { locals, posts }); // Pass 'posts' to the template
res.render('admin/dashboard', { locals, posts });
});


/**
* GET /add-post
* Admin Add Post Route
*/
router.get('/add-post', authMiddleware, async (req, res) => {
router.get('/add-post', authMiddleware, adminMiddleware, async (req, res) => {
const token = req.cookies.token;

try {
const locals = {
title: 'Add Post',
Expand All @@ -154,7 +86,7 @@ router.get('/add-post', authMiddleware, async (req, res) => {
* POST /add-post
* Admin Create New Post Route
*/
router.post('/add-post', upload.single('poster'), authMiddleware, validatePost, async (req, res) => {
router.post('/add-post', upload.single('poster'), authMiddleware, adminMiddleware, validatePost, async (req, res) => {
try {
const token = req.cookies.token

Expand All @@ -177,7 +109,7 @@ router.post('/add-post', upload.single('poster'), authMiddleware, validatePost,
* GET /edit-post/:id
* Admin Edit Post Route
*/
router.get('/edit-post/:id', authMiddleware, async (req, res) => {
router.get('/edit-post/:id', authMiddleware, adminMiddleware, async (req, res) => {
try {
const locals = {
title: 'Edit Post',
Expand All @@ -197,7 +129,7 @@ router.get('/edit-post/:id', authMiddleware, async (req, res) => {
* PUT /edit-post/:id
* Admin Update Post Route
*/
router.put('/edit-post/:id', upload.single('poster'), authMiddleware, validatePost, async (req, res) => {
router.put('/edit-post/:id', upload.single('poster'), authMiddleware, adminMiddleware, validatePost, async (req, res) => {
try {
await Post.findByIdAndUpdate(req.params.id, {
title: req.body.title,
Expand All @@ -217,7 +149,7 @@ router.put('/edit-post/:id', upload.single('poster'), authMiddleware, validatePo
* DELETE /delete-post/:id
* Admin Delete Post Route
*/
router.delete('/delete-post/:id', authMiddleware, async (req, res) => {
router.delete('/delete-post/:id', authMiddleware, adminMiddleware, async (req, res) => {
try {
await Post.deleteOne({ _id: req.params.id });
res.redirect('/dashboard');
Expand All @@ -226,89 +158,5 @@ router.delete('/delete-post/:id', authMiddleware, async (req, res) => {
}
});

/**
* POST /register
* Admin Registration Route
*/

/**
* GET /register
* Admin - Registration Page
*/
// Example of admin.js route handling
router.get('/register',restrictAuthRouteMiddleware, (req, res) => {
// Initialize messages object, you can adjust it according to your error handling logic
const locals = {
title: 'Admin',
description: 'Simple Blog created with NodeJs, Express & MongoDb.',
};

res.render('admin/register', { locals, layout: adminLayout }); // Pass messages to the template
});



router.post('/register',validateRegistration, async (req, res) => {
const { username, password } = req.body;

// Simple validation
if (!username || !password) {
req.flash('error', 'All fields are required');
return res.redirect('/register'); // Change to '/register'
}

if (!/^[a-zA-Z0-9]+$/.test(username) || username.length < 3) {
req.flash('error', 'Username must be at least 3 characters long and contain only alphanumeric characters.');
return res.redirect('/register');
}

if (password.length < 8 || !/\d/.test(password) || !/[!@#$%^&*]/.test(password)) {
req.flash('error', 'Password must be at least 8 characters long, contain a number, and a special character.');
return res.redirect('/register');
}

try {
const existingUser = await User.findOne({ username });

if (existingUser) {
req.flash('error', 'Username already taken');
return res.redirect('/register'); // Change to '/register'
}

// Hash password and create new user
const hashedPassword = await bcrypt.hash(password, 10);
const user = new User({ username, password: hashedPassword });
await user.save();

// Automatically log the user in
req.login(user, (err) => {
if (err) return res.status(500).json({ message: 'Error logging in after registration' });

const token = jwt.sign({ userId: user._id }, jwtSecret, { expiresIn: '1h' });
res.cookie('token', token, { httpOnly: true });

return res.redirect('/dashboard');
});
} catch (error) {
console.log(error);
res.status(500).json({ message: 'Internal server error' });
}
});


/**
* GET /logout
* Admin Logout Route
*/
router.get('/logout', (req, res) => {

req.logout((err) => {
if (err) {
return next(err);
}
res.clearCookie('token');
res.redirect('/');
});
});

module.exports = router;
Loading

0 comments on commit 1b6120f

Please sign in to comment.