diff --git a/.gitignore b/.gitignore
index 3d70248ba..78651256b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,4 +12,5 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
-package-lock.json
\ No newline at end of file
+package-lock.json
+note.md
diff --git a/README.md b/README.md
index dfa05e177..8d869b80e 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,21 @@
# 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.
+For this project, the focus was on connecting the frontend and backend by creating a registration form that not only registers the user but also logs them in and returns an access token used to authenticate the user. Since we are developing an application for children aged 7-9 years old to help them improve their learning skills in English, Swedish, and math, we wanted to implement these functionalities in this project using MongoDB as the database, and ReactJS and ExpressJS to handle the frontend and fetch data from the API. In this project, we are able to register, log in, and log out a user.
## 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?
+We had some problems deploying both the frontend and backend, but we worked together and solved them. We also found some difficulty adding the user data to the database after deployment. However, after adding the correct endpoints and using the correct connection string to MongoDB, we were able to start registering new users and use that to log i
## 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.
+[Frontend](https://technigo-project-auth.netlify.app/)
+
+[Backend](https://technigo-project-auth.onrender.com/)
+
+## Contributors
+
+Thanks to these great people for contributing to this project:
+
+- [@Tejpex](https://github.com/Tejpex)
+- [@fridaforser](https://github.com/fridaforser)
+- [@KatSjolin](https://github.com/KatSjolin)
diff --git a/backend/package.json b/backend/package.json
index 8de5c4ce0..588b5a6fe 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -12,9 +12,14 @@
"@babel/core": "^7.17.9",
"@babel/node": "^7.16.8",
"@babel/preset-env": "^7.16.11",
+ "bcrypt-nodejs": "^0.0.3",
"cors": "^2.8.5",
"express": "^4.17.3",
- "mongoose": "^8.0.0",
+ "mongodb": "^6.6.2",
+ "mongoose": "^8.4.0",
"nodemon": "^3.0.1"
+ },
+ "devDependencies": {
+ "@types/bcrypt-nodejs": "^0.0.31"
}
}
diff --git a/backend/server.js b/backend/server.js
index dfe86fb8e..ffe3ceda2 100644
--- a/backend/server.js
+++ b/backend/server.js
@@ -1,24 +1,142 @@
import cors from "cors";
import express from "express";
import mongoose from "mongoose";
+import bcrypt from "bcrypt-nodejs";
+import crypto from "crypto";
-const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo";
+// Defining port and connecting to mongoose
+const port = process.env.PORT || 8000;
+const app = express();
+const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/auth";
+
+console.log("Connecting to MongoDB at:", mongoUrl);
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
-const port = process.env.PORT || 8080;
-const app = express();
+// Defining schema for a User
+const User = mongoose.model("User", {
+ username: {
+ type: String,
+ unique: true,
+ required: true,
+ },
+ password: {
+ type: String,
+ required: true,
+ },
+ firstName: {
+ type: String,
+ required: true,
+ },
+ lastName: {
+ type: String,
+ required: true,
+ },
+ age: {
+ type: String,
+ required: true,
+ },
+ email: {
+ type: String,
+ unique: true,
+ required: true,
+ },
+ accessToken: {
+ type: String,
+ default: () => crypto.randomBytes(128).toString("hex"),
+ },
+});
-// Add middlewares to enable cors and json body parsing
+//Authenticate user as middleware
+const authenticateUser = async (req, res, next) => {
+ const accessToken = req.header("Authorization");
+ if (!accessToken) {
+ return res.status(401).json({ error: "Unauthorized: Missing access token" });
+ }
+
+ const user = await User.findOne({ accessToken })
+ if (user) {
+ console.log("User is found", user);
+ req.user = user;
+ next();
+ } else {
+ return res.status(403).json({ error: "Forbidden: Invalid access token" });
+ }
+};
+
+// Middlewares to enable cors and json body parsing
app.use(cors());
app.use(express.json());
+app.use((req, res, next) => {
+ if (mongoose.connection.readyState === 1) {
+ next();
+ } else {
+ res.status(503).json({ error: "Service unavailable." });
+ }
+});
-// Start defining your routes here
+// Defining routes
app.get("/", (req, res) => {
- res.send("Hello Technigo!");
+ res.send("Hello friend!");
+});
+
+//User-endpoint for developing purpose
+app.get("/users", async (req, res) => {
+ const allUsers = await User.find().exec();
+ if (allUsers.length > 0) {
+ res.status(200).json(allUsers);
+ } else {
+ res.status(404).send("No users found");
+ }
+});
+
+//Create user with username, password etc.
+app.post("/users", async (req, res) => {
+ try {
+ const { username, firstName, lastName, age, email, password } = req.body;
+ const salt = bcrypt.genSaltSync(10);
+ const user = new User({
+ username,
+ firstName,
+ lastName,
+ age,
+ email,
+ password: bcrypt.hashSync(password, salt),
+ });
+ await user.save();
+ res.status(201).json({ id: user._id, accessToken: user.accessToken });
+ } catch (error) {
+ res
+ .status(400)
+ .json({ response: error, message: "Could not create user." });
+ }
+});
+
+//Endpoint for login
+app.post("/sessions", async (req, res) => {
+ const userByUsername = await User.findOne({ username: req.body.username });
+ const userByEmail = await User.findOne({ email: req.body.email });
+ if (
+ userByUsername &&
+ bcrypt.compareSync(req.body.password, userByUsername.password)
+ ) {
+ res.status(200).json({userId: userByUsername._id, accessToken: userByUsername.accessToken,
+ });
+ } else if (
+ userByEmail &&
+ bcrypt.compareSync(req.body.password, userByEmail.password)
+ ) {
+ res.status(200).json({ userId: userByEmail._id, accessToken: userByEmail.accessToken });
+ } else {
+ res.status(404).json({ notFound: true });
+ }
+});
+
+app.get("/games", authenticateUser);
+app.get("/games", async (req, res) => {
+ res
+ .status(200)
+ .json({ message: "Secret message only for logged in users to see!" });
});
// Start the server
diff --git a/frontend/index.html b/frontend/index.html
index 0c589eccd..cd0a6f8c1 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -4,7 +4,10 @@
-
Vite + React
+
+
+
+ Pluggin
diff --git a/frontend/package.json b/frontend/package.json
index e9c95b79f..d74ed8395 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -10,8 +10,13 @@
"preview": "vite preview"
},
"dependencies": {
+ "dotenv": "^16.4.5",
"react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "react-dom": "^18.2.0",
+ "react-hook-form": "^7.51.5",
+ "react-router": "^6.23.1",
+ "react-router-dom": "^6.23.1",
+ "styled-components": "^6.1.11"
},
"devDependencies": {
"@types/react": "^18.2.15",
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 1091d4310..c4f4206e2 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,3 +1,33 @@
+import { BrowserRouter, Routes, Route } from "react-router-dom";
+import { Header } from "./components/Header";
+import { RegistrationForm } from "./components/RegistrationForm";
+import { Login } from "./components/Login";
+import { Play } from "./components/Play";
+import { Math } from "./components/Games/Math";
+import { Swedish } from "./components/Games/Swedish";
+import { English } from "./components/Games/English";
+import { Progress } from "./components/MyProgress";
+import { WelcomeText } from "./components/WelcomeText";
+import { UserProvider } from "./contexts/UserContext";
+
export const App = () => {
- return