-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #133 from heropj/template/fullstack-ejs
feat: FullStack - ejs auth template
- Loading branch information
Showing
21 changed files
with
2,710 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
14
template/FullStack/EJS(SSR)+Nodejs(Backend)/configs/connectdb.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
90 changes: 90 additions & 0 deletions
90
template/FullStack/EJS(SSR)+Nodejs(Backend)/controllers/userController.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}`)) |
13 changes: 13 additions & 0 deletions
13
template/FullStack/EJS(SSR)+Nodejs(Backend)/middlewares/adminAuthrization.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
49
template/FullStack/EJS(SSR)+Nodejs(Backend)/middlewares/jwtAuth.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
93
template/FullStack/EJS(SSR)+Nodejs(Backend)/models/userModel.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | ||
*/ |
Oops, something went wrong.