From 323d4d3996b6f8bc6c2524b2e09d91a1d649032f Mon Sep 17 00:00:00 2001 From: Muhammad Abdullah Khan Date: Sun, 24 Aug 2025 07:32:58 -0400 Subject: [PATCH] Final Project --- final_project/index.js | 31 ++++-- final_project/router/auth_users.js | 90 ++++++++++++++-- final_project/router/booksdb.js | 64 +++++++++--- final_project/router/general.js | 162 +++++++++++++++++++++++++---- 4 files changed, 303 insertions(+), 44 deletions(-) diff --git a/final_project/index.js b/final_project/index.js index b890c1d380..5adc01093e 100644 --- a/final_project/index.js +++ b/final_project/index.js @@ -3,20 +3,39 @@ const jwt = require('jsonwebtoken'); const session = require('express-session') const customer_routes = require('./router/auth_users.js').authenticated; const genl_routes = require('./router/general.js').general; +const { users } = require("./router/auth_users.js"); const app = express(); app.use(express.json()); -app.use("/customer",session({secret:"fingerprint_customer",resave: true, saveUninitialized: true})) +app.get("/users", (req, res) => { + return res.status(200).json({ + users, + }); +}); + +app.use("/customer", session({ secret: "fingerprint_customer", resave: true, saveUninitialized: true })) + +app.use("/customer/auth/*", function auth(req, res, next) { + if (!req.session.authorization) { + return res.status(403).json({ message: "User not logged in" }); + } -app.use("/customer/auth/*", function auth(req,res,next){ -//Write the authenication mechanism here + const token = req.session.authorization.accessToken; + + jwt.verify(token, "fingerprint", (err, user) => { + if (err) { + return res.status(403).json({ message: "Invalid token" }); + } + req.user = user; + next(); + }); }); - -const PORT =5000; + +const PORT = 5000; app.use("/customer", customer_routes); app.use("/", genl_routes); -app.listen(PORT,()=>console.log("Server is running")); +app.listen(PORT, () => console.log("Server is running")); diff --git a/final_project/router/auth_users.js b/final_project/router/auth_users.js index 8cb6ef6e40..ff90a44c6d 100644 --- a/final_project/router/auth_users.js +++ b/final_project/router/auth_users.js @@ -6,23 +6,99 @@ 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"}); +regd_users.post("/login", (req, res) => { + const { username, password } = req.body; + + if (!username || !password) { + return res.status(409).json({ + message: "Please enter username and password both!", + }); + } + + if (!authenticatedUser(username, password)) { + return res.status(400).json({ + message: "Username and password do not match", + username, + password, + }); + } + + const token = jwt.sign({ username }, "fingerprint", { expiresIn: "1h" }); + + req.session.authorization = { + accessToken: token, + username, + }; + + return res.status(200).json({ + message: "Login successful", + token: token, + }); }); // 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; + + if (!review) { + return res.status(400).json({ message: "Review is required" }); + } + + const username = req.session.authorization?.username; + const book = books[isbn]; + + if (!book) { + return res.status(404).json({ message: "Book not found" }); + } + + book.reviews[username] = review; + + return res.status(200).json({ + message: "Rating saved", + reviews: book.reviews, + books + }); +}); + +regd_users.delete("/auth/review/:isbn", (req, res) => { + const isbn = req.params.isbn; // keep as string + const username = req.session.authorization?.username; + + if (!username) { + return res.status(401).json({ + message: "Not authorized. Please log in", + }); + } + + 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 from this user", + }); + } + + delete book.reviews[username]; // delete user’s review + + return res.status(200).json({ + message: "Review successfully deleted", + }); }); module.exports.authenticated = regd_users; diff --git a/final_project/router/booksdb.js b/final_project/router/booksdb.js index 0d719ca81b..a6a1ccaa34 100644 --- a/final_project/router/booksdb.js +++ b/final_project/router/booksdb.js @@ -1,14 +1,54 @@ let books = { - 1: {"author": "Chinua Achebe","title": "Things Fall Apart", "reviews": {} }, - 2: {"author": "Hans Christian Andersen","title": "Fairy tales", "reviews": {} }, - 3: {"author": "Dante Alighieri","title": "The Divine Comedy", "reviews": {} }, - 4: {"author": "Unknown","title": "The Epic Of Gilgamesh", "reviews": {} }, - 5: {"author": "Unknown","title": "The Book Of Job", "reviews": {} }, - 6: {"author": "Unknown","title": "One Thousand and One Nights", "reviews": {} }, - 7: {"author": "Unknown","title": "Nj\u00e1l's Saga", "reviews": {} }, - 8: {"author": "Jane Austen","title": "Pride and Prejudice", "reviews": {} }, - 9: {"author": "Honor\u00e9 de Balzac","title": "Le P\u00e8re Goriot", "reviews": {} }, - 10: {"author": "Samuel Beckett","title": "Molloy, Malone Dies, The Unnamable, the trilogy", "reviews": {} } -} + 1: { + author: "Chinua Achebe", + title: "Things Fall Apart", + reviews: {}, + }, + 2: { + author: "Hans Christian Andersen", + title: "Fairy tales", + reviews: {}, + }, + 3: { + author: "Dante Alighieri", + title: "The Divine Comedy", + reviews: {}, + }, + 4: { + author: "Unknown", + title: "The Epic Of Gilgamesh", + reviews: {}, + }, + 5: { + author: "Unknown", + title: "The Book Of Job", + reviews: {}, + }, + 6: { + author: "Unknown", + title: "One Thousand and One Nights", + reviews: {}, + }, + 7: { + author: "Unknown", + title: "Nj\u00e1l's Saga", + reviews: {}, + }, + 8: { + author: "Jane Austen", + title: "Pride and Prejudice", + reviews: {}, + }, + 9: { + author: "Honor\u00e9 de Balzac", + title: "Le P\u00e8re Goriot", + reviews: {}, + }, + 10: { + author: "Samuel Beckett", + title: "Molloy, Malone Dies, The Unnamable, the trilogy", + reviews: {}, + }, +}; -module.exports=books; +module.exports = books; \ No newline at end of file diff --git a/final_project/router/general.js b/final_project/router/general.js index 9eb0ac1a91..e51df02520 100644 --- a/final_project/router/general.js +++ b/final_project/router/general.js @@ -5,39 +5,163 @@ 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"}); +public_users.post("/register", (req, res) => { + const { username, password } = req.body; + if (!username || !password) { + return res.status(400).json({ + message: "User name and password are required", + }); + } + + const isExist = users.find((user) => user.username === username); + if (isExist) { + return res.status(400).json({ + message: "This user already exists", + }); + } + users.push({ + username, + password, + }); + return res.status(201).json({ + message: "User was successfully registered :)", + username: username, + }); }); // 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"}); +public_users.get("/", async (req, res) => { + try { + const response = await new Promise((resolve) => { + setTimeout(() => { + resolve({ data: books }); + }, 100); + }); + + return res.status(200).json({ + message: "Booklist loaded", + books: response.data, + }); + } catch (error) { + return res.status(500).json({ + message: "Error loading", + error: error.message, + }); + } }); // 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"}); - }); +public_users.get("/isbn/:isbn", async (req, res) => { + try { + const isbn = parseInt(req.params.isbn); + if (isNaN(isbn)) { + return res.status(400).json({ + message: "Enter ISBN number", + }); + } + + const response = await new Promise((resolve, reject) => { + setTimeout(() => { + resolve({ + data: books[isbn], + }); + }, 100); + }); + + return res.status(200).json({ + message: "Book with this ISBN", + book: response.data, + }); + } catch (err) { + return res.status(400).json({ + message: "Error accessing the book with ISBN", + error: err.message, + }); + } +}); // 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"}); +public_users.get("/author/:author", async (req, res) => { + try { + const autor = req.params.author.toLowerCase(); + const response = await new Promise((resolve) => { + setTimeout(() => { + resolve({ data: books }); + }, 100); + }); + const buchlist = response.data; + + const result = Object.values(buchlist).filter( + (book) => book.author.toLowerCase() === autor + ); + + if (result.length === 0) { + return res.status(404).json({ + message: "No data for these users", + }); + } + + return res.status(200).json({ + message: "book data author", + books: result, + }); + } catch (err) { + return res.json({ + message: "Error loading books", + error: err.message, + }); + } }); // 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"}); +public_users.get("/title/:title", async (req, res) => { + try { + const title = req.params.title.toLowerCase(); + const response = await new Promise((resolve) => { + setTimeout(() => { + resolve({ data: books }); + }, 100); + }); + const bookList = Object.values(response.data); + const book = bookList.filter((b) => b.title.toLowerCase() === title); + if (book.length === 0) { + return res.status(404).json({ + message: "not found", + }); + } + + return res.status(200).json({ + message: "Books", + books: book, + }); + } catch (error) { + return res.status(500).json({ + message: "Error loading book details", + error: error.message, + }); + } }); // 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"}); +public_users.get("/review/:isbn", function (req, res) { + const isbn = parseInt(req.params.isbn); + const book = books[isbn]; + if (!book) { + return res.status(404).json({ + message: "book not found", + }); + } + + const reviewKeys = Object.keys(book.reviews); + if (reviewKeys.length === 0) { + return res.json({ + message: "this book has no rating", + }); + } + return res.json({ + message: "Evaluation", + reviews: book.reviews, + }); }); module.exports.general = public_users;