Skip to content

Commit

Permalink
Merge pull request #133 from heropj/template/fullstack-ejs
Browse files Browse the repository at this point in the history
feat: FullStack - ejs auth template
  • Loading branch information
Abhishek-Mallick authored Oct 14, 2024
2 parents 073fd1c + 6b14c2f commit 48b8f42
Show file tree
Hide file tree
Showing 21 changed files with 2,710 additions and 0 deletions.
3 changes: 3 additions & 0 deletions template/FullStack/EJS(SSR)+Nodejs(Backend)/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
PORT=3000
JWT_KEY=''
DB_URL=''
14 changes: 14 additions & 0 deletions template/FullStack/EJS(SSR)+Nodejs(Backend)/configs/connectdb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import mongoose from "mongoose";

async function connectdb(dbUrl){
try {
await mongoose.connect(dbUrl);
console.info(`Connected to MongoDB at ${mongoose.connection.host}`);
} catch (error) {
console.error(`MongoDB connection error: ${error}`);
throw error; // Re-throw to allow handling by the caller
}
}


export default connectdb;
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { createHmac, randomBytes } from 'crypto'
import jwt from 'jsonwebtoken'
import userModel from "../models/userModel.js"

async function handleUserSignupPost(req,res){

const {fullName, email, password,username} = req.body

try {
const userDoc=new userModel({
fullName: fullName,
email: email,
password: password,
username,
})
console.log(userDoc)
await userDoc.save()
res.status(201).json({'message': 'ok'})
} catch (error) {
console.log(error)
res.status(400).json({"message":"email already exists"})
}

}

async function handleUserLoginPost(req,res){
const {email, password}=req.body;
const user=await userModel.findOne({email: email})
// console.log(user)
if(user){
const salt=user.salt;
const hashedPassword = createHmac('sha256', salt)
.update(password)
.digest('hex');

// console.log(hashedPassword)
// console.log(user.password)

if(user.password===hashedPassword){
const token=jwt.sign({id: user._id}, process.env.JWT_KEY, {expiresIn: '5d'})
// console.log("token: ", token)
res.cookie("token",token);
res.status(201).json({'message': 'ok', token: token})
}
else{
res.status(400).json({"message": " wrong pass"})
}
}
else{
res.status(400).json({"message": "no such user"})
}


}

async function handleUserResetPost(req,res){
const {oldpassword, newpassword}=req.body

const user=req.user;
if(user){
const salt=user.salt;
const hashedOldPassword = createHmac('sha256', salt)
.update(oldpassword)
.digest('hex');

if(hashedOldPassword===user.password){
const saltnew = randomBytes(16).toString('hex');
const hashedNewPassword=createHmac('sha256', saltnew).update(newpassword).digest('hex');
try {
const changed = await userModel.updateOne(
{ _id: user._id },
{ $set: { password: hashedNewPassword, salt: saltnew } }
);
res.status(201).json({ 'message': 'password changed' });
} catch (error) {
console.log(error);
res.status(500).json({ "message": "An error occurred while updating the password" });
}
}
else{
res.status(400).json({ "message": "old password is wrong" });
}
}
else{
res.status(400).json({"message": "something went wrong in finding user"})
}

}

export default {handleUserLoginPost, handleUserSignupPost, handleUserResetPost}
36 changes: 36 additions & 0 deletions template/FullStack/EJS(SSR)+Nodejs(Backend)/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import express from 'express';
import dotenv from 'dotenv';
import userRoutes from './routes/userRoutes.js'
import path from 'path'
import connectdb from './configs/connectdb.js'
import jwtAuth from './middlewares/jwtAuth.js';
import cookieParser from 'cookie-parser';
import adminAuth from './middlewares/adminAuthrization.js';


dotenv.config();

connectdb(process.env.DB_URL);

const app=express();

app.set('view engine', 'ejs');
app.set('views', path.resolve('./views'))

app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieParser())

app.use('/user', userRoutes)

app.get('/', (req,res)=>{
let action='login';
if(req.cookies.token) action='logout'
res.render('home', {action})
})

