diff --git a/README.md b/README.md
index dfa05e177..75ae756a5 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,12 @@
# Project Auth API
-Replace this readme with your own information about your project.
-
-Start by briefly describing the assignment in a sentence or two. Keep it short and to the point.
+Creating my own Authentication API and using it in a simple website.
## The problem
-Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next?
+I used tools like MongoDB Atlas and postman to test my API. I did a small plan for the project using Figma. If I had more time I would work on the strech goals.
## 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.
+Backend deploy: https://project-auth-backend-kfgp.onrender.com/
+Frontend deploy: https://sweet-lily-05d48d.netlify.app/
diff --git a/backend/.gitignore b/backend/.gitignore
index 25c8fdbab..8f5e467c8 100644
--- a/backend/.gitignore
+++ b/backend/.gitignore
@@ -1,2 +1,3 @@
node_modules
-package-lock.json
\ No newline at end of file
+package-lock.json
+.env
\ No newline at end of file
diff --git a/backend/models/User.js b/backend/models/User.js
new file mode 100644
index 000000000..7292f7712
--- /dev/null
+++ b/backend/models/User.js
@@ -0,0 +1,11 @@
+import mongoose from "mongoose";
+
+const userSchema = new mongoose.Schema({
+ username: { type: String, unique: true, required: true },
+ password: { type: String, required: true },
+ accessToken: { type: String },
+});
+
+const User = mongoose.model("User", userSchema);
+
+export default User;
diff --git a/backend/package.json b/backend/package.json
index 8de5c4ce0..cbb10f26c 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -12,9 +12,15 @@
"@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",
- "mongoose": "^8.0.0",
+ "jsonwebtoken": "^9.0.2",
+ "mongoose": "^8.0.0"
+ },
+ "devDependencies": {
"nodemon": "^3.0.1"
}
}
diff --git a/backend/server.js b/backend/server.js
index dfe86fb8e..405ff3e23 100644
--- a/backend/server.js
+++ b/backend/server.js
@@ -1,26 +1,110 @@
import cors from "cors";
import express from "express";
import mongoose from "mongoose";
+import bcrypt from "bcrypt";
+import jwt from "jsonwebtoken";
+import dotenv from "dotenv";
+import User from "./models/User";
-const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo";
-mongoose.connect(mongoUrl);
-mongoose.Promise = Promise;
+dotenv.config();
-// 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;
-// Add middlewares to enable cors and json body parsing
+// Middleware
app.use(cors());
app.use(express.json());
-// Start defining your routes here
+// Connect to MongoDB
+const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-auth";
+mongoose.connect(mongoUrl);
+mongoose.Promise = Promise;
+
+// Routes
app.get("/", (req, res) => {
- res.send("Hello Technigo!");
+ res.send("Welcome to your Express API");
});
+app.post("/api/register", async (req, res) => {
+ const { username, password } = req.body;
+
+ try {
+ // Check if the username already exists
+ let user = await User.findOne({ username });
+ if (user) {
+ return res.status(400).json({ message: "Username already taken" });
+ }
+
+ // Hash the password
+ const salt = await bcrypt.genSalt(10);
+ const hashedPassword = await bcrypt.hash(password, salt);
+
+ // Create a new user
+ user = new User({ username, password: hashedPassword });
+ await user.save();
+
+ // Generate JWT token
+ const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, {
+ expiresIn: "1h",
+ });
+
+ res.status(201).json({ message: "User registered successfully", token });
+ } catch (error) {
+ console.error("Registration error:", error);
+ res.status(500).json({ message: "Server error" });
+ }
+});
+
+app.post("/api/login", async (req, res) => {
+ const { username, password } = req.body;
+
+ try {
+ // Find the user by username
+ const user = await User.findOne({ username });
+ if (!user) {
+ return res.status(400).json({ message: "Invalid credentials" });
+ }
+
+ // Check if the password matches
+ const isMatch = await bcrypt.compare(password, user.password);
+ if (!isMatch) {
+ return res.status(400).json({ message: "Invalid credentials" });
+ }
+
+ // Generate JWT token
+ const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, {
+ expiresIn: "1h",
+ });
+
+ res.json({ token });
+ } catch (error) {
+ console.error("Login error:", error);
+ res.status(500).json({ message: "Server error" });
+ }
+});
+
+app.get("/api/protected", authenticateToken, (req, res) => {
+ res.json({ message: "This is protected content" });
+});
+
+function authenticateToken(req, res, next) {
+ const authHeader = req.headers["authorization"];
+ const token = authHeader && authHeader.split(" ")[1];
+
+ if (!token) {
+ return res.status(401).json({ message: "No token, authorization denied" });
+ }
+
+ jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
+ if (err) {
+ console.error("Token verification error:", err);
+ return res.status(403).json({ message: "Token is not valid" });
+ }
+ req.user = decoded;
+ next();
+ });
+}
+
// Start the server
app.listen(port, () => {
console.log(`Server running on http://localhost:${port}`);
diff --git a/frontend/.gitignore b/frontend/.gitignore
index 265f50c92..6254213ab 100644
--- a/frontend/.gitignore
+++ b/frontend/.gitignore
@@ -23,4 +23,5 @@ dist-ssr
*.sln
*.sw?
-package-lock.json
\ No newline at end of file
+package-lock.json
+.env
\ No newline at end of file
diff --git a/frontend/index.html b/frontend/index.html
index 0c589eccd..04e80fae5 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -1,10 +1,16 @@
-
+
- Vite + React
+ Cute kitties
+
+
+
diff --git a/frontend/package.json b/frontend/package.json
index e9c95b79f..cd8de5765 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -10,8 +10,11 @@
"preview": "vite preview"
},
"dependencies": {
+ "axios": "^1.7.2",
"react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "react-dom": "^18.2.0",
+ "react-icons": "^5.2.1",
+ "react-router-dom": "^6.23.1"
},
"devDependencies": {
"@types/react": "^18.2.15",
diff --git a/frontend/public/Kittens.jpg b/frontend/public/Kittens.jpg
new file mode 100644
index 000000000..ced177108
Binary files /dev/null and b/frontend/public/Kittens.jpg differ
diff --git a/frontend/public/LogoIcon.png b/frontend/public/LogoIcon.png
new file mode 100644
index 000000000..924ecf63c
Binary files /dev/null and b/frontend/public/LogoIcon.png differ
diff --git a/frontend/public/homeKitten.jpg b/frontend/public/homeKitten.jpg
new file mode 100644
index 000000000..5f91cc6e3
Binary files /dev/null and b/frontend/public/homeKitten.jpg differ
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/components/Home.jsx b/frontend/src/components/Home.jsx
new file mode 100644
index 000000000..07b5e452e
--- /dev/null
+++ b/frontend/src/components/Home.jsx
@@ -0,0 +1,41 @@
+import { Link } from "react-router-dom";
+import { FaLongArrowAltDown } from "react-icons/fa";
+import "../styling/Home.css";
+
+const Home = () => {
+ return (
+
+
+
Ready to see some very cute kitties?
+
+
+
+ "A cat will do what it wants, when it wants, and there is not a
+ thing you can do about it"
+
+
+
+
+
+
+
+
+
+
+ To get access to the kittens you need to log in.
+