From c1d5b484e09da3319bddcc1de3ce26a1191a4f82 Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Sun, 15 Jun 2025 14:19:22 +0200 Subject: [PATCH 01/17] getting thoughts and individual thoughts --- server.js | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/server.js b/server.js index f47771b..58e693f 100644 --- a/server.js +++ b/server.js @@ -1,22 +1,47 @@ -import cors from "cors" -import express from "express" +import cors from "cors"; +import express from "express"; +import data from "./data.json"; // Defines the port the app will run on. Defaults to 8080, but can be overridden // when starting the server. Example command to overwrite PORT env variable value: // PORT=9000 npm start -const port = process.env.PORT || 8080 -const app = express() +const port = process.env.PORT || 8080; +const app = express(); // Add middlewares to enable cors and json body parsing -app.use(cors()) -app.use(express.json()) +app.use(cors()); +app.use(express.json()); // Start defining your routes here app.get("/", (req, res) => { - res.send("Hello Technigo!") -}) + res.send("Hello Technigo!"); +}); + +app.get("/thoughts", (req, res) => { + res.json(data); +}); + +app.get("/thoughts/:thoughtId", (req, res) => { + const id = req.params.thoughtId; + const post = data.filter((item) => { + return item._id === id; + }); + if (post.length === 0) { + res.status(404).json({ error: "Thought not found" }); + } + res.json(post[0]); +}); + +// new thought +app.post("/thoughts", (req, res) => { + res.send("Hello Technigo!"); +}); + +app.post("/thoughts/:postId/like", (req, res) => { + res.send("Hello Technigo!"); +}); // Start the server app.listen(port, () => { - console.log(`Server running on http://localhost:${port}`) -}) + console.log(`Server running on http://localhost:${port}`); +}); From aaff82f2f157281e5c05fa1070090ad34289ce8d Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Sun, 15 Jun 2025 16:57:36 +0200 Subject: [PATCH 02/17] adding a thought written by the user --- package.json | 1 + server.js | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index bf25bb6..af9782a 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@babel/preset-env": "^7.16.11", "cors": "^2.8.5", "express": "^4.17.3", + "moment": "^2.30.1", "nodemon": "^3.0.1" } } diff --git a/server.js b/server.js index 58e693f..68d29db 100644 --- a/server.js +++ b/server.js @@ -1,6 +1,9 @@ import cors from "cors"; import express from "express"; import data from "./data.json"; +import crypto from "crypto"; +import moment from "moment"; +import { error } from "console"; // Defines the port the app will run on. Defaults to 8080, but can be overridden // when starting the server. Example command to overwrite PORT env variable value: @@ -21,6 +24,7 @@ app.get("/thoughts", (req, res) => { res.json(data); }); +//sending a single thought app.get("/thoughts/:thoughtId", (req, res) => { const id = req.params.thoughtId; const post = data.filter((item) => { @@ -32,9 +36,33 @@ app.get("/thoughts/:thoughtId", (req, res) => { res.json(post[0]); }); -// new thought +// accepting/ adding a new thought app.post("/thoughts", (req, res) => { - res.send("Hello Technigo!"); + const note = req.body.message; + + if (!note) { + res.status(400).send({ error: "Could not save thought. Message missing" }); + return; + } + + if (note.length < 5) { + res.status(400).send({ error: "Text is shorter than minimum allowed lenght of 5" }); + return; + } + + const id = crypto.randomBytes(12).toString("hex"); + const date = moment().format(); + + const thought = { + _id: id, + message: note, + hearts: 0, + createdAt: date, + __v: 0, + }; + + data.push(thought); + res.status(201).send(thought); }); app.post("/thoughts/:postId/like", (req, res) => { From 025b3c0ffce799c8c5d4e216d9d713e86f0ce617 Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Sun, 15 Jun 2025 17:08:47 +0200 Subject: [PATCH 03/17] liking a thought with a given ID --- server.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index 68d29db..d534541 100644 --- a/server.js +++ b/server.js @@ -46,7 +46,9 @@ app.post("/thoughts", (req, res) => { } if (note.length < 5) { - res.status(400).send({ error: "Text is shorter than minimum allowed lenght of 5" }); + res + .status(400) + .send({ error: "Text is shorter than minimum allowed lenght of 5" }); return; } @@ -65,8 +67,17 @@ app.post("/thoughts", (req, res) => { res.status(201).send(thought); }); -app.post("/thoughts/:postId/like", (req, res) => { - res.send("Hello Technigo!"); +//liking a thought with a given ID +app.post("/thoughts/:thoughtId/like", (req, res) => { + const id = req.params.thoughtId; + const post = data.filter((item) => { + return item._id === id; + }); + if (post.length === 0) { + res.status(404).json({ error: "Thought not found" }); + } + post[0].hearts = post[0].hearts + 1; + res.json(post[0]); }); // Start the server From 6e713fa533880b499be13d36a6ab86927355969d Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Sun, 15 Jun 2025 17:18:58 +0200 Subject: [PATCH 04/17] change to put new thoughts at the beginning --- server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.js b/server.js index d534541..3c6e538 100644 --- a/server.js +++ b/server.js @@ -63,7 +63,7 @@ app.post("/thoughts", (req, res) => { __v: 0, }; - data.push(thought); + data.unshift(thought); res.status(201).send(thought); }); From 5b1ea6dd4737dee348d7e32cea83e30568e1af74 Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Sun, 15 Jun 2025 19:31:04 +0200 Subject: [PATCH 05/17] stage one completed --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 0f9f073..976f342 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,11 @@ Install dependencies with `npm install`, then start the server by running `npm r ## View it live Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. + +# Project has been developed in three steps + +## First stage + +- API endpoints for creating, listing and liking thoughts to work with the existing Happy Thoughts App +- work with static data + From a13153d02173708afdba21354ab95d1af4fe702d Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Sun, 15 Jun 2025 20:41:37 +0200 Subject: [PATCH 06/17] added dotenv and mongoose --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index af9782a..eaa4d83 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,10 @@ "@babel/node": "^7.16.8", "@babel/preset-env": "^7.16.11", "cors": "^2.8.5", + "dotenv": "^16.5.0", "express": "^4.17.3", "moment": "^2.30.1", + "mongoose": "^8.15.2", "nodemon": "^3.0.1" } } From 98a89100435116e845e34256a297fb4cdb314138 Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Sun, 15 Jun 2025 20:42:14 +0200 Subject: [PATCH 07/17] boilerplate for mongo connection --- server.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/server.js b/server.js index 3c6e538..0135002 100644 --- a/server.js +++ b/server.js @@ -4,6 +4,37 @@ import data from "./data.json"; import crypto from "crypto"; import moment from "moment"; import { error } from "console"; +import dotenv from "dotenv"; +import mongoose from "mongoose"; + +dotenv.config(); + +const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/thoughts"; +mongoose.connect(mongoUrl); + +const thoughtSchema = new mongoose.Schema({ + _id: { + type: String, + default: () => { + return crypto.randomBytes(12).toString("hex"); + }, + }, + message: String, + hearts: { + type: Number, + default: 0, + }, + createdAt: { + type: Date, + default: Date.now, + }, + __v: { + type: Number, + default: 0, + }, +}); + +const Thought = mongoose.model("Thought", thoughtSchema); // Defines the port the app will run on. Defaults to 8080, but can be overridden // when starting the server. Example command to overwrite PORT env variable value: From 29ffa2be2280e8341cad2a4b40f182fc5b80cf13 Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Sun, 15 Jun 2025 23:14:32 +0200 Subject: [PATCH 08/17] replaced API with mongo queries --- server.js | 51 +++++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/server.js b/server.js index 0135002..0e45399 100644 --- a/server.js +++ b/server.js @@ -1,9 +1,6 @@ import cors from "cors"; import express from "express"; -import data from "./data.json"; import crypto from "crypto"; -import moment from "moment"; -import { error } from "console"; import dotenv from "dotenv"; import mongoose from "mongoose"; @@ -51,15 +48,16 @@ app.get("/", (req, res) => { res.send("Hello Technigo!"); }); -app.get("/thoughts", (req, res) => { - res.json(data); +app.get("/thoughts", async (req, res) => { + const thoughts = await Thought.find(); + res.json(thoughts); }); //sending a single thought -app.get("/thoughts/:thoughtId", (req, res) => { +app.get("/thoughts/:thoughtId", async (req, res) => { const id = req.params.thoughtId; - const post = data.filter((item) => { - return item._id === id; + const post = await Thought.find({ + _id: id, }); if (post.length === 0) { res.status(404).json({ error: "Thought not found" }); @@ -68,7 +66,7 @@ app.get("/thoughts/:thoughtId", (req, res) => { }); // accepting/ adding a new thought -app.post("/thoughts", (req, res) => { +app.post("/thoughts", async (req, res) => { const note = req.body.message; if (!note) { @@ -83,32 +81,29 @@ app.post("/thoughts", (req, res) => { return; } - const id = crypto.randomBytes(12).toString("hex"); - const date = moment().format(); - - const thought = { - _id: id, + const thought = new Thought({ message: note, - hearts: 0, - createdAt: date, - __v: 0, - }; - - data.unshift(thought); + }); + await thought.save(); res.status(201).send(thought); }); //liking a thought with a given ID -app.post("/thoughts/:thoughtId/like", (req, res) => { +app.post("/thoughts/:thoughtId/like", async (req, res) => { const id = req.params.thoughtId; - const post = data.filter((item) => { - return item._id === id; - }); - if (post.length === 0) { - res.status(404).json({ error: "Thought not found" }); + try { + const likedThought = await Thought.findOneAndUpdate( + { _id: id }, + { $inc: { hearts: 1 } }, + { new: true } + ); + + res.status(201).json(likedThought); + } catch (error) { + res.status(404).json({ + error: "Thought not found", + }); } - post[0].hearts = post[0].hearts + 1; - res.json(post[0]); }); // Start the server From aad9dffcee8088209d2048d7c8bb7918f9dca035 Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Sun, 15 Jun 2025 23:15:01 +0200 Subject: [PATCH 09/17] deleted temp data --- data.json | 121 ------------------------------------------------------ 1 file changed, 121 deletions(-) delete mode 100644 data.json diff --git a/data.json b/data.json deleted file mode 100644 index a2c844f..0000000 --- a/data.json +++ /dev/null @@ -1,121 +0,0 @@ -[ - { - "_id": "682bab8c12155b00101732ce", - "message": "Berlin baby", - "hearts": 37, - "createdAt": "2025-05-19T22:07:08.999Z", - "__v": 0 - }, - { - "_id": "682e53cc4fddf50010bbe739", - "message": "My family!", - "hearts": 0, - "createdAt": "2025-05-22T22:29:32.232Z", - "__v": 0 - }, - { - "_id": "682e4f844fddf50010bbe738", - "message": "The smell of coffee in the morning....", - "hearts": 23, - "createdAt": "2025-05-22T22:11:16.075Z", - "__v": 0 - }, - { - "_id": "682e48bf4fddf50010bbe737", - "message": "Newly washed bedlinen, kids that sleeps through the night.. FINGERS CROSSED 🤞🏼\n", - "hearts": 6, - "createdAt": "2025-05-21T21:42:23.862Z", - "__v": 0 - }, - { - "_id": "682e45804fddf50010bbe736", - "message": "I am happy that I feel healthy and have energy again", - "hearts": 13, - "createdAt": "2025-05-21T21:28:32.196Z", - "__v": 0 - }, - { - "_id": "682e23fecf615800105107aa", - "message": "cold beer", - "hearts": 2, - "createdAt": "2025-05-21T19:05:34.113Z", - "__v": 0 - }, - { - "_id": "682e22aecf615800105107a9", - "message": "My friend is visiting this weekend! <3", - "hearts": 6, - "createdAt": "2025-05-21T18:59:58.121Z", - "__v": 0 - }, - { - "_id": "682cec1b17487d0010a298b6", - "message": "A god joke: \nWhy did the scarecrow win an award?\nBecause he was outstanding in his field!", - "hearts": 12, - "createdAt": "2025-05-20T20:54:51.082Z", - "__v": 0 - }, - { - "_id": "682cebbe17487d0010a298b5", - "message": "Tacos and tequila🌮🍹", - "hearts": 2, - "createdAt": "2025-05-19T20:53:18.899Z", - "__v": 0 - }, - { - "_id": "682ceb5617487d0010a298b4", - "message": "Netflix and late night ice-cream🍦", - "hearts": 1, - "createdAt": "2025-05-18T20:51:34.494Z", - "__v": 0 - }, - { - "_id": "682c99ba3bff2d0010f5d44e", - "message": "Summer is coming...", - "hearts": 2, - "createdAt": "2025-05-20T15:03:22.379Z", - "__v": 0 - }, - { - "_id": "682c706c951f7a0017130024", - "message": "Exercise? I thought you said extra fries! 🍟😂", - "hearts": 14, - "createdAt": "2025-05-20T12:07:08.185Z", - "__v": 0 - }, - { - "_id": "682c6fe1951f7a0017130023", - "message": "I’m on a seafood diet. I see food, and I eat it.", - "hearts": 4, - "createdAt": "2025-05-20T12:04:49.978Z", - "__v": 0 - }, - { - "_id": "682c6f0e951f7a0017130022", - "message": "Cute monkeys🐒", - "hearts": 2, - "createdAt": "2025-05-20T12:01:18.308Z", - "__v": 0 - }, - { - "_id": "682c6e65951f7a0017130021", - "message": "The weather is nice!", - "hearts": 0, - "createdAt": "2025-05-20T11:58:29.662Z", - "__v": 0 - }, - { - "_id": "682bfdb4270ca300105af221", - "message": "good vibes and good things", - "hearts": 3, - "createdAt": "2025-05-20T03:57:40.322Z", - "__v": 0 - }, - { - "_id": "682bab8c12155b00101732ce", - "message": "Berlin baby", - "hearts": 37, - "createdAt": "2025-05-19T22:07:08.999Z", - "__v": 0 - } -] \ No newline at end of file From bb4afd8ff8cf2842e48da3b5b8f540173f2fc137 Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Sun, 15 Jun 2025 23:16:26 +0200 Subject: [PATCH 10/17] stage two completed --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 976f342..68a4f97 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,6 @@ Every project should be deployed somewhere. Be sure to include the link to the d - API endpoints for creating, listing and liking thoughts to work with the existing Happy Thoughts App - work with static data +## Second stage +- API uses Mongo DB for storing thoughts +- Data is now persistent \ No newline at end of file From 1bbacbad8b9546e4d7d214558f9e7689ea2f7ebd Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Mon, 16 Jun 2025 22:29:39 +0200 Subject: [PATCH 11/17] comments to first two stages --- server.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server.js b/server.js index 0e45399..d634d4b 100644 --- a/server.js +++ b/server.js @@ -4,11 +4,14 @@ import crypto from "crypto"; import dotenv from "dotenv"; import mongoose from "mongoose"; +// loading environment from env file dotenv.config(); +//connecting to MondoDB const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/thoughts"; mongoose.connect(mongoUrl); +//data model for Thoughts const thoughtSchema = new mongoose.Schema({ _id: { type: String, @@ -48,6 +51,7 @@ app.get("/", (req, res) => { res.send("Hello Technigo!"); }); +//listing all the thoughts app.get("/thoughts", async (req, res) => { const thoughts = await Thought.find(); res.json(thoughts); @@ -106,7 +110,7 @@ app.post("/thoughts/:thoughtId/like", async (req, res) => { } }); -// Start the server +// Starting the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); }); From 1c73fccbb752f053c6ed510518f7c07361cb2fdd Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Tue, 17 Jun 2025 00:01:41 +0200 Subject: [PATCH 12/17] deployed to onrender --- pull_request_template.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pull_request_template.md b/pull_request_template.md index fb9fdc3..c6ca86d 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -1 +1,4 @@ -Please include your Render link here. \ No newline at end of file +Please include your Render link here. + +Here you go: +https://js-project-api-vj6h.onrender.com \ No newline at end of file From cbb979d645d3adeade4248ab26610b8737f71e57 Mon Sep 17 00:00:00 2001 From: Kasssiiii Date: Tue, 17 Jun 2025 22:30:02 +0200 Subject: [PATCH 13/17] week3 --- package.json | 1 + server.js | 101 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index eaa4d83..36a0648 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@babel/core": "^7.17.9", "@babel/node": "^7.16.8", "@babel/preset-env": "^7.16.11", + "bcryptjs": "^3.0.2", "cors": "^2.8.5", "dotenv": "^16.5.0", "express": "^4.17.3", diff --git a/server.js b/server.js index d634d4b..dd0f66c 100644 --- a/server.js +++ b/server.js @@ -1,10 +1,11 @@ import cors from "cors"; import express from "express"; import crypto from "crypto"; +import bcrypt from "bcryptjs"; import dotenv from "dotenv"; import mongoose from "mongoose"; -// loading environment from env file +// loading environment from env file dotenv.config(); //connecting to MondoDB @@ -15,11 +16,15 @@ mongoose.connect(mongoUrl); const thoughtSchema = new mongoose.Schema({ _id: { type: String, + unique: true, default: () => { return crypto.randomBytes(12).toString("hex"); }, }, - message: String, + message: { + type: String, + require: true, + }, hearts: { type: Number, default: 0, @@ -36,6 +41,26 @@ const thoughtSchema = new mongoose.Schema({ const Thought = mongoose.model("Thought", thoughtSchema); +//user schema +const User = mongoose.model("User", { + name: { + type: String, + unique: true, + }, + password: { + type: String, + required: true, + }, + accessToken: { + type: String, + default: () => crypto.randomBytes(128).toString("hex"), + }, +}); + +//example of a user +//const user = new User({name: "Mary", password: bcrypt.hashSync("Maryspassword")}); +//user.save(); + // Defines the port the app will run on. Defaults to 8080, but can be overridden // when starting the server. Example command to overwrite PORT env variable value: // PORT=9000 npm start @@ -46,6 +71,57 @@ const app = express(); app.use(cors()); app.use(express.json()); +//endpoint for creating a user +app.post("/users", async (req, res) => { + const userName = req.body.user; + const password = req.body.password; + if (!userName || !password) { + res + .status(400) + .send({ error: "Could not create user. User or password missing" }); + return; + } + try { + const user = new User({ + name: userName, + password: bcrypt.hashSync(password), + }); + await user.save(); + res.status(201).send(user); + } catch (error) { + res.status(400).send({ error: error }); + } +}); + +//endpoint for logging +app.post("/users/:userName", async (req, res) => { + const userName = req.params.userName; + const passEncrypted = req.body.password; + if (!passEncrypted) { + res.json({ error: "password missing in the body of request" }); + } + const user = await User.findOne({ name: userName }); + + if (user && bcrypt.compareSync(passEncrypted, user.password)) { + //success + res.json({ userName: user.name, accessToken: user.accessToken }); + } else { + //failure + res.json({ notFound: true }); + } +}); + +///authenticating middleware +const authenticateUser = async (req, res, next) => { + const user = await User.findOne({ accessToken: req.header("Authorization") }); + if (user) { + req.user = user; + next(); + } else { + res.status(401).json({ error: "User logged out" }); + } +}; + // Start defining your routes here app.get("/", (req, res) => { res.send("Hello Technigo!"); @@ -53,7 +129,7 @@ app.get("/", (req, res) => { //listing all the thoughts app.get("/thoughts", async (req, res) => { - const thoughts = await Thought.find(); + const thoughts = await Thought.find().sort({createdAt: -1}).limit(20); res.json(thoughts); }); @@ -69,7 +145,23 @@ app.get("/thoughts/:thoughtId", async (req, res) => { res.json(post[0]); }); +//removing a single thought +app.delete("/thoughts/:thoughtId", authenticateUser); +app.delete("/thoughts/:thoughtId", async (req, res) => { + const id = req.params.thoughtId; + const result = await Thought.deleteOne({ + _id: id, + }); + if (result.deletedCount === 0) { + res.status(404).json({ error: "Thought not found" }); + } + res.json(result); +}); + // accepting/ adding a new thought + +app.post("/thoughts", authenticateUser); + app.post("/thoughts", async (req, res) => { const note = req.body.message; @@ -93,6 +185,9 @@ app.post("/thoughts", async (req, res) => { }); //liking a thought with a given ID + +app.post("/thoughts/:thoughtId/like", authenticateUser); + app.post("/thoughts/:thoughtId/like", async (req, res) => { const id = req.params.thoughtId; try { From 6f845cc82d28b45a2c9b1050b2bed8cc86fd2abf Mon Sep 17 00:00:00 2001 From: Kasssiii Date: Fri, 15 Aug 2025 15:39:24 +0200 Subject: [PATCH 14/17] added editing a thought with authorization --- server.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/server.js b/server.js index dd0f66c..b2dfaaa 100644 --- a/server.js +++ b/server.js @@ -158,6 +158,25 @@ app.delete("/thoughts/:thoughtId", async (req, res) => { res.json(result); }); +// editing a thought +app.patch('/thoughts/:thoughtId', authenticateUser); +app.patch('/thoughts/:thoughtId', async (req, res) => { + console.log("patching a post with id" + req.params.thoughtId); + try { + const edited = await Thought.findByIdAndUpdate( + req.params.thoughtId, + { message: req.body.message }, + { new: true, runValidators: true } + ) + res.json(edited) + } catch (error) { + res.status(404).json({ + error: "Thought not found", + }); + } +}) + + // accepting/ adding a new thought app.post("/thoughts", authenticateUser); From 500c0fbaef2c0c54e047e0b9f74ffddf62f7d548 Mon Sep 17 00:00:00 2001 From: Kasssiii Date: Fri, 15 Aug 2025 17:52:58 +0200 Subject: [PATCH 15/17] added owning a post and editing your post only --- server.js | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/server.js b/server.js index b2dfaaa..b440058 100644 --- a/server.js +++ b/server.js @@ -25,6 +25,10 @@ const thoughtSchema = new mongoose.Schema({ type: String, require: true, }, + userName: { + type: String, + require: true, + }, hearts: { type: Number, default: 0, @@ -161,17 +165,23 @@ app.delete("/thoughts/:thoughtId", async (req, res) => { // editing a thought app.patch('/thoughts/:thoughtId', authenticateUser); app.patch('/thoughts/:thoughtId', async (req, res) => { - console.log("patching a post with id" + req.params.thoughtId); try { - const edited = await Thought.findByIdAndUpdate( - req.params.thoughtId, + const edited = await Thought.findOneAndUpdate( + { _id: req.params.thoughtId, userName: req.user.name }, { message: req.body.message }, { new: true, runValidators: true } ) - res.json(edited) + if (!edited) { + res.status(404).json({ + error: "Thought not found, or you are not the owner of this thought", + }); + } + else { + res.json(edited) + } } catch (error) { res.status(404).json({ - error: "Thought not found", + error: "Thought not found, or you are not the owner of this thought", }); } }) @@ -180,7 +190,6 @@ app.patch('/thoughts/:thoughtId', async (req, res) => { // accepting/ adding a new thought app.post("/thoughts", authenticateUser); - app.post("/thoughts", async (req, res) => { const note = req.body.message; @@ -198,15 +207,13 @@ app.post("/thoughts", async (req, res) => { const thought = new Thought({ message: note, + userName: req.user.name }); await thought.save(); res.status(201).send(thought); }); //liking a thought with a given ID - -app.post("/thoughts/:thoughtId/like", authenticateUser); - app.post("/thoughts/:thoughtId/like", async (req, res) => { const id = req.params.thoughtId; try { From 465d5e92b53416839fb85e90c4625d3b55feb5f5 Mon Sep 17 00:00:00 2001 From: Kasssiii Date: Sat, 16 Aug 2025 13:12:47 +0200 Subject: [PATCH 16/17] sent proper error message when logging in --- server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.js b/server.js index b440058..798bed7 100644 --- a/server.js +++ b/server.js @@ -111,7 +111,7 @@ app.post("/users/:userName", async (req, res) => { res.json({ userName: user.name, accessToken: user.accessToken }); } else { //failure - res.json({ notFound: true }); + res.status(401).json({ notFound: true }); } }); From 2982a0a4b98cc9f99cc9a2a6ae4f6c5b646d1b36 Mon Sep 17 00:00:00 2001 From: Kasssiii Date: Sun, 17 Aug 2025 14:27:57 +0200 Subject: [PATCH 17/17] updated readme with stage 3 implementation --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 68a4f97..ef495ef 100644 --- a/README.md +++ b/README.md @@ -19,4 +19,9 @@ Every project should be deployed somewhere. Be sure to include the link to the d ## Second stage - API uses Mongo DB for storing thoughts -- Data is now persistent \ No newline at end of file +- Data is now persistent + +## Third stage +- Support for user authentication +- Post creation, edition and deletion now require authentication +- deployed on onRender: https://js-project-api-vj6h.onrender.com