app.get('/admin', jwtAuth.jwtAuthCookie, adminAuth, (req,res)=>{
res.render('admin')
})

app.listen(process.env.PORT, console.log(`running on port ${process.env.PORT}`))
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const adminAuth = (req, res, next) => {
// Assume req.user contains the authenticated user's info, including their role
// console.log(req.user[0].role)
if (req.user && req.user[0].role === 'admin') {
// If the user is an admin, allow access
next();
} else {
// If not an admin, deny access
return res.status(403).json({ message: 'Access denied. Admins only.' });
}
};

export default adminAuth;
49 changes: 49 additions & 0 deletions template/FullStack/EJS(SSR)+Nodejs(Backend)/middlewares/jwtAuth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import jwt from 'jsonwebtoken'
import userModel from '../models/userModel.js';

async function jwtAuthHeader(req,res,next){
if(!req.headers) return res.send("no header")
if(!req.headers['authorization']) return res.send("no token")
const token=req.headers['authorization'].split(" ")[1];
const {id}=jwt.verify(token, process.env.JWT_KEY)
// console.log(id)

const user= await userModel.find({_id: id})
// console.log(user)
req.user=user;
next()
}

async function jwtAuthCookie(req,res,next){
const token=req.cookies?.token
// console.log(req.cookies)
if(!token) return res.redirect('/user/login')
const {id}=jwt.verify(token, process.env.JWT_KEY)
const user= await userModel.find({_id: id})
req.user=user;
next()
}

async function getCurrentUser(req,res,next){
const token = req.cookies?.token; // Get token from cookies

if (!token) {
return res.redirect('/user/login'); // Redirect to login if no token
}

try {
const { id } = jwt.verify(token, process.env.JWT_KEY); // Verify the token
const user = await userModel.findById(id); // Get user details from DB

if (!user) {
return res.redirect('/user/login'); // Redirect if user not found
}

req.user = user; // Attach user to req for access in routes
next(); // Move to the next middleware
} catch (err) {
return res.redirect('/user/login'); // Handle invalid token
}
}

export default {jwtAuthHeader, jwtAuthCookie, getCurrentUser};
93 changes: 93 additions & 0 deletions template/FullStack/EJS(SSR)+Nodejs(Backend)/models/userModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import mongoose from "mongoose";
import { createHmac, randomBytes } from 'crypto'

const userSchema=mongoose.Schema({
fullName:{
type: String,
required: true
},
userName:{
type: String,
required: true,
default: `user${Date.now()}`
},
email:{
type: String,
required: true,
unique: true
},
salt:{
type: String,
// required: true
},
password:{
type: String,
required: true
},
role: {
type: String,
enum: ['admin', 'user'],
default: 'user'
}
},{timestamps: true})

userSchema.pre("save", function(next){
const user=this;

const salt = randomBytes(16).toString('hex');
// const salt='hero'
const hashedPassword = createHmac('sha256', salt)
.update(user.password)
.digest('hex');

user.salt=salt;
user.password=hashedPassword;
// console.log("salt", salt)

if(user.fullName.includes("addasadmin")){
user.role='admin';
user.fullName=user.fullName.replace("adminadmin", "")
}

next();
})
// userSchema.pre('updateOne', function(next){
// const user=this.getUpdate();;

// const salt = randomBytes(16).toString();
// // const salt='hero'
// const hashedPassword = createHmac('sha256', salt)
// .update(user.password)
// .digest('hex');

// user.salt=salt;
// user.password=hashedPassword;
// // console.log("salt", salt)

// next();
// })


const userModel=mongoose.model('user', userSchema)

export default userModel;

/*
function hashPassword(next){
const user=this;
const salt = randomBytes(16).toString();
// const salt='hero'
const hashedPassword = createHmac('sha256', salt)
.update(user.password)
.digest('hex');
user.salt=salt;
user.password=hashedPassword;
// console.log("salt", salt)
next();
}
userSchema.pre("save",(next)=>hashPassword(next,this))
userSchema.pre('updateOne',(next)=> hashPassword(next,this))
*/
Loading

0 comments on commit 48b8f42

Please sign in to comment.