JWT-bcrypt-learning
This commit is contained in:
parent
d23fa693ea
commit
e1a60bdccd
27
app.js
27
app.js
|
@ -2,34 +2,23 @@ require("dotenv").config();
|
|||
const express = require("express");
|
||||
const connectDB= require("./config/db");
|
||||
const userRoutes= require("./routes/userRoutes");
|
||||
const authRoutes = require("./routes/authRoutes");
|
||||
const logger = require('./middleware/logger')
|
||||
const app= express();
|
||||
const PORT = process.env.PORT || 5000;
|
||||
//DB connection:Done
|
||||
connectDB();
|
||||
|
||||
//use in built-middleware to parse the data form body
|
||||
app.use(express.urlencoded({ extended: false }))
|
||||
//parse the json data
|
||||
app.use(express.json());
|
||||
//parse the url-encoded data
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(logger);
|
||||
//Routes
|
||||
app.use("/api/users",userRoutes);
|
||||
|
||||
|
||||
app.use("/api/user", authRoutes);
|
||||
app.listen(PORT,()=>{
|
||||
console.log(`Server is running on port ${PORT}`);
|
||||
})
|
||||
|
||||
|
||||
// const logger = require("./middleware/logger");
|
||||
// const userRoutes = require("./routes/userRoutes");
|
||||
|
||||
// const app = express();
|
||||
// const PORT = process.env.PORT || 5000;
|
||||
|
||||
// connectDB();
|
||||
|
||||
// app.use(express.json());
|
||||
// app.use(logger); // custom middleware
|
||||
// app.use("/api/users", userRoutes);
|
||||
|
||||
// app.listen(PORT, () => {
|
||||
// console.log(`Server is running on port ${PORT}`);
|
||||
// });
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const mongoose = require("mongoose");
|
||||
|
||||
const connectDB = async()=>{
|
||||
try{
|
||||
await mongoose.connect(process.env.MONGO_URI);
|
||||
|
@ -9,4 +10,7 @@ const connectDB = async()=>{
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = connectDB;
|
||||
module.exports = connectDB;
|
||||
|
||||
|
||||
|
||||
|
|
58
controllers/authController.js
Normal file
58
controllers/authController.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
const User = require("../models/User");
|
||||
const jwt = require("jsonwebtoken");
|
||||
|
||||
const generateToken = (id) => {
|
||||
return jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: "1h" });
|
||||
};
|
||||
|
||||
//Register
|
||||
const registerUser = async (req, res) => {
|
||||
const { username, email, password } = req.body;
|
||||
|
||||
try {
|
||||
const userExists = await User.findOne({ email });
|
||||
if (userExists)
|
||||
return res.status(400).json({ message: "User already exists" });
|
||||
|
||||
const user = await User.create({ username, email, password });
|
||||
|
||||
res.status(201).json({
|
||||
_id: user._id,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
token: generateToken(user._id),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error in registerUser:", error.message);
|
||||
res.status(500).json({ message: "Server error" });
|
||||
}
|
||||
|
||||
};
|
||||
//Login
|
||||
const loginUser = async (req, res) => {
|
||||
const { email, password } = req.body;
|
||||
|
||||
try {
|
||||
const user = await User.findOne({ email });
|
||||
if (!user) return res.status(400).json({ message: "Invalid credentials" });
|
||||
|
||||
const isMatch = await user.matchPassword(password);
|
||||
if (!isMatch)
|
||||
return res.status(400).json({ message: "Invalid credentials" });
|
||||
|
||||
res.status(200).json({
|
||||
_id: user._id,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
token: generateToken(user._id),
|
||||
message: "success",
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: "Server error" });
|
||||
}
|
||||
};
|
||||
const getProfile = async (req, res) => {
|
||||
res.json(req.user);
|
||||
};
|
||||
|
||||
module.exports = { registerUser, loginUser, getProfile };
|
|
@ -52,6 +52,7 @@ const deleteUser= async(req,res)=>{
|
|||
if(!user){
|
||||
return res.status(404).json({message: "User not found"});
|
||||
}
|
||||
res.status(200).json({message:"success"})
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
}
|
||||
|
|
24
middleware/authMiddleware.js
Normal file
24
middleware/authMiddleware.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
const jwt = require("jsonwebtoken");
|
||||
const User = require("../models/User");
|
||||
|
||||
const authToken = async (req, res, next) => {
|
||||
let token;
|
||||
if (
|
||||
req.headers.authorization &&
|
||||
req.headers.authorization.startsWith("Bearer")
|
||||
) {
|
||||
try {
|
||||
token = req.headers.authorization.split(" ")[1]; // Correct split by space
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
||||
req.user = await User.findById(decoded.id).select("-password");
|
||||
next();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(401).json({ message: "Not authorized, token failed" });
|
||||
}
|
||||
} else {
|
||||
res.status(401).json({ message: "Not authorized, no token" });
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = authToken;
|
6
middleware/logger.js
Normal file
6
middleware/logger.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
// logger.js
|
||||
function logger(req, res, next) {
|
||||
console.log(`${req.method} ${req.url} at ${new Date().toISOString()}`);
|
||||
next();
|
||||
}
|
||||
module.exports = logger;
|
|
@ -1,19 +1,41 @@
|
|||
const mongoose = require("mongoose");
|
||||
const bcrypt = require("bcrypt");
|
||||
const userSchema = new mongoose.Schema({
|
||||
first_name:{
|
||||
type:String,
|
||||
required:true
|
||||
},
|
||||
last_name:{
|
||||
type:String,
|
||||
},
|
||||
email:{
|
||||
type:String,
|
||||
required:true,
|
||||
unique:true
|
||||
},
|
||||
age:{
|
||||
type:Number
|
||||
}
|
||||
})
|
||||
module.exports = mongoose.model("User",userSchema);
|
||||
first_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
last_name: {
|
||||
type: String,
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
age: {
|
||||
type: Number,
|
||||
},
|
||||
username: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
userSchema.pre("save", async function (next) {
|
||||
if (!this.isModified("password")) return next();
|
||||
|
||||
const salt = await bcrypt.genSalt(10);
|
||||
this.password = await bcrypt.hash(this.password, salt);
|
||||
next();
|
||||
});
|
||||
|
||||
userSchema.methods.matchPassword = async function (enteredPassword) {
|
||||
return await bcrypt.compare(enteredPassword, this.password);
|
||||
};
|
||||
module.exports = mongoose.model("User", userSchema);
|
||||
|
|
4
nodemon.json
Normal file
4
nodemon.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"watch": ["."],
|
||||
"legacyWatch": true
|
||||
}
|
136
package-lock.json
generated
136
package-lock.json
generated
|
@ -9,8 +9,10 @@
|
|||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bcrypt": "^6.0.0",
|
||||
"dotenv": "^16.5.0",
|
||||
"express": "^5.1.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"mongodb": "^6.16.0",
|
||||
"mongoose": "^8.15.1",
|
||||
"nodemon": "^3.1.10"
|
||||
|
@ -72,6 +74,20 @@
|
|||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bcrypt": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
|
||||
"integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"node-addon-api": "^8.3.0",
|
||||
"node-gyp-build": "^4.8.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||
|
@ -135,6 +151,12 @@
|
|||
"node": ">=16.20.1"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-equal-constant-time": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
|
@ -293,6 +315,15 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
|
@ -655,6 +686,49 @@
|
|||
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jsonwebtoken": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
|
||||
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jws": "^3.2.2",
|
||||
"lodash.includes": "^4.3.0",
|
||||
"lodash.isboolean": "^3.0.3",
|
||||
"lodash.isinteger": "^4.0.4",
|
||||
"lodash.isnumber": "^3.0.3",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"lodash.isstring": "^4.0.1",
|
||||
"lodash.once": "^4.0.0",
|
||||
"ms": "^2.1.1",
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12",
|
||||
"npm": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jwa": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
|
||||
"integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-equal-constant-time": "^1.0.1",
|
||||
"ecdsa-sig-formatter": "1.0.11",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/jws": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
|
||||
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jwa": "^1.4.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/kareem": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz",
|
||||
|
@ -664,6 +738,48 @@
|
|||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.includes": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isboolean": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
|
||||
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isinteger": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
|
||||
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isnumber": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
|
||||
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isplainobject": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isstring": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
|
||||
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.once": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
||||
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
|
@ -845,6 +961,26 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "8.3.1",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz",
|
||||
"integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^18 || ^20 || >= 21"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp-build": {
|
||||
"version": "4.8.4",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
|
||||
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"node-gyp-build": "bin.js",
|
||||
"node-gyp-build-optional": "optional.js",
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/nodemon": {
|
||||
"version": "3.1.10",
|
||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz",
|
||||
|
|
|
@ -11,10 +11,14 @@
|
|||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"bcrypt": "^6.0.0",
|
||||
"dotenv": "^16.5.0",
|
||||
"express": "^5.1.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"mongodb": "^6.16.0",
|
||||
"mongoose": "^8.15.1",
|
||||
"nodemon": "^3.1.10"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
21
routes/authRoutes.js
Normal file
21
routes/authRoutes.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
const express = require("express");
|
||||
const {
|
||||
registerUser,
|
||||
loginUser,
|
||||
getProfile,
|
||||
} = require("../controllers/authController");
|
||||
const authToken = require("../middleware/authMiddleware");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Register user
|
||||
router.post("/register",registerUser );
|
||||
|
||||
// Login user
|
||||
router.post("/login", loginUser);
|
||||
|
||||
//protectRoute
|
||||
router.get("/profile", authToken, getProfile);
|
||||
|
||||
|
||||
module.exports = router;
|
Loading…
Reference in a new issue