diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000..c5c4cad722 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index b6e47617de..2abce0d2e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,129 +1,4 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - # Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -.python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site +node_modules -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json -# Pyre type checker -.pyre/ diff --git a/1-getallbooks.png b/1-getallbooks.png new file mode 100644 index 0000000000..270babe5c9 Binary files /dev/null and b/1-getallbooks.png differ diff --git a/2-gedetailsISBN.png b/2-gedetailsISBN.png new file mode 100644 index 0000000000..f80d91c205 Binary files /dev/null and b/2-gedetailsISBN.png differ diff --git a/3-getbooksbyauthor.png b/3-getbooksbyauthor.png new file mode 100644 index 0000000000..c451d8c907 Binary files /dev/null and b/3-getbooksbyauthor.png differ diff --git a/4-getbooksbytitle.png b/4-getbooksbytitle.png new file mode 100644 index 0000000000..6d897497f5 Binary files /dev/null and b/4-getbooksbytitle.png differ diff --git a/5-getbookreview.png b/5-getbookreview.png new file mode 100644 index 0000000000..3969dcd5bf Binary files /dev/null and b/5-getbookreview.png differ diff --git a/6-register.png b/6-register.png new file mode 100644 index 0000000000..24d64153ab Binary files /dev/null and b/6-register.png differ diff --git a/7-login.png b/7-login.png new file mode 100644 index 0000000000..79c25d79ec Binary files /dev/null and b/7-login.png differ diff --git a/8-reviewadded.png b/8-reviewadded.png new file mode 100644 index 0000000000..302ee834c8 Binary files /dev/null and b/8-reviewadded.png differ diff --git a/9-deletereviewpng.png b/9-deletereviewpng.png new file mode 100644 index 0000000000..17c05b029d Binary files /dev/null and b/9-deletereviewpng.png differ diff --git a/practice_project/README.md b/final_project/README.md similarity index 100% rename from practice_project/README.md rename to final_project/README.md diff --git a/final_project/index.js b/final_project/index.js new file mode 100644 index 0000000000..72ecda8e2c --- /dev/null +++ b/final_project/index.js @@ -0,0 +1,23 @@ +const express = require('express'); +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 app = express(); + +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 PORT =5000; + +app.use("/customer", customer_routes); +app.use("/", genl_routes); + +app.listen(PORT,()=>console.log("Server is running")); diff --git a/final_project/package.json b/final_project/package.json new file mode 100644 index 0000000000..931bba4eda --- /dev/null +++ b/final_project/package.json @@ -0,0 +1,19 @@ +{ + "name": "bookshop", + "version": "1.0.1", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "nodemon index.js" + }, + "keywords": [], + "author": "", + "license": "MIT", + "dependencies": { + "express": "^4.18.1", + "express-session": "^1.17.3", + "jsonwebtoken": "^8.5.1", + "nodemon": "^2.0.19" + } +} diff --git a/final_project/router/auth_users.js b/final_project/router/auth_users.js new file mode 100644 index 0000000000..237c7273be --- /dev/null +++ b/final_project/router/auth_users.js @@ -0,0 +1,84 @@ +const express = require('express'); +const jwt = require('jsonwebtoken'); +let books = require("./booksdb.js"); +const regd_users = express.Router(); + +let users = []; + +const isValid = (username)=>{ //returns boolean +//write code to check is the username is valid +} + +const authenticatedUser = (username,password)=>{ //returns boolean +//write code to check if username and password match the one we have in records. +} + +//only registered users can login +regd_users.post("/login", (req,res) => { + const { username, password } = req.body; + + // Check if both fields are provided + if (!username || !password) { + return res.status(400).json({ message: "Username and password are required." }); + } + + // Validate credentials + if (!authenticatedUser(username, password)) { + return res.status(401).json({ message: "Invalid username or password." }); + } + + // Generate JWT + const accessToken = jwt.sign({ username }, 'access', { expiresIn: '1h' }); + + // Save token in session + req.session.authorization = { + accessToken, + username + }; + + return res.status(200).json({ message: "User successfully logged in." }); +}); + +// Add a book review +regd_users.put("/auth/review/:isbn", (req, res) => { + //Write your code here + const token = req.headers['auth-token']; + const username = getUsernameFromToken(token); + if (!username) { + return res.status(401).json({ message: "Unauthorized. Please login." }); + } + const isbn = req.params.isbn; + const review = req.query.review; + if (!review) { + return res.status(400).json({ message: "Review query parameter is required." }); + } + if (!books[isbn]) { + return res.status(404).json({ message: "Book not found." }); + } + if (!books[isbn].reviews) { + books[isbn].reviews = {}; + } + books[isbn].reviews[username] = review; + return res.status(200).json({ message: `Review for book with ISBN ${isbn} has been added/updated` }); +}); + +regd_users.delete("/auth/review/:isbn", (req, res) => { + const token = req.headers['auth-token']; + const username = getUsernameFromToken(token); + if (!username) { + return res.status(401).json({ message: "Unauthorized. Please login." }); + } + const isbn = req.params.isbn; + if (!books[isbn]) { + return res.status(404).json({ message: "Book not found." }); + } + if (!books[isbn].reviews || !books[isbn].reviews[username]) { + return res.status(404).json({ message: "Review not found for this user and ISBN." }); + } + delete books[isbn].reviews[username]; + return res.status(200).json({ message: "Review deleted successfully." }); +}); + +module.exports.authenticated = regd_users; +module.exports.isValid = isValid; +module.exports.users = users; diff --git a/final_project/router/booksdb.js b/final_project/router/booksdb.js new file mode 100644 index 0000000000..0d719ca81b --- /dev/null +++ b/final_project/router/booksdb.js @@ -0,0 +1,14 @@ +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": {} } +} + +module.exports=books; diff --git a/final_project/router/general.js b/final_project/router/general.js new file mode 100644 index 0000000000..4a89bec5ad --- /dev/null +++ b/final_project/router/general.js @@ -0,0 +1,106 @@ +const express = require('express'); +let books = require("./booksdb.js"); +let isValid = require("./auth_users.js").isValid; +let users = require("./auth_users.js").users; +const public_users = express.Router(); +const { type } = require('express/lib/response.js'); + + +public_users.post("/register", (req,res) => { + //Write your code here + const {username,password}=req.body; + if(!username || !password){ + return res.status(400).json({ message: "Username and password are required." }); + } + if (users.find(user => user.username === username)) { + return res.status(400).json({ message: "Username already exists. Please choose a different one." }); + } + users.push({ username, password }); + return res.status(200).json({ message: "User registered successfully." }); +}); + + +// Get the book list available in the shop +public_users.get('/', function (req, res) { + //Write your code here + new Promise((resolve, reject) => { + resolve(JSON.stringify(books)); + }) + .then(data => { + res.status(200).json(data); + }) + .catch(error => { + res.status(500).json({ message: "Internal server error" }); + }); +}); + +// Get book details based on ISBN +public_users.get('/isbn/:isbn', function (req, res) { + new Promise((resolve, reject) => { + const isbn = req.params.isbn; + const book = books[isbn]; + if (!book) { + reject("Book not found"); + } else { + resolve(book); + } + }) + .then(data => { + res.status(200).json(data); + }) + .catch(error => { + res.status(404).json({ message: error }); + }); +}); + +// Get book details based on author +public_users.get('/author/:author', function (req, res) { + new Promise((resolve, reject) => { + const author = req.params.author; + const booksByAuthor = Object.values(books).filter(b => b.author === author); + if (booksByAuthor.length === 0) { + reject("No books found for this author"); + } else { + resolve(booksByAuthor); + } + }) + .then(data => { + res.status(200).json(data); + }) + .catch(error => { + res.status(404).json({ message: error }); + }); +}); + + +// Get all books based on title +public_users.get('/title/:title', function (req, res) { + //Write your code here + new Promise((resolve, reject) => { + const title = req.params.title; + const booksByTitle = Object.values(books).filter(b => b.title.includes(title)); + if (booksByTitle.length === 0) { + reject("No books found with this title"); + } else { + resolve(booksByTitle); + } + }) + .then(data => { + res.status(200).json(data); + }) + .catch(error => { + res.status(404).json({ message: error }); + }); +}); + +// Get book review +public_users.get('/review/:isbn', function (req, res) { + const isbn = req.params.isbn; + const book = books[isbn]; + if (!book || !book.reviews) { + return res.status(404).json({ message: "Reviews not found for this book" }); + } + return res.status(200).json(book.reviews); +}); + +module.exports.general = public_users; diff --git a/practice_project/index.js b/practice_project/index.js deleted file mode 100644 index 43c970fbe4..0000000000 --- a/practice_project/index.js +++ /dev/null @@ -1,13 +0,0 @@ -const express = require('express'); - -const routes = require('./router/practiceuser.js') - - -const app = express(); - -const PORT =5000; - -app.use(express.json()); -app.use("/user", routes); - -app.listen(PORT,()=>console.log("Server is running")); diff --git a/practice_project/router/practiceuser.js b/practice_project/router/practiceuser.js deleted file mode 100644 index fd346d1e9f..0000000000 --- a/practice_project/router/practiceuser.js +++ /dev/null @@ -1,38 +0,0 @@ -const express = require('express'); - -const router = express.Router(); - -var users = { - "johnsmith@gamil.com": {"firstName": "John","lastName": "Doe","DOB":"22-12-1990"}, - "annasmith@gamil.com":{"firstName": "Anna","lastName": "smith","DOB":"02-07-1983"}, - "peterjones@gamil.com":{"firstName": "Peter","lastName": "Jones","DOB":"21-03-1989"} -}; - - -router.get('/',function (req, res) { - -//Update the code here - -}); - -router.get('/:email',function (req, res) { -//Update the code here - -}); - -router.post("/",function (req,res){ -//Update the code here -}); - -router.put("/:email", function (req, res) { -//Update the code here - }); - - - router.delete("/:email", (req, res) => { -//Update the code here - }); - - - - module.exports=router;