From 6e18d4fe47fdc2a1b2566d7dd8e8f9c959689a92 Mon Sep 17 00:00:00 2001 From: Antonella Morittu <33493978+AntonellaMorittu@users.noreply.github.com> Date: Wed, 22 May 2024 14:57:16 +0200 Subject: [PATCH 01/36] Delete netlify.toml --- netlify.toml | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 netlify.toml diff --git a/netlify.toml b/netlify.toml deleted file mode 100644 index ed9e83391..000000000 --- a/netlify.toml +++ /dev/null @@ -1,6 +0,0 @@ -# This file tells netlify where the code for this project is and -# how it should build the JavaScript assets to deploy from. -[build] - base = "frontend/" - publish = "dist" - command = "npm run build" From 774efcc14a7492030eb3dacd84fef7624d3ed069 Mon Sep 17 00:00:00 2001 From: Paulajungaker Date: Thu, 23 May 2024 16:31:51 +0200 Subject: [PATCH 02/36] Creating the backend --- backend/models/User.js | 34 ++++++++++++++++++ backend/package.json | 4 +++ backend/routes/auth.js | 78 ++++++++++++++++++++++++++++++++++++++++++ backend/server.js | 8 ++++- 4 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 backend/models/User.js create mode 100644 backend/routes/auth.js diff --git a/backend/models/User.js b/backend/models/User.js new file mode 100644 index 000000000..291aaae36 --- /dev/null +++ b/backend/models/User.js @@ -0,0 +1,34 @@ +import mongoose from "mongoose"; +import bcrypt from "bcrypt"; + +const userSchema = new mongoose.Schema({ + username: { + type: String, + required: true, + unique: true, + }, + password: { + type: String, + required: true, + }, + accessToken: { + type: String, + }, +}); + +userSchema.pre("save", async function (next) { + if (!this.isModified("password")) { + next(); + } + const salt = await bcrypt.genSalt(10); + this.password = await bcrypt.hash(this.password, salt); + next(); +}); + +userSchema.methods.matchPassword = async function (enteredPassword) { + return await bcrypt.compare(enteredPassword, this.password); +}; + +const User = mongoose.model("User", userSchema); + +export default User; diff --git a/backend/package.json b/backend/package.json index 8de5c4ce0..162e406a4 100644 --- a/backend/package.json +++ b/backend/package.json @@ -12,8 +12,12 @@ "@babel/core": "^7.17.9", "@babel/node": "^7.16.8", "@babel/preset-env": "^7.16.11", + "bcrypt": "^5.1.1", + "bcryptjs": "^2.4.3", "cors": "^2.8.5", + "dotenv": "^16.4.5", "express": "^4.17.3", + "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..361c90be4 --- /dev/null +++ b/backend/routes/auth.js @@ -0,0 +1,78 @@ +import express from "express"; +import bcrypt from "bcrypt"; +import jwt from "jsonwebtoken"; +import User from "../models/User"; + +const router = express.Router(); + +router.post("/register", async (req, res) => { + const { username, password } = req.body; + try { + const userExists = await User.findOne({ username }); + if (userExists) { + return res.status(400).json({ message: "User already exists" }); + } + + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(password, salt); + + const user = await User.create({ username, password: hashedPassword }); + + const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { + expiresIn: "1h", + }); + + user.accessToken = token; + await user.save(); + + res.status(201).json({ token }); + } catch (error) { + res.status(500).json({ message: "Server error" }); + } +}); + +router.post("/login", async (req, res) => { + const { username, password } = req.body; + try { + const user = await User.findOne({ username }); + if (!user) { + return res.status(400).json({ message: "Invalid credentials" }); + } + + const isMatch = await user.matchPassword(password); + if (!isMatch) { + return res.status(400).json({ message: "Invalid credentials" }); + } + + const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { + expiresIn: "1h", + }); + + user.accessToken = token; + await user.save(); + + res.json({ token }); + } catch (error) { + res.status(500).json({ message: "Server error" }); + } +}); + +router.get("/protected", async (req, res) => { + const token = req.headers.authorization?.split(" ")[1]; + if (!token) { + return res.status(401).json({ message: "No token, authorization denied" }); + } + + try { + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const user = await User.findById(decoded.id); + if (!user) { + return res.status(401).json({ message: "Token is not valid" }); + } + res.json({ message: "This is protected content" }); + } catch (error) { + res.status(401).json({ message: "Token is not valid " }); + } +}); + +export default router; diff --git a/backend/server.js b/backend/server.js index dfe86fb8e..0c2974f1e 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,8 +1,12 @@ import cors from "cors"; import express from "express"; import mongoose from "mongoose"; +import dotenv from "dotenv"; +import authRoutes from "./routes/auth"; -const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo"; +dotenv.config(); + +const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-auth"; mongoose.connect(mongoUrl); mongoose.Promise = Promise; @@ -21,6 +25,8 @@ app.get("/", (req, res) => { res.send("Hello Technigo!"); }); +app.use("/api/auth", authRoutes); + // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); From f8e4b53337305ec7289fa8b37ccf91d3753f251e Mon Sep 17 00:00:00 2001 From: Paulajungaker Date: Thu, 23 May 2024 16:35:36 +0200 Subject: [PATCH 03/36] Adding netlify file --- netlify.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 netlify.toml diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 000000000..0c8656403 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,10 @@ +[build] + base = "frontend" + publish = "dist" + command = "npm run build" + +[[redirects]] + from = "/*" + to = "/index.html" + status = 200 + \ No newline at end of file From 11e3f91df772240fa5359d4bb228befc39b4ab37 Mon Sep 17 00:00:00 2001 From: Paulajungaker Date: Thu, 23 May 2024 16:44:43 +0200 Subject: [PATCH 04/36] Creating config file for axios --- frontend/package.json | 4 +++- frontend/src/config.js | 7 +++++++ package.json | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 frontend/src/config.js diff --git a/frontend/package.json b/frontend/package.json index e9c95b79f..599f83528 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,8 +10,10 @@ "preview": "vite preview" }, "dependencies": { + "axios": "^1.7.2", "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/config.js b/frontend/src/config.js new file mode 100644 index 000000000..325416f19 --- /dev/null +++ b/frontend/src/config.js @@ -0,0 +1,7 @@ +import axios from "axios"; + +const instance = axios.create({ + baseURL: "https://project-auth-ws3k.onrender.com/", +}); + +export default instance; diff --git a/package.json b/package.json index d774b8cc3..10b14c9d8 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "project-auth-parent", + "name": "project-auth", "version": "1.0.0", "scripts": { "postinstall": "npm install --prefix backend" From eb3de0bb204345d654e61392c4d12ab3acbe5819 Mon Sep 17 00:00:00 2001 From: Paulajungaker Date: Thu, 23 May 2024 17:19:10 +0200 Subject: [PATCH 05/36] Setting up routes and creating navbar --- frontend/src/App.jsx | 13 ++++++- frontend/src/{ => api}/config.js | 0 frontend/src/components/ErrorBoundary.jsx | 0 frontend/src/components/Home.jsx | 5 +++ frontend/src/components/LoadingSpinner.jsx | 0 frontend/src/components/Navbar.jsx | 39 +++++++++++++++++++ frontend/src/components/auth/Login.jsx | 5 +++ frontend/src/components/auth/Logout.jsx | 5 +++ frontend/src/components/auth/Register.jsx | 5 +++ .../src/components/protected/Protected.jsx | 5 +++ frontend/src/routes/AppRoutes.jsx | 24 ++++++++++++ frontend/src/styling/Navbar.css | 1 + 12 files changed, 101 insertions(+), 1 deletion(-) rename frontend/src/{ => api}/config.js (100%) create mode 100644 frontend/src/components/ErrorBoundary.jsx create mode 100644 frontend/src/components/Home.jsx create mode 100644 frontend/src/components/LoadingSpinner.jsx create mode 100644 frontend/src/components/Navbar.jsx create mode 100644 frontend/src/components/auth/Login.jsx create mode 100644 frontend/src/components/auth/Logout.jsx create mode 100644 frontend/src/components/auth/Register.jsx create mode 100644 frontend/src/components/protected/Protected.jsx create mode 100644 frontend/src/routes/AppRoutes.jsx create mode 100644 frontend/src/styling/Navbar.css diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 1091d4310..719645227 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,3 +1,14 @@ +import { BrowserRouter as Router } from "react-router-dom"; +import AppRoutes from "./routes/AppRoutes"; + export const App = () => { - return
Find me in src/app.jsx!
; + return ( + +
+ +
+
+ ); }; + +export default App; diff --git a/frontend/src/config.js b/frontend/src/api/config.js similarity index 100% rename from frontend/src/config.js rename to frontend/src/api/config.js diff --git a/frontend/src/components/ErrorBoundary.jsx b/frontend/src/components/ErrorBoundary.jsx new file mode 100644 index 000000000..e69de29bb diff --git a/frontend/src/components/Home.jsx b/frontend/src/components/Home.jsx new file mode 100644 index 000000000..d7ab57451 --- /dev/null +++ b/frontend/src/components/Home.jsx @@ -0,0 +1,5 @@ +const Home = () => { + return; +}; + +export default Home; diff --git a/frontend/src/components/LoadingSpinner.jsx b/frontend/src/components/LoadingSpinner.jsx new file mode 100644 index 000000000..e69de29bb diff --git a/frontend/src/components/Navbar.jsx b/frontend/src/components/Navbar.jsx new file mode 100644 index 000000000..d3b18751f --- /dev/null +++ b/frontend/src/components/Navbar.jsx @@ -0,0 +1,39 @@ +import { Link } from "react-router-dom"; +import "../styling/Navbar.css"; + +const Navbar = () => { + return ( + + ); +}; + +export default Navbar; diff --git a/frontend/src/components/auth/Login.jsx b/frontend/src/components/auth/Login.jsx new file mode 100644 index 000000000..21b40f547 --- /dev/null +++ b/frontend/src/components/auth/Login.jsx @@ -0,0 +1,5 @@ +const Login = () => { + return; +}; + +export default Login; diff --git a/frontend/src/components/auth/Logout.jsx b/frontend/src/components/auth/Logout.jsx new file mode 100644 index 000000000..02849ee24 --- /dev/null +++ b/frontend/src/components/auth/Logout.jsx @@ -0,0 +1,5 @@ +const Logout = () => { + return; +}; + +export default Logout; diff --git a/frontend/src/components/auth/Register.jsx b/frontend/src/components/auth/Register.jsx new file mode 100644 index 000000000..6130d9d0e --- /dev/null +++ b/frontend/src/components/auth/Register.jsx @@ -0,0 +1,5 @@ +const Register = () => { + return; +}; + +export default Register; diff --git a/frontend/src/components/protected/Protected.jsx b/frontend/src/components/protected/Protected.jsx new file mode 100644 index 000000000..5299f43c4 --- /dev/null +++ b/frontend/src/components/protected/Protected.jsx @@ -0,0 +1,5 @@ +const Protected = () => { + return; +}; + +export default Protected; diff --git a/frontend/src/routes/AppRoutes.jsx b/frontend/src/routes/AppRoutes.jsx new file mode 100644 index 000000000..ac4088aed --- /dev/null +++ b/frontend/src/routes/AppRoutes.jsx @@ -0,0 +1,24 @@ +import { Route, Routes } from "react-router-dom"; +import Navbar from "../components/navbar"; +import Home from "../components/Home"; +import Register from "../components/auth/Register"; +import Login from "../components/auth/Login"; +import Protected from "../components/protected/Protected"; +import Logout from "../components/auth/Logout"; + +const AppRoutes = () => { + return ( + <> + + + } /> + } /> + } /> + } /> + } /> + + + ); +}; + +export default AppRoutes; diff --git a/frontend/src/styling/Navbar.css b/frontend/src/styling/Navbar.css new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/frontend/src/styling/Navbar.css @@ -0,0 +1 @@ + From 700c5ea8f2d5d036142bde7d7d7476bedbbf4b61 Mon Sep 17 00:00:00 2001 From: Paulajungaker Date: Thu, 23 May 2024 17:41:28 +0200 Subject: [PATCH 06/36] First styling of navbar --- frontend/index.html | 10 ++++++-- frontend/public/LogoIcon.png | Bin 0 -> 4423 bytes frontend/src/components/Navbar.jsx | 2 ++ frontend/src/index.css | 11 +++++--- frontend/src/styling/Navbar.css | 39 +++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 frontend/public/LogoIcon.png diff --git a/frontend/index.html b/frontend/index.html index 0c589eccd..7983abb7c 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,10 +1,16 @@ - + - Vite + React + Cute kitties + + +
diff --git a/frontend/public/LogoIcon.png b/frontend/public/LogoIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..924ecf63c91cc47554b11249ff58a0e1eb24d42b GIT binary patch literal 4423 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 N002ovPDHLkV1n!kYbO8z literal 0 HcmV?d00001 diff --git a/frontend/src/components/Navbar.jsx b/frontend/src/components/Navbar.jsx index d3b18751f..ab5dc5a62 100644 --- a/frontend/src/components/Navbar.jsx +++ b/frontend/src/components/Navbar.jsx @@ -5,6 +5,8 @@ const Navbar = () => { return (