Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions final_project/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -11,12 +12,23 @@ 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 = req.session.authorization?.accessToken;
if(!token){
return 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;

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"));
72 changes: 61 additions & 11 deletions final_project/router/auth_users.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,74 @@ const regd_users = express.Router();

let users = [];

const isValid = (username)=>{ //returns boolean
//write code to check is the username is valid
}
const isValid = (username) => {
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.
}
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) => {
//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(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 successful",
token: accessToken
});
});

// 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) {
return 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 = books[isbn].reviews || {};
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 || !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;
Expand Down
149 changes: 134 additions & 15 deletions final_project/router/general.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,160 @@ 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) => {
//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){
return 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){
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 an async callback function
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', (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
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;