From 6d475631811fc92bdf1023a95bdf326ce284b875 Mon Sep 17 00:00:00 2001 From: Sbadhon Date: Sat, 13 Sep 2025 05:46:55 -0500 Subject: [PATCH 1/4] Task: 1 to 9 --- final_project/index.js | 12 +++++- final_project/router/auth_users.js | 60 ++++++++++++++++++++++++++---- final_project/router/general.js | 53 +++++++++++++++++++------- 3 files changed, 103 insertions(+), 22 deletions(-) diff --git a/final_project/index.js b/final_project/index.js index b890c1d380..0bfa4bdaac 100644 --- a/final_project/index.js +++ b/final_project/index.js @@ -11,7 +11,17 @@ app.use(express.json()); app.use("/customer",session({secret:"fingerprint_customer",resave: true, saveUninitialized: true})) app.use("/customer/auth/*", function auth(req,res,next){ -//Write the authenication mechanism here + const token = re.session.authorization?.accessToken; + if(!token){ + res.status(403).json({message: "Access token missing. Please log in."}) + } + jwt.verify(token, "access",(err, user) => { + if(err){ + return res.status(403).json({message: "Invalid or expired token"}) + } + req.user = user; + next(); + }) }); const PORT =5000; diff --git a/final_project/router/auth_users.js b/final_project/router/auth_users.js index 8cb6ef6e40..ef5d12b4a9 100644 --- a/final_project/router/auth_users.js +++ b/final_project/router/auth_users.js @@ -6,23 +6,69 @@ const regd_users = express.Router(); let users = []; const isValid = (username)=>{ //returns boolean -//write code to check is the username is valid + return users.some(user => user.username === username); } const authenticatedUser = (username,password)=>{ //returns boolean -//write code to check if username and password match the one we have in records. -} + return users.some(user => user.username === username && user.password === password); +}; //only registered users can login regd_users.post("/login", (req,res) => { - //Write your code here - return res.status(300).json({message: "Yet to be implemented"}); + const { username, password} = req.body; + if(!username || !password){ + return res.status(400).json({message: "Username and password are required"}); + } + if(!authenticatedUser(username, password)){ + return res.status(401).json({message: "Invalid credentials"}); + } + + const accessToken = jwt.sign( + {username}, + 'access', + {expiresIn: '1h'} + ) + req.session.authorization = { accessToken, username }; + return res.status(200).json({message: "Login sucessful"}); }); // Add a book review regd_users.put("/auth/review/:isbn", (req, res) => { - //Write your code here - return res.status(300).json({message: "Yet to be implemented"}); + const isbn = req.params.isbn; + const review = req.body.review; + const username = req.session.authorization?.username; + if(!username){ + res.status(403).json({message: "User not authenticated"}) + } + if(!books[isbn]){ + return res.status(404).json({message: "Book not found"}) + } + if(!review){ + return res.status(400).json({message: "Review content is required"}) + } + books[isbn].reviews[username] = review; + return res.status(200).json({message: "Review added/updated successfully"}); +}); + +regd_users.delete("/auth/review/:isbn", (req, res) => { + const isbn = req.params.isbn; + const username = req.session.authorization?.username; + + if (!username) { + return res.status(403).json({ message: "User not authenticated" }); + } + + const book = books[isbn]; + if (!book) { + return res.status(404).json({ message: "Book not found" }); + } + + if (!book.reviews[username]) { + return res.status(404).json({ message: "No review found for this user" }); + } + + delete book.reviews[username]; + return res.status(200).json({ message: "Review deleted successfully" }); }); module.exports.authenticated = regd_users; diff --git a/final_project/router/general.js b/final_project/router/general.js index 9eb0ac1a91..6d11d58ee2 100644 --- a/final_project/router/general.js +++ b/final_project/router/general.js @@ -4,40 +4,65 @@ let isValid = require("./auth_users.js").isValid; let users = require("./auth_users.js").users; const public_users = express.Router(); - public_users.post("/register", (req,res) => { - //Write your code here - return res.status(300).json({message: "Yet to be implemented"}); + const { username, password } = req.body; + if(!username || !password){ + return res.status(400).json({message : "Username and password are required"}) + } + if(isValid(username)){ + return res.status(409).json({message: "User already exists"}); + } + users.push({username, password}); + return res.status(200).json({message: "User sucessfully registered"}); }); // Get the book list available in the shop public_users.get('/',function (req, res) { - //Write your code here - return res.status(300).json({message: "Yet to be implemented"}); + return res.status(200).json(books); }); // Get book details based on ISBN public_users.get('/isbn/:isbn',function (req, res) { - //Write your code here - return res.status(300).json({message: "Yet to be implemented"}); + const isbn = req.params.isbn; + const book = books[isbn]; + if(!book){ + res.status(404).json({ message : "Book not found"}); + } + return res.status(200).json(book); }); - + // Get book details based on author public_users.get('/author/:author',function (req, res) { - //Write your code here - return res.status(300).json({message: "Yet to be implemented"}); + const author = req.params.author.toLocaleLowerCase(); + const filteredBooks = Object.entries(books) + .filter(([_, book]) => book.author.toLocaleLowerCase() === author) + .map(([isbn, book]) => ({isbn, ...book})); + if(filteredBooks.length === 0){ + return res.status(404).json({message: "No books found by this author"}) + } + return res.status(200).json(filteredBooks); }); // Get all books based on title public_users.get('/title/:title',function (req, res) { - //Write your code here - return res.status(300).json({message: "Yet to be implemented"}); + const title = req.params.title.toLocaleLowerCase(); + const filteredBooks = Object.entries(books) + .filter(([_, book]) => book.title.toLocaleLowerCase() === title) + .map(([isbn, book]) => ({isbn, ...book})); + if(filteredBooks.length === 0){ + return res.json({message: "No books found with this title"}) + } + return res.status(200).json(filteredBooks); }); // Get book review public_users.get('/review/:isbn',function (req, res) { - //Write your code here - return res.status(300).json({message: "Yet to be implemented"}); + const isbn = req.params.isbn; + const book = books[isbn]; + if(!book){ + res.status(404).json({ message: "Book not found"}) + } + return res.status(200).json(book.reviews); }); module.exports.general = public_users; From 3dc347897d887d77869fb93ee3512a781bfba316 Mon Sep 17 00:00:00 2001 From: Sbadhon Date: Sat, 13 Sep 2025 21:56:11 -0500 Subject: [PATCH 2/4] Task: 10 to 13 --- final_project/index.js | 8 ++- final_project/router/general.js | 99 ++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 6 deletions(-) diff --git a/final_project/index.js b/final_project/index.js index 0bfa4bdaac..61fcba41ac 100644 --- a/final_project/index.js +++ b/final_project/index.js @@ -2,6 +2,7 @@ const express = require('express'); const jwt = require('jsonwebtoken'); const session = require('express-session') const customer_routes = require('./router/auth_users.js').authenticated; +const public_routes = require('./router/general.js').public_users; const genl_routes = require('./router/general.js').general; const app = express(); @@ -11,9 +12,9 @@ app.use(express.json()); app.use("/customer",session({secret:"fingerprint_customer",resave: true, saveUninitialized: true})) app.use("/customer/auth/*", function auth(req,res,next){ - const token = re.session.authorization?.accessToken; + const token = req.session.authorization?.accessToken; if(!token){ - res.status(403).json({message: "Access token missing. Please log in."}) + return res.status(403).json({message: "Access token missing. Please log in."}) } jwt.verify(token, "access",(err, user) => { if(err){ @@ -27,6 +28,7 @@ app.use("/customer/auth/*", function auth(req,res,next){ const PORT =5000; app.use("/customer", customer_routes); -app.use("/", genl_routes); +app.use("/", public_routes); +app.use("/general", genl_routes); app.listen(PORT,()=>console.log("Server is running")); diff --git a/final_project/router/general.js b/final_project/router/general.js index 6d11d58ee2..c88846bf24 100644 --- a/final_project/router/general.js +++ b/final_project/router/general.js @@ -3,6 +3,7 @@ let books = require("./booksdb.js"); let isValid = require("./auth_users.js").isValid; let users = require("./auth_users.js").users; const public_users = express.Router(); +let general = express.Router(); public_users.post("/register", (req,res) => { const { username, password } = req.body; @@ -26,7 +27,7 @@ public_users.get('/isbn/:isbn',function (req, res) { const isbn = req.params.isbn; const book = books[isbn]; if(!book){ - res.status(404).json({ message : "Book not found"}); + return res.status(404).json({ message : "Book not found"}); } return res.status(200).json(book); }); @@ -60,9 +61,101 @@ public_users.get('/review/:isbn',function (req, res) { const isbn = req.params.isbn; const book = books[isbn]; if(!book){ - res.status(404).json({ message: "Book not found"}) + return res.status(404).json({ message: "Book not found"}) } return res.status(200).json(book.reviews); }); -module.exports.general = public_users; + + // Task 10: Get all books using Promise + function getBooks() { + return new Promise((resolve, reject) => { + if (books) { + resolve(books); + } else { + reject("Books not available"); + } + }); + } + + general.get("/", async (req, res) => { + try { + const data = await getBooks(); + res.send(JSON.stringify(data, null, 4)); + } catch (err) { + res.status(500).send({ message: err }); + } + }); + + // Task 11: Get book by ISBN using Promise + function getBookByISBN(isbn) { + return new Promise((resolve, reject) => { + const book = books[isbn]; + if (book) { + resolve(book); + } else { + reject("Book not found for ISBN: " + isbn); + } + }); + } + + general.get("/isbn/:isbn", async (req, res) => { + try { + const isbn = req.params.isbn; + const data = await getBookByISBN(isbn); + res.send(JSON.stringify(data, null, 4)); + } catch (err) { + res.status(404).send({ message: err }); + } + }); + + // Task 12: Get books by author using Promise + function getBooksByAuthor(author) { + return new Promise((resolve, reject) => { + const matchingBooks = Object.values(books).filter( + (book) => book.author.toLowerCase() === author.toLowerCase() + ); + if (matchingBooks.length > 0) { + resolve(matchingBooks); + } else { + reject("No books found by author: " + author); + } + }); + } + + general.get("/author/:author", async (req, res) => { + try { + const author = req.params.author; + const data = await getBooksByAuthor(author); + res.send(JSON.stringify(data, null, 4)); + } catch (err) { + res.status(404).send({ message: err }); + } + }); + + // Task 13: Get books by title using Promise + function getBooksByTitle(title) { + return new Promise((resolve, reject) => { + const matchingBooks = Object.values(books).filter( + (book) => book.title.toLowerCase() === title.toLowerCase() + ); + if (matchingBooks.length > 0) { + resolve(matchingBooks); + } else { + reject("No books found with title: " + title); + } + }); + } + + general.get("/title/:title", async (req, res) => { + try { + const title = req.params.title; + const data = await getBooksByTitle(title); + res.send(JSON.stringify(data, null, 4)); + } catch (err) { + res.status(404).send({ message: err }); + } + }); + + module.exports.general = general; + module.exports.public_users = public_users; From 7d78c53ce3288ba88e79f636fea56f24b9dd3abb Mon Sep 17 00:00:00 2001 From: Sbadhon Date: Sat, 13 Sep 2025 22:19:35 -0500 Subject: [PATCH 3/4] Change Task 11 as instruction --- final_project/router/general.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/final_project/router/general.js b/final_project/router/general.js index c88846bf24..58ff731537 100644 --- a/final_project/router/general.js +++ b/final_project/router/general.js @@ -67,7 +67,7 @@ public_users.get('/review/:isbn',function (req, res) { }); - // Task 10: Get all books using Promise + // Task 10: Get all books using an async callback function function getBooks() { return new Promise((resolve, reject) => { if (books) { @@ -99,14 +99,15 @@ public_users.get('/review/:isbn',function (req, res) { }); } - general.get("/isbn/:isbn", async (req, res) => { - try { - const isbn = req.params.isbn; - const data = await getBookByISBN(isbn); - res.send(JSON.stringify(data, null, 4)); - } catch (err) { - res.status(404).send({ message: err }); - } + general.get('/isbn/:isbn', (req, res) => { + const isbn = req.params.isbn; + getBookByISBN(isbn) + .then((book) => { + res.send(JSON.stringify(book, null, 4)); // Pretty print JSON + }) + .catch((error) => { + res.status(404).send({ message: error }); + }); }); // Task 12: Get books by author using Promise From 2cd8e483b677775d0b7cc06255cdce35444c9219 Mon Sep 17 00:00:00 2001 From: Sbadhon Date: Sun, 14 Sep 2025 02:31:40 -0500 Subject: [PATCH 4/4] add token test from postman --- final_project/router/auth_users.js | 52 ++++++++++++++++-------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/final_project/router/auth_users.js b/final_project/router/auth_users.js index ef5d12b4a9..a93f4d0385 100644 --- a/final_project/router/auth_users.js +++ b/final_project/router/auth_users.js @@ -5,31 +5,34 @@ const regd_users = express.Router(); let users = []; -const isValid = (username)=>{ //returns boolean - return users.some(user => user.username === username); -} +const isValid = (username) => { + return users.some(user => user.username === username); +}; -const authenticatedUser = (username,password)=>{ //returns boolean +const authenticatedUser = (username, password) => { return users.some(user => user.username === username && user.password === password); }; //only registered users can login -regd_users.post("/login", (req,res) => { - const { username, password} = req.body; - if(!username || !password){ - return res.status(400).json({message: "Username and password are required"}); +regd_users.post("/login", (req, res) => { + const { username, password } = req.body; + + if (!username || !password) { + return res.status(400).json({ message: "Username and password are required" }); } - if(!authenticatedUser(username, password)){ - return res.status(401).json({message: "Invalid credentials"}); + + if (!authenticatedUser(username, password)) { + return res.status(401).json({ message: "Invalid credentials" }); } - const accessToken = jwt.sign( - {username}, - 'access', - {expiresIn: '1h'} - ) + const accessToken = jwt.sign({ username }, 'access', { expiresIn: '1h' }); + req.session.authorization = { accessToken, username }; - return res.status(200).json({message: "Login sucessful"}); + + return res.status(200).json({ + message: "Login successful", + token: accessToken + }); }); // Add a book review @@ -37,17 +40,18 @@ regd_users.put("/auth/review/:isbn", (req, res) => { const isbn = req.params.isbn; const review = req.body.review; const username = req.session.authorization?.username; - if(!username){ - res.status(403).json({message: "User not authenticated"}) + if (!username) { + return res.status(403).json({ message: "User not authenticated" }); } - if(!books[isbn]){ - return res.status(404).json({message: "Book not found"}) + if (!books[isbn]) { + return res.status(404).json({ message: "Book not found" }); } - if(!review){ - return res.status(400).json({message: "Review content is required"}) + if (!review) { + return res.status(400).json({ message: "Review content is required" }); } + books[isbn].reviews = books[isbn].reviews || {}; books[isbn].reviews[username] = review; - return res.status(200).json({message: "Review added/updated successfully"}); + return res.status(200).json({ message: "Review added/updated successfully" }); }); regd_users.delete("/auth/review/:isbn", (req, res) => { @@ -63,7 +67,7 @@ regd_users.delete("/auth/review/:isbn", (req, res) => { return res.status(404).json({ message: "Book not found" }); } - if (!book.reviews[username]) { + if (!book.reviews || !book.reviews[username]) { return res.status(404).json({ message: "No review found for this user" }); }