diff --git a/README.md b/README.md index dfa05e177..ce8626bb7 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,7 @@ # 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. - -## 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? - ## 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. +Front-end: [](https://app.netlify.com/sites/yifan-project-authentication/deploys) + +Back-end: https://project-authentication-6r12.onrender.com/ diff --git a/backend/package.json b/backend/package.json index 8de5c4ce0..3bda8e5d3 100644 --- a/backend/package.json +++ b/backend/package.json @@ -12,8 +12,11 @@ "@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", "express": "^4.17.3", + "express-list-endpoints": "^7.1.0", "mongoose": "^8.0.0", "nodemon": "^3.0.1" } diff --git a/backend/server.js b/backend/server.js index dfe86fb8e..59b5f90b9 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,14 +1,35 @@ import cors from "cors"; import express from "express"; import mongoose from "mongoose"; +import crypto from "crypto"; +import bcrypt from "bcryptjs"; +import expressListEndpoints from "express-list-endpoints"; -const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo"; +const mongoUrl = process.env.MONGO_URL || "mongodb://127.0.0.1/project-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 +const User = mongoose.model("User", { + name: { type: String, unique: true, required: true }, + email: { type: String, unique: true, required: true }, + password: { type: String, required: true }, + accessToken: { + type: String, + default: () => crypto.randomBytes(128).toString("hex"), //user gets a string of random numbers as the accessToken + }, +}); + +//a middleware function for looking for the user based on the accessToken saved in "Authorization" in the header +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 }); + } +}; + const port = process.env.PORT || 8080; const app = express(); @@ -18,7 +39,65 @@ app.use(express.json()); // Start defining your routes here app.get("/", (req, res) => { - res.send("Hello Technigo!"); + const endpoints = expressListEndpoints(app); + const documentation = endpoints.map((endpoint) => ({ + method: endpoint.methods.join(", "), + path: endpoint.path, + })); + res.json(documentation); +}); + +app.post("/registration", async (req, res) => { + try { + const { name, email, password } = req.body; + + //error handling + if (!name || name.trim() === "") { + return res.status(400).json({ message: "Please enter username" }); + } + if (!email || email.trim() === "") { + return res.status(400).json({ message: "Please enter email" }); + } + if (!password || password.trim() === "") { + return res.status(400).json({ message: "Please enter password" }); + } + if (password.length < 6) { + return res + .status(400) + .json({ message: "Password must be at least 6 characters long" }); + } + + const salt = bcrypt.genSaltSync(); + const user = new User({ + name, + email, + password: bcrypt.hashSync(password, salt), + }); + user.save(); + res.status(201).json({ id: user._id, accessToken: user.accessToken }); + } catch (err) { + res + .status(400) + .json({ message: "Could not create the user", errors: err.errors }); + } +}); + +app.get("/dashboard", authenticateUser); +app.get("/dashboard", (req, res) => { + res.json({ message: "You're logged in!" }); +}); + +app.post("/login", async (req, res) => { + const user = await User.findOne({ email: req.body.email }); + if (user && bcrypt.compareSync(req.body.password, user.password)) { + res.json({ + userId: user._id, + name: user.name, + accessToken: user.accessToken, + }); + } else { + return res.status(400).json({ notFound: true }); + } }); // Start the server diff --git a/frontend/index.html b/frontend/index.html index 0c589eccd..69a744d15 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,13 +1,16 @@ -
- - - -