diff --git a/backend/middleware/authenticateUser.js b/backend/middleware/authenticateUser.js new file mode 100644 index 000000000..33d5a91cd --- /dev/null +++ b/backend/middleware/authenticateUser.js @@ -0,0 +1,21 @@ +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) + console.log('Token:', token); + console.log('Dekrypterad token:', decoded); + 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/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/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..9acfeaf05 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,10 +1,12 @@ { "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", - "dev": "nodemon server.js --exec babel-node" + "start": "node server.js", + "dev": "nodemon --env-file=.env server.js --exec babel-node" }, "author": "", "license": "ISC", @@ -12,8 +14,12 @@ "@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", + "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 new file mode 100644 index 000000000..580d6c2f5 --- /dev/null +++ b/backend/routes/Auth.js @@ -0,0 +1,78 @@ +import express from "express" +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() + +authRouter.post("/signup", async (req, res) => { + try { + const { username, password } = req.body + const user = new User({ username, password: password }) + await user.save() + res.status(201).json({ message: "User registered successfully" }) + } catch (error) { + res.status(500).json({ error: error.message }) + } +}) + +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 + 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" }) + } + 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("/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 diff --git a/backend/server.js b/backend/server.js index dfe86fb8e..1d55e999f 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,27 +1,33 @@ -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()) -// Add middlewares to enable cors and json body parsing -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") +}) -// 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) diff --git a/frontend/package.json b/frontend/package.json index e9c95b79f..f616712d4 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -4,14 +4,19 @@ "version": "0.0.0", "type": "module", "scripts": { + "start": "vite", "dev": "vite", "build": "vite build", "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", "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}
} +