From 6f7d3e5922d1b4c77c754fb6b1da02abab1baf82 Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 13:20:58 +0200 Subject: [PATCH 01/13] backend --- backend/middleware/authenticateUser.js | 19 ++++++++++ backend/model/User.js | 23 ++++++++++++ backend/package.json | 6 +++- backend/routes/Auth.js | 43 ++++++++++++++++++++++ backend/server.js | 49 +++++++++++++++----------- backend/utils/generateSecretKey.js | 4 +++ 6 files changed, 123 insertions(+), 21 deletions(-) create mode 100644 backend/middleware/authenticateUser.js create mode 100644 backend/model/User.js create mode 100644 backend/routes/Auth.js create mode 100644 backend/utils/generateSecretKey.js diff --git a/backend/middleware/authenticateUser.js b/backend/middleware/authenticateUser.js new file mode 100644 index 000000000..d1e7b100b --- /dev/null +++ b/backend/middleware/authenticateUser.js @@ -0,0 +1,19 @@ +import jwt from "jsonwebtoken" +import User from "../model/User.js" + +const authenticateUser = async (req, res, next) => { + try { + const token = req.header("Authorization").replace("Bearer ", "") + const decoded = jwt.verify(token, process.env.JWT_SECRET) + const user = await User.findOne({ _id: decoded.userId }) + if (!user) { + throw new Error() + } + req.user = user + next() + } catch (error) { + res.status(401).json({ error: "Please authenticate" }) + } +} + +export default authenticateUser diff --git a/backend/model/User.js b/backend/model/User.js new file mode 100644 index 000000000..d2c760c85 --- /dev/null +++ b/backend/model/User.js @@ -0,0 +1,23 @@ +import mongoose from 'mongoose'; +import bcrypt from 'bcryptjs'; + +const userSchema = new mongoose.Schema({ + username: { type: String, required: true, unique: true }, + password: { type: String, required: true } +}); + +userSchema.pre('save', async function(next) { + const user = this; + if (!user.isModified('password')) return next(); + try { + const hash = await bcrypt.hash(user.password, 10); + user.password = hash; + next(); + } catch (error) { + return next(error); + } +}); + +const User = mongoose.model('User', userSchema); + +export default User; \ No newline at end of file diff --git a/backend/package.json b/backend/package.json index 8de5c4ce0..33bd494b3 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,9 +1,11 @@ { "name": "project-auth-backend", "version": "1.0.0", + "main": "server.js", + "type": "module", "description": "Starter project to get up and running with express quickly", "scripts": { - "start": "babel-node server.js", + "start": "node --env-file=.env server.js", "dev": "nodemon server.js --exec babel-node" }, "author": "", @@ -14,6 +16,8 @@ "@babel/preset-env": "^7.16.11", "cors": "^2.8.5", "express": "^4.17.3", + "express-list-endpoints": "^7.1.0", + "jsonwebtoken": "^9.0.2", "mongoose": "^8.0.0", "nodemon": "^3.0.1" } diff --git a/backend/routes/Auth.js b/backend/routes/Auth.js new file mode 100644 index 000000000..fe405c50a --- /dev/null +++ b/backend/routes/Auth.js @@ -0,0 +1,43 @@ +import express from "express" +import bcrypt from "bcryptjs" +import jwt from "jsonwebtoken" +import User from "../model/User.js" +import authenticateUser from "../middleware/authenticateUser.js" + +const authRouter = express.Router() + +authRouter.post("/signup", async (req, res) => { + try { + const { username, password } = req.body + const hashedPassword = await bcrypt.hash(password, 10) + const user = new User({ username, password: hashedPassword }) + await user.save() + res.status(201).json({ message: "User registered successfully" }) + } catch (error) { + res.status(500).json({ error: error.message }) + } +}) + +authRouter.post("/login", async (req, res) => { + try { + const { username, password } = req.body + const user = await User.findOne({ username }) + if (!user) { + return res.status(401).json({ error: "Invalid username or password" }) + } + const isPasswordValid = await bcrypt.compare(password, user.password) + if (!isPasswordValid) { + return res.status(401).json({ error: "Invalid username or password" }) + } + const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET) + res.status(200).json({ token }) + } catch (error) { + res.status(500).json({ error: error.message }) + } +}) + +authRouter.get("/thoughts", authenticateUser, (req, res) => { + res.send("Authenticated content") +}) + +export default authRouter diff --git a/backend/server.js b/backend/server.js index dfe86fb8e..c197993e8 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,27 +1,36 @@ -import cors from "cors"; -import express from "express"; -import mongoose from "mongoose"; +import express from "express" +import mongoose from "mongoose" +import cors from "cors" +import listEndpoints from "express-list-endpoints" +import authRouter from "./routes/auth.js" -const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo"; -mongoose.connect(mongoUrl); -mongoose.Promise = Promise; +const app = express() +const port = process.env.SERVER_PORT || 3001 -// 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(); +app.use(cors()) +app.use(express.json()) + + +mongoose.connect(`mongodb://${process.env.DB_HOST}:${process.env.DB_PORT}`, { + dbName: process.env.DB_NAME, + user: process.env.DB_USER, + pass: process.env.DB_PASS, +}) +const db = mongoose.connection +db.on("error", console.error.bind(console, "Anslutningsfel:")) +db.once("open", () => { + console.log("Ansluten till databasen") +}) -// Add middlewares to enable cors and json body parsing -app.use(cors()); -app.use(express.json()); -// Start defining your routes here app.get("/", (req, res) => { - res.send("Hello Technigo!"); -}); + const endpoints = listEndpoints(app) + res.json(endpoints) +}) + + +app.use(authRouter) -// Start the server app.listen(port, () => { - console.log(`Server running on http://localhost:${port}`); -}); + console.log(`Chattservern lyssnar på port ${port}`) +}) diff --git a/backend/utils/generateSecretKey.js b/backend/utils/generateSecretKey.js new file mode 100644 index 000000000..07e6bcd32 --- /dev/null +++ b/backend/utils/generateSecretKey.js @@ -0,0 +1,4 @@ +import crypto from "crypto" + +const jwtSecret = crypto.randomBytes(32).toString("hex") +console.log(jwtSecret) From 0a45fc6d9c73a21d02c855e04c704721fe75f6a1 Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 13:28:22 +0200 Subject: [PATCH 02/13] backend --- backend/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/package.json b/backend/package.json index 33bd494b3..0cc685bf2 100644 --- a/backend/package.json +++ b/backend/package.json @@ -5,8 +5,8 @@ "type": "module", "description": "Starter project to get up and running with express quickly", "scripts": { - "start": "node --env-file=.env server.js", - "dev": "nodemon server.js --exec babel-node" + "start": "node server.js", + "dev": "nodemon --env-file=.env server.js --exec babel-node" }, "author": "", "license": "ISC", From 62aa656d77c7d0d43155934b2fca92ca9392f83f Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 13:37:14 +0200 Subject: [PATCH 03/13] backend --- backend/server.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/server.js b/backend/server.js index c197993e8..c947d2bd7 100644 --- a/backend/server.js +++ b/backend/server.js @@ -10,7 +10,6 @@ const port = process.env.SERVER_PORT || 3001 app.use(cors()) app.use(express.json()) - mongoose.connect(`mongodb://${process.env.DB_HOST}:${process.env.DB_PORT}`, { dbName: process.env.DB_NAME, user: process.env.DB_USER, @@ -22,13 +21,11 @@ db.once("open", () => { console.log("Ansluten till databasen") }) - app.get("/", (req, res) => { const endpoints = listEndpoints(app) res.json(endpoints) }) - app.use(authRouter) app.listen(port, () => { From 9e2f65665b5b10a5ebbbedfeceaa76f941108947 Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 13:53:42 +0200 Subject: [PATCH 04/13] backend --- backend/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/server.js b/backend/server.js index c947d2bd7..2ed0136f1 100644 --- a/backend/server.js +++ b/backend/server.js @@ -26,7 +26,7 @@ app.get("/", (req, res) => { res.json(endpoints) }) -app.use(authRouter) +app.use("/", authRouter) app.listen(port, () => { console.log(`Chattservern lyssnar på port ${port}`) From 60b7040b92f79956b06b61c76c19776bef3ae883 Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 14:03:33 +0200 Subject: [PATCH 05/13] backend --- backend/server.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/server.js b/backend/server.js index 2ed0136f1..1d55e999f 100644 --- a/backend/server.js +++ b/backend/server.js @@ -2,7 +2,7 @@ import express from "express" import mongoose from "mongoose" import cors from "cors" import listEndpoints from "express-list-endpoints" -import authRouter from "./routes/auth.js" +import authRouter from "./routes/Auth.js" const app = express() const port = process.env.SERVER_PORT || 3001 @@ -26,7 +26,7 @@ app.get("/", (req, res) => { res.json(endpoints) }) -app.use("/", authRouter) +app.use(authRouter) app.listen(port, () => { console.log(`Chattservern lyssnar på port ${port}`) From 699a711092d9092bbd779eeb7f5b5f1d7a548882 Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 14:07:03 +0200 Subject: [PATCH 06/13] backend --- backend/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/package.json b/backend/package.json index 0cc685bf2..602d0fa65 100644 --- a/backend/package.json +++ b/backend/package.json @@ -14,6 +14,7 @@ "@babel/core": "^7.17.9", "@babel/node": "^7.16.8", "@babel/preset-env": "^7.16.11", + "bcryptjs": "^2.4.3", "cors": "^2.8.5", "express": "^4.17.3", "express-list-endpoints": "^7.1.0", From 9dc6f094726de7499b4c3e8f0b0840cf73880a02 Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 14:51:10 +0200 Subject: [PATCH 07/13] backend --- backend/routes/Auth.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/backend/routes/Auth.js b/backend/routes/Auth.js index fe405c50a..12e029f50 100644 --- a/backend/routes/Auth.js +++ b/backend/routes/Auth.js @@ -18,6 +18,15 @@ authRouter.post("/signup", async (req, res) => { } }) +authRouter.get("/signup", async (req, res) => { + try { + const users = await User.find() + res.status(200).json(users) + } catch (error) { + res.status(500).json({ error: error.message }) + } +}) + authRouter.post("/login", async (req, res) => { try { const { username, password } = req.body From 08e279ed272794f66e687d31d545d2e7920826b5 Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 15:27:34 +0200 Subject: [PATCH 08/13] backend --- backend/package.json | 1 + backend/routes/Auth.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/backend/package.json b/backend/package.json index 602d0fa65..9acfeaf05 100644 --- a/backend/package.json +++ b/backend/package.json @@ -19,6 +19,7 @@ "express": "^4.17.3", "express-list-endpoints": "^7.1.0", "jsonwebtoken": "^9.0.2", + "jwt-decode": "^4.0.0", "mongoose": "^8.0.0", "nodemon": "^3.0.1" } diff --git a/backend/routes/Auth.js b/backend/routes/Auth.js index 12e029f50..1b87dec54 100644 --- a/backend/routes/Auth.js +++ b/backend/routes/Auth.js @@ -45,6 +45,10 @@ authRouter.post("/login", async (req, res) => { } }) +authRouter.get("/login", (req, res) => { + res.status(404).send("Not found") +}) + authRouter.get("/thoughts", authenticateUser, (req, res) => { res.send("Authenticated content") }) From 9186e2eea4cf5305502cecbb419c60ffbbc4b2b8 Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 15:47:51 +0200 Subject: [PATCH 09/13] backend --- backend/middleware/authenticateUser.js | 2 ++ backend/routes/Auth.js | 7 +++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/middleware/authenticateUser.js b/backend/middleware/authenticateUser.js index d1e7b100b..33d5a91cd 100644 --- a/backend/middleware/authenticateUser.js +++ b/backend/middleware/authenticateUser.js @@ -5,6 +5,8 @@ const authenticateUser = async (req, res, next) => { try { const token = req.header("Authorization").replace("Bearer ", "") const decoded = jwt.verify(token, process.env.JWT_SECRET) + console.log('Token:', token); + console.log('Dekrypterad token:', decoded); const user = await User.findOne({ _id: decoded.userId }) if (!user) { throw new Error() diff --git a/backend/routes/Auth.js b/backend/routes/Auth.js index 1b87dec54..52a70f023 100644 --- a/backend/routes/Auth.js +++ b/backend/routes/Auth.js @@ -31,6 +31,8 @@ authRouter.post("/login", async (req, res) => { try { const { username, password } = req.body const user = await User.findOne({ username }) + console.log("Inkommande lösenord:", password) + console.log("Hashat lösenord i databasen:", user.password) if (!user) { return res.status(401).json({ error: "Invalid username or password" }) } @@ -39,16 +41,13 @@ authRouter.post("/login", async (req, res) => { return res.status(401).json({ error: "Invalid username or password" }) } const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET) + console.log("Genererat JWT-token:", token) res.status(200).json({ token }) } catch (error) { res.status(500).json({ error: error.message }) } }) -authRouter.get("/login", (req, res) => { - res.status(404).send("Not found") -}) - authRouter.get("/thoughts", authenticateUser, (req, res) => { res.send("Authenticated content") }) From 0d6fcfa1cbbaea26fb26361e4d93a666a48368aa Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 16:08:42 +0200 Subject: [PATCH 10/13] backend --- backend/routes/Auth.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/routes/Auth.js b/backend/routes/Auth.js index 52a70f023..82a9a52e5 100644 --- a/backend/routes/Auth.js +++ b/backend/routes/Auth.js @@ -9,8 +9,7 @@ const authRouter = express.Router() authRouter.post("/signup", async (req, res) => { try { const { username, password } = req.body - const hashedPassword = await bcrypt.hash(password, 10) - const user = new User({ username, password: hashedPassword }) + const user = new User({ username, password: password }) await user.save() res.status(201).json({ message: "User registered successfully" }) } catch (error) { @@ -30,13 +29,17 @@ authRouter.get("/signup", async (req, res) => { authRouter.post("/login", async (req, res) => { try { const { username, password } = req.body + console.log(username) + console.log(password) const user = await User.findOne({ username }) + console.log(user) console.log("Inkommande lösenord:", password) console.log("Hashat lösenord i databasen:", user.password) if (!user) { return res.status(401).json({ error: "Invalid username or password" }) } const isPasswordValid = await bcrypt.compare(password, user.password) + console.log(isPasswordValid) if (!isPasswordValid) { return res.status(401).json({ error: "Invalid username or password" }) } From c880c3fc8bbaaf2232296ddd35f1c3b5f7bdf437 Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 16:42:03 +0200 Subject: [PATCH 11/13] backend --- backend/model/Thought.js | 10 ++++++++++ backend/routes/Auth.js | 24 ++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 backend/model/Thought.js diff --git a/backend/model/Thought.js b/backend/model/Thought.js new file mode 100644 index 000000000..924a482e7 --- /dev/null +++ b/backend/model/Thought.js @@ -0,0 +1,10 @@ +import mongoose from 'mongoose'; + +const thoughtSchema = new mongoose.Schema({ + text: { type: String, required: true }, + user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true } +}); + +const Thought = mongoose.model('Thought', thoughtSchema); + +export default Thought; diff --git a/backend/routes/Auth.js b/backend/routes/Auth.js index 82a9a52e5..580d6c2f5 100644 --- a/backend/routes/Auth.js +++ b/backend/routes/Auth.js @@ -3,6 +3,7 @@ import bcrypt from "bcryptjs" import jwt from "jsonwebtoken" import User from "../model/User.js" import authenticateUser from "../middleware/authenticateUser.js" +import Thought from "../model/Thought.js" const authRouter = express.Router() @@ -51,8 +52,27 @@ authRouter.post("/login", async (req, res) => { } }) -authRouter.get("/thoughts", authenticateUser, (req, res) => { - res.send("Authenticated content") +authRouter.get("/thoughts", authenticateUser, async (req, res) => { + try { + const userId = req.user._id + const userThoughts = await Thought.find({ user: userId }) + + res.status(200).json(userThoughts) + } catch (error) { + res.status(500).json({ error: error.message }) + } +}) + +authRouter.post("/thoughts", authenticateUser, async (req, res) => { + try { + const { thought } = req.body + const userId = req.user._id + const newThought = new Thought({ text: thought, user: userId }) + await newThought.save() + res.status(201).json({ message: "Thought saved successfully" }) + } catch (error) { + res.status(500).json({ error: error.message }) + } }) export default authRouter From f23da3aa05046d680855d535b1ffa4ea464974d8 Mon Sep 17 00:00:00 2001 From: Josephineoderland <153084500+Josephineoderland@users.noreply.github.com> Date: Wed, 22 May 2024 16:57:11 +0200 Subject: [PATCH 12/13] frontend --- frontend/package.json | 6 +- frontend/src/App.jsx | 26 ++++++++- frontend/src/components/Home.jsx | 20 +++++++ frontend/src/components/Login.jsx | 80 +++++++++++++++++++++++++++ frontend/src/components/Register.jsx | 44 +++++++++++++++ frontend/src/components/Thoughts.jsx | 82 ++++++++++++++++++++++++++++ frontend/src/context/AuthContext.jsx | 28 ++++++++++ frontend/src/context/authHelpers.jsx | 24 ++++++++ frontend/src/main.jsx | 2 +- 9 files changed, 307 insertions(+), 5 deletions(-) create mode 100644 frontend/src/components/Home.jsx create mode 100644 frontend/src/components/Login.jsx create mode 100644 frontend/src/components/Register.jsx create mode 100644 frontend/src/components/Thoughts.jsx create mode 100644 frontend/src/context/AuthContext.jsx create mode 100644 frontend/src/context/authHelpers.jsx diff --git a/frontend/package.json b/frontend/package.json index e9c95b79f..e971eb2e5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,8 +10,12 @@ "preview": "vite preview" }, "dependencies": { + "axios": "^1.7.2", + "jwt-decode": "^4.0.0", + "prop-types": "^15.8.1", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-router-dom": "^6.23.1" }, "devDependencies": { "@types/react": "^18.2.15", diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 1091d4310..b7976c6d7 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,3 +1,23 @@ -export const App = () => { - return
Please select an option:
+{error}
} +