diff --git a/README.md b/README.md
index dfa05e177..0f577362e 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,17 @@
# 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.
+This fullstack project requires developing a backend to support user registration, login and an authenticated endpoint accessible only to loggen-in users.
+The frontend features a startpage, a registration and login form and a page displaying authenticated content. Also sign-out button that removes the access token from local storage and brings the user back to the startpage.
## 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 started by using the code from the codealong in the backend, trying to figure out how to do an authentication process and use bycript properly.
+Being frustrated with backend I started creating the frontend and for a bit my project was all over the place.
+In the end I went back to finish and test backend and then finish a frontend that could also be used for our final project.
+
+If I had more time, I would add a loading animation page, because it takes forever on login and registration.
## 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: https://project-auth-ziup.onrender.com
+Frontend: https://project-auth-eliane.netlify.app
diff --git a/backend/package.json b/backend/package.json
index 8de5c4ce0..17a4b9a1d 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -12,9 +12,13 @@
"@babel/core": "^7.17.9",
"@babel/node": "^7.16.8",
"@babel/preset-env": "^7.16.11",
+ "bcrypt": "^5.1.1",
"cors": "^2.8.5",
- "express": "^4.17.3",
- "mongoose": "^8.0.0",
+ "dotenv": "^16.4.5",
+ "express": "^4.19.2",
+ "express-list-endpoints": "^7.1.0",
+ "mongodb": "^4.17.2",
+ "mongoose": "^8.4.0",
"nodemon": "^3.0.1"
}
}
diff --git a/backend/server.js b/backend/server.js
index dfe86fb8e..b47efcd1d 100644
--- a/backend/server.js
+++ b/backend/server.js
@@ -1,27 +1,126 @@
import cors from "cors";
import express from "express";
import mongoose from "mongoose";
+import dotenv from "dotenv";
+import expressListEndpoints from "express-list-endpoints";
+import bcrypt from "bcrypt";
+import crypto from "crypto";
-const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo";
+dotenv.config();
+
+const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/auth";
mongoose.connect(mongoUrl);
mongoose.Promise = Promise;
-// 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
+//create schema and model
+const { Schema, model } = mongoose;
+const userSchema = new Schema({
+ name: {
+ type: String,
+ unique: true,
+ },
+ email: {
+ type: String,
+ unique: true,
+ },
+ password: {
+ type: String,
+ required: true,
+ },
+ accessToken: {
+ type: String,
+ default: () => crypto.randomBytes(128).toString("hex"),
+ },
+});
+const User = model("User", userSchema);
+
+//defines the port the app will run on
const port = process.env.PORT || 8080;
const app = express();
-// Add middlewares to enable cors and json body parsing
+//add middlewares to enable cors and json body parsing
app.use(cors());
app.use(express.json());
-// Start defining your routes here
+//middleware to check if database is available
+app.use((req, res, next) => {
+ if (mongoose.connection.readyState === 1) {
+ next();
+ } else {
+ res.status(503).json({ error: "service unavailable" });
+ }
+});
+
+//middleware to authenticate user
+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({
+ loggedOut: true,
+ message: "You have to log in to get access",
+ });
+ }
+};
+
+//registration endpoint
+app.post("/register", async (req, res) => {
+ try {
+ const { name, email, password } = req.body;
+ const salt = bcrypt.genSaltSync();
+ const user = new User({
+ name,
+ email,
+ password: bcrypt.hashSync(password, salt),
+ });
+ await user.save();
+ res.status(201).json({
+ success: true,
+ message: "User created",
+ id: user._id,
+ accessToken: user.accessToken,
+ });
+ } catch (error) {
+ res.status(400).json({
+ success: false,
+ message: "Could not create user",
+ errors: error,
+ });
+ }
+});
+
+//authenticated endpoint *super secret endpoint*
+app.get("/dashboard", authenticateUser, (req, res) => {
+ res.json({
+ secret: "This is the secret dashboard, only visible to logged-in users!",
+ });
+});
+
+//login endpoint
+app.post("/login", async (req, res) => {
+ //find user by name
+ const user = await User.findOne({ name: req.body.name });
+ //check if password is correct
+ if (user && bcrypt.compareSync(req.body.password, user.password)) {
+ //success
+ res.status(200).json({ userId: user._id, accessToken: user.accessToken });
+ } else {
+ //failure
+ res
+ .status(401)
+ .json({ notFound: true, message: "Invalid name or password" });
+ }
+});
+
+//route to list all endpoints
app.get("/", (req, res) => {
- res.send("Hello Technigo!");
+ const endpoints = expressListEndpoints(app);
+ res.json(endpoints);
});
-// Start the server
+//start the server
app.listen(port, () => {
console.log(`Server running on http://localhost:${port}`);
});
diff --git a/netlify.toml b/frontend/netlify.toml
similarity index 68%
rename from netlify.toml
rename to frontend/netlify.toml
index 95443a1f3..558042533 100644
--- a/netlify.toml
+++ b/frontend/netlify.toml
@@ -2,5 +2,11 @@
# how it should build the JavaScript assets to deploy from.
[build]
base = "frontend/"
- publish = "build/"
+ publish = "dist"
command = "npm run build"
+
+[[redirects]]
+ from = "/*"
+ to = "/index.html"
+ status = 200
+
diff --git a/frontend/package.json b/frontend/package.json
index e9c95b79f..955b69152 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -10,13 +10,16 @@
"preview": "vite preview"
},
"dependencies": {
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "react-router-dom": "^6.23.1",
+ "styled-components": "^6.1.11"
},
"devDependencies": {
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@vitejs/plugin-react": "^4.0.3",
+ "babel-plugin-styled-components": "^2.1.4",
"eslint": "^8.45.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
diff --git a/frontend/public/globe.png b/frontend/public/globe.png
new file mode 100644
index 000000000..1802a8e03
Binary files /dev/null and b/frontend/public/globe.png differ
diff --git a/frontend/public/header.jpg b/frontend/public/header.jpg
new file mode 100644
index 000000000..ea0da6e35
Binary files /dev/null and b/frontend/public/header.jpg differ
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 1091d4310..45af87ccc 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,3 +1,18 @@
+import { BrowserRouter, Routes, Route } from "react-router-dom";
+import { Login } from "./components/Login";
+import { Registration } from "./components/Registration";
+import { Dashboard } from "./components/Dashboard";
+import { Homepage } from "./components/Homepage";
+
export const App = () => {
- return