From 337ae5b5a79be2fa050e74097984987c598cf1c8 Mon Sep 17 00:00:00 2001 From: Atakan Temizkan Date: Sun, 4 Aug 2024 12:02:16 +0000 Subject: [PATCH 1/2] finished core criteria --- package-lock.json | 62 ++++++++++++++++++------------ src/https.js | 14 +++++++ src/index.js | 19 +++++++--- src/routers/books.js | 62 +++++++++++++++++++++++++++++- src/routers/films.js | 62 ++++++++++++++++++++++++++++++ src/routers/users.js | 90 ++++++++++++++++++++++++++++++++++++++++++++ src/server.js | 11 +++++- 7 files changed, 288 insertions(+), 32 deletions(-) create mode 100644 src/https.js diff --git a/package-lock.json b/package-lock.json index fc9d54a..95caf7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1395,12 +1395,13 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -1408,7 +1409,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -1428,12 +1429,13 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -1490,6 +1492,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -1708,6 +1711,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -1719,9 +1723,10 @@ "dev": true }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -1992,16 +1997,17 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -2054,10 +2060,11 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2375,6 +2382,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -2513,6 +2521,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -3367,6 +3376,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -3914,9 +3924,10 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -4038,7 +4049,8 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", @@ -4489,6 +4501,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -4541,6 +4554,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" diff --git a/src/https.js b/src/https.js new file mode 100644 index 0000000..fce02af --- /dev/null +++ b/src/https.js @@ -0,0 +1,14 @@ +function httpsServer(app) { + const https = require("https"); + const fs = require("fs"); + + const SSLcert = { + key: fs.readFileSync("/etc/letsencrypt/live/atakan.cloud/privkey.pem"), + cert: fs.readFileSync("/etc/letsencrypt/live/atakan.cloud/fullchain.pem"), + }; + + const httpsServer = https.createServer(SSLcert, app); + return httpsServer; +} + +module.exports = httpsServer; diff --git a/src/index.js b/src/index.js index c16707f..384ae99 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,17 @@ /* REQUIRE APP */ -const app = require('./server.js') -const port = 3030; +const app = require("./server.js"); +const httpsServer = require("./https.js"); +// const port = 3030; -/* START SERVER */ -app.listen(port, () => { - console.log(`Server is running on http://localhost:${port}/`); +httpsServer(app).listen(3030, () => { + console.log(`HTTPS server is running`); +}); + +app.listen(3031, () => { + console.log(`HTTP server is running`); }); + +/* START SERVER */ +// app.listen(port, () => { +// console.log(`Server is running on http://localhost:${port}/`); +// }); diff --git a/src/routers/books.js b/src/routers/books.js index 18b9a7c..d37e196 100644 --- a/src/routers/books.js +++ b/src/routers/books.js @@ -1,4 +1,62 @@ -// Import data here... +const express = require("express"); +const router = express.Router(); -// Write routes here... +const { books } = require("../../data/index"); + +let nextBookId = books.length + 1; + +//FUNCTIONS + +function getBookById(providedId) { + const foundBook = books.find((book) => book.id == providedId); + return foundBook; +} + +//GET ROUTES + +router.get("/", (req, res) => { + res.json({ books }); +}); + +router.get("/:id", (req, res) => { + const foundBook = getBookById(req.params.id); + res.json({ + book: foundBook, + }); +}); + +//POST ROUTES + +router.post("/", (req, res) => { + const newBook = { id: nextBookId, ...req.body }; + books.push(newBook); + res.status(201).json({ book: newBook }); + nextBookId++; +}); + +//DELETE ROUTES + +router.delete("/:id", (req, res) => { + const foundBook = getBookById(req.params.id); + books.splice(books.indexOf(foundBook), 1); + res.json({ + book: foundBook, + }); +}); + +//PUT ROUTES + +router.put("/:id", (req, res) => { + const foundBook = getBookById(req.params.id); + + let theBook = (books[books.indexOf(foundBook)] = { + id: foundBook.id, + ...req.body, + }); + res.json({ + book: theBook, + }); +}); + +module.exports = router; diff --git a/src/routers/films.js b/src/routers/films.js index e69de29..209ec99 100644 --- a/src/routers/films.js +++ b/src/routers/films.js @@ -0,0 +1,62 @@ +const express = require("express"); + +const router = express.Router(); + +const { films } = require("../../data/index"); + +let nextFilmId = films.length + 1; + +//FUNCTIONS + +function getFilmById(providedId) { + const foundFilm = films.find((film) => film.id == providedId); + return foundFilm; +} + +//GET ROUTES + +router.get("/", (req, res) => { + res.json({ films }); +}); + +router.get("/:id", (req, res) => { + const foundFilm = getFilmById(req.params.id); + res.json({ + film: foundFilm, + }); +}); + +//POST ROUTES + +router.post("/", (req, res) => { + const newFilm = { id: nextFilmId, ...req.body }; + films.push(newFilm); + res.status(201).json({ film: newFilm }); + nextFilmId++; +}); + +//DELETE ROUTES + +router.delete("/:id", (req, res) => { + const foundFilm = getFilmById(req.params.id); + films.splice(films.indexOf(foundFilm), 1); + res.json({ + film: foundFilm, + }); +}); + +//PUT ROUTES + +router.put("/:id", (req, res) => { + const foundFilm = getFilmById(req.params.id); + + let theFilm = (films[films.indexOf(foundFilm)] = { + id: foundFilm.id, + ...req.body, + }); + res.json({ + film: theFilm, + }); +}); + +module.exports = router; diff --git a/src/routers/users.js b/src/routers/users.js index e69de29..e640fd8 100644 --- a/src/routers/users.js +++ b/src/routers/users.js @@ -0,0 +1,90 @@ +const express = require("express"); + +const router = express.Router(); + +const { users } = require("../../data/index"); + +let nextUserId = users.length + 1; + +//FUNCTIONS + +function getUserById(providedId) { + const foundUser = users.find((user) => user.id == providedId); + return foundUser; +} + +function noUserErr(res) { + return res.status(404).json({ + error: "A user with the provided ID does not exist", + }); +} + +function missingFieldsErr(res) { + return res.status(400).json({ + error: "Missing fields in request body", + }); +} + +//GET ROUTES + +router.get("/", (req, res) => { + res.json({ users }); +}); + +router.get("/:id", (req, res) => { + const foundUser = getUserById(req.params.id); + + foundUser + ? res.json({ + user: foundUser, + }) + : noUserErr(res); +}); + +//POST ROUTES + +router.post("/", (req, res) => { + if (!req.body.email) { + missingFieldsErr(res); + } else { + const newUser = { id: nextUserId, ...req.body }; + users.push(newUser); + res.status(201).json({ user: newUser }); + nextUserId++; + } +}); + +//DELETE ROUTES + +router.delete("/:id", (req, res) => { + const foundUser = getUserById(req.params.id); + + if (foundUser) { + users.splice(users.indexOf(foundUser), 1); + res.json({ + user: foundUser, + }); + } else { + noUserErr(res); + } +}); + +//PUT ROUTES + +router.put("/:id", (req, res) => { + const foundUser = getUserById(req.params.id); + + if (foundUser) { + let theUser = (users[users.indexOf(foundUser)] = { + id: foundUser.id, + ...req.body, + }); + res.json({ + user: theUser, + }); + } else { + noUserErr(res); + } +}); + +module.exports = router; diff --git a/src/server.js b/src/server.js index 715321f..5834e6a 100644 --- a/src/server.js +++ b/src/server.js @@ -11,8 +11,17 @@ app.use(morgan("dev")); // REQUIRE ROUTERS const usersRouter = require("./routers/users"); +const filmsRouter = require("./routers/films"); +const booksRouter = require("./routers/books"); // ADD ROUTERS TO APP +app.get("/", (req, res) => { + res.json("BONJUR"); +}); -module.exports = app +app.use("/users", usersRouter); +app.use("/films", filmsRouter); +app.use("/books", booksRouter); + +module.exports = app; From 26fd1c5c8d16c3e27604aff32842bf9e5428f3e5 Mon Sep 17 00:00:00 2001 From: Atakan Temizkan Date: Sun, 4 Aug 2024 14:31:26 +0000 Subject: [PATCH 2/2] finished extensions --- src/routers/books.js | 77 +++++++++++++++++++++++++-------- src/routers/films.js | 100 +++++++++++++++++++++++++++++++++++-------- src/routers/users.js | 16 +++++-- 3 files changed, 152 insertions(+), 41 deletions(-) diff --git a/src/routers/books.js b/src/routers/books.js index d37e196..71b8742 100644 --- a/src/routers/books.js +++ b/src/routers/books.js @@ -13,6 +13,24 @@ function getBookById(providedId) { return foundBook; } +function noBookErr(res) { + return res.status(404).json({ + error: "A book the provided ID does not exist", + }); +} + +function missingFieldsErr(res) { + return res.status(400).json({ + error: "Missing fields in request body", + }); +} + +function alreadyExistsErr(res) { + return res.status(409).json({ + error: "A book with the provided title already exists", + }); +} + //GET ROUTES router.get("/", (req, res) => { @@ -21,42 +39,63 @@ router.get("/", (req, res) => { router.get("/:id", (req, res) => { const foundBook = getBookById(req.params.id); - res.json({ - book: foundBook, - }); + + foundBook + ? res.json({ + book: foundBook, + }) + : noBookErr(res); }); //POST ROUTES router.post("/", (req, res) => { - const newBook = { id: nextBookId, ...req.body }; - books.push(newBook); - res.status(201).json({ book: newBook }); - nextBookId++; + if (!req.body.title || !req.body.type || !req.body.author) { + missingFieldsErr(res); + } else if (books.find((book) => book.title == req.body.title)) { + alreadyExistsErr(res); + } else { + const newBook = { id: nextBookId, ...req.body }; + books.push(newBook); + res.status(201).json({ book: newBook }); + nextBookId++; + } }); //DELETE ROUTES router.delete("/:id", (req, res) => { const foundBook = getBookById(req.params.id); - books.splice(books.indexOf(foundBook), 1); - res.json({ - book: foundBook, - }); + + if (foundBook) { + books.splice(books.indexOf(foundBook), 1); + res.json({ + book: foundBook, + }); + } else { + noBookErr(res); + } }); //PUT ROUTES router.put("/:id", (req, res) => { const foundBook = getBookById(req.params.id); - - let theBook = (books[books.indexOf(foundBook)] = { - id: foundBook.id, - ...req.body, - }); - res.json({ - book: theBook, - }); + if (!req.body.title || !req.body.type || !req.body.author) { + missingFieldsErr(res); + } else if (!foundBook) { + noBookErr(res); + } else if (books.find((book) => book.title == req.body.title)) { + alreadyExistsErr(res); + } else { + let theBook = (books[books.indexOf(foundBook)] = { + id: foundBook.id, + ...req.body, + }); + res.json({ + book: theBook, + }); + } }); module.exports = router; diff --git a/src/routers/films.js b/src/routers/films.js index 209ec99..61deca4 100644 --- a/src/routers/films.js +++ b/src/routers/films.js @@ -13,50 +13,112 @@ function getFilmById(providedId) { return foundFilm; } +function noFilmErr(res) { + return res.status(404).json({ + error: "A film with provided ID does not exist", + }); +} + +function missingFieldsErr(res) { + return res.status(400).json({ + error: "Missing fields in request body", + }); +} + +function alreadyExistsErr(res) { + return res.status(409).json({ + error: "A film with the provided title already exists", + }); +} + //GET ROUTES router.get("/", (req, res) => { - res.json({ films }); + if (req.query.director) { + res.json({ + films: films.filter((film) => film.director == req.query.director), + }); + } else { + res.json({ films }); + } }); router.get("/:id", (req, res) => { const foundFilm = getFilmById(req.params.id); - res.json({ - film: foundFilm, - }); + + foundFilm + ? res.json({ + film: foundFilm, + }) + : noFilmErr(res); }); //POST ROUTES router.post("/", (req, res) => { - const newFilm = { id: nextFilmId, ...req.body }; - films.push(newFilm); - res.status(201).json({ film: newFilm }); - nextFilmId++; + if (!req.body.title) { + missingFieldsErr(res); + } else if (films.find((film) => film.title == req.body.title)) { + alreadyExistsErr(res); + } else { + const newFilm = { id: nextFilmId, ...req.body }; + films.push(newFilm); + res.status(201).json({ film: newFilm }); + nextFilmId++; + } }); //DELETE ROUTES router.delete("/:id", (req, res) => { const foundFilm = getFilmById(req.params.id); - films.splice(films.indexOf(foundFilm), 1); - res.json({ - film: foundFilm, - }); + + if (foundFilm) { + films.splice(films.indexOf(foundFilm), 1); + res.json({ + film: foundFilm, + }); + } else { + noFilmErr(res); + } }); //PUT ROUTES router.put("/:id", (req, res) => { const foundFilm = getFilmById(req.params.id); + if (!req.body.title || !req.body.director) { + missingFieldsErr(res); + } else if (!foundFilm) { + noFilmErr(res); + } else if (films.find((film) => film.title == req.body.title)) { + alreadyExistsErr(res); + } else { + let theFilm = (films[films.indexOf(foundFilm)] = { + id: foundFilm.id, + ...req.body, + }); + res.json({ + film: theFilm, + }); + } +}); - let theFilm = (films[films.indexOf(foundFilm)] = { - id: foundFilm.id, - ...req.body, - }); - res.json({ - film: theFilm, - }); +router.patch("/:id", (req, res) => { + const foundFilm = getFilmById(req.params.id); + if (!foundFilm) { + noFilmErr(res); + } else if (films.find((film) => film.title == req.body.title)) { + alreadyExistsErr(res); + } else { + let theFilm = (films[films.indexOf(foundFilm)] = { + id: foundFilm.id, + ...req.body, + }); + res.json({ + film: theFilm, + }); + } }); module.exports = router; diff --git a/src/routers/users.js b/src/routers/users.js index e640fd8..ae508c6 100644 --- a/src/routers/users.js +++ b/src/routers/users.js @@ -25,6 +25,12 @@ function missingFieldsErr(res) { }); } +function alreadyExistsErr(res) { + return res.status(409).json({ + error: "A user with the provided email already exists", + }); +} + //GET ROUTES router.get("/", (req, res) => { @@ -46,6 +52,8 @@ router.get("/:id", (req, res) => { router.post("/", (req, res) => { if (!req.body.email) { missingFieldsErr(res); + } else if (users.find((user) => user.email == req.body.email)) { + alreadyExistsErr(res); } else { const newUser = { id: nextUserId, ...req.body }; users.push(newUser); @@ -74,7 +82,11 @@ router.delete("/:id", (req, res) => { router.put("/:id", (req, res) => { const foundUser = getUserById(req.params.id); - if (foundUser) { + if (!foundUser) { + noUserErr(res); + } else if (users.find((user) => user.email == req.body.email)) { + alreadyExistsErr(res); + } else { let theUser = (users[users.indexOf(foundUser)] = { id: foundUser.id, ...req.body, @@ -82,8 +94,6 @@ router.put("/:id", (req, res) => { res.json({ user: theUser, }); - } else { - noUserErr(res); } });