Skip to content

Commit 86a6936

Browse files
author
Matheus Ishiyama
authored
Create register user workflow (#1)
2 parents 45e1cf9 + 175f35a commit 86a6936

File tree

19 files changed

+6183
-0
lines changed

19 files changed

+6183
-0
lines changed

package.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "chat-app-backend",
3+
"version": "0.0.0",
4+
"description": "",
5+
"main": "src/index.js",
6+
"scripts": {
7+
"dev": "nodemon src/index.js",
8+
"start": "node src/index.js",
9+
"test": "jest"
10+
},
11+
"jest": {
12+
"testEnvironment": "node"
13+
},
14+
"repository": {
15+
"type": "git",
16+
"url": "git+https://github.com/MatheusIshiyama/chat-app-backend.git"
17+
},
18+
"keywords": [],
19+
"author": "",
20+
"license": "ISC",
21+
"bugs": {
22+
"url": "https://github.com/MatheusIshiyama/chat-app-backend/issues"
23+
},
24+
"homepage": "https://github.com/MatheusIshiyama/chat-app-backend#readme",
25+
"dependencies": {
26+
"bcrypt": "^5.0.1",
27+
"crypto": "^1.0.1",
28+
"dotenv": "^8.2.0",
29+
"email-validator": "^2.0.4",
30+
"express": "^4.17.1",
31+
"mongoose": "^5.12.3",
32+
"nodemailer": "^6.5.0"
33+
},
34+
"devDependencies": {
35+
"jest": "^26.6.3",
36+
"nodemon": "^2.0.7",
37+
"supertest": "^6.1.3"
38+
}
39+
}

src/app.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const express = require("express");
2+
3+
//* express setup
4+
const app = express();
5+
app.use(express.json());
6+
app.use(express.urlencoded({ extended: true }));
7+
8+
//* routes
9+
app.use("/user", require("./routes/user"));
10+
11+
module.exports = app;

src/controllers/user.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const crypto = require("crypto");
2+
const User = require("../models/user");
3+
const sendMail = require("../services/sendMail");
4+
const password = require("../services/password");
5+
6+
const UserController = {
7+
async register(req, res) {
8+
const body = req.body;
9+
const hashPassword = password.hash(body.password);
10+
const verifyCode = crypto.randomBytes(128).toString("base64");
11+
const newUser = new User({
12+
username: body.username.toLowerCase(),
13+
name: body.name,
14+
email: body.email,
15+
verifyCode,
16+
verified: false,
17+
password: hashPassword,
18+
createdAt: Date.now(),
19+
});
20+
await newUser.save();
21+
22+
const user = await User.findOne(
23+
{ username: body.username },
24+
{ _id: false, password: false }
25+
);
26+
27+
await sendMail(body.email, verifyCode, "Confirm register");
28+
29+
return res.status(201).json({ message: user });
30+
},
31+
32+
async confirm(req, res) {
33+
const { verifyCode } = req.params;
34+
35+
await User.findOneAndUpdate(
36+
{ verifyCode },
37+
{ verifyCode: "verified", verified: true }
38+
);
39+
40+
return res.status(200).json({ message: "User confirmed" });
41+
},
42+
};
43+
44+
module.exports = UserController;

src/database/config.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const mongoose = require("mongoose");
2+
require("dotenv").config();
3+
4+
const database = mongoose;
5+
6+
database
7+
.connect(process.env.MONGO_URI, {
8+
useCreateIndex: true,
9+
useUnifiedTopology: true,
10+
useNewUrlParser: true,
11+
useFindAndModify: false,
12+
})
13+
.then(() => console.log("[DATABASE] Connected"));
14+
15+
module.exports = database;

src/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
const app = require('./app');
2+
require('dotenv').config();
3+
4+
app.listen(process.env.PORT, () => console.log('[SERVER] Running'))

src/middlewares/validateCode.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = (req, res, next) => {
2+
if (!req.params.verifyCode)
3+
return res.status(400).json({ message: "No verifyCode provided" });
4+
5+
if (req.params.verifyCode.length !== 172)
6+
return res.status(400).json({ message: "No verifyCode length accept" });
7+
8+
next();
9+
};
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const User = require("../models/user");
2+
const EmailValidator = require("email-validator");
3+
const validateBody = require("../services/validateBody");
4+
5+
module.exports = async (req, res, next) => {
6+
if (!req.body) return res.status(400).json({ message: "No body provided" });
7+
const { username, name, email, password, checkPassword } = req.body;
8+
9+
//* validate body
10+
if (!validateBody.username(username)) {
11+
return res
12+
.status(400)
13+
.json({ message: "No username provided or no length accept" });
14+
}
15+
16+
if (!validateBody.name(name))
17+
return res
18+
.status(400)
19+
.json({ message: "No name provided or no length accept" });
20+
21+
if (!EmailValidator.validate(email))
22+
return res
23+
.status(400)
24+
.json({ message: "No email provided or invalid format" });
25+
26+
if (!validateBody.password(password))
27+
return res
28+
.status(400)
29+
.json({ message: "No password provided or doesn't match params" });
30+
31+
if (!validateBody.checkPassword(password, checkPassword))
32+
return res.status(400).json({
33+
message: "No checkPassword provided or passwords doesn't match",
34+
});
35+
36+
//* verify if user exists
37+
const userExists = await User.findOne({ username });
38+
const emailExists = await User.findOne({ email });
39+
40+
if (userExists || emailExists)
41+
return res.status(400).json({ message: "Username or Email already exists"});
42+
43+
next();
44+
};

src/models/user.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const database = require("../database/config");
2+
3+
const User = new database.Schema(
4+
{
5+
username: String,
6+
name: String,
7+
email: String,
8+
verifyCode: String,
9+
verified: Boolean,
10+
password: String,
11+
createdAt: Date,
12+
},
13+
{
14+
versionKey: false,
15+
}
16+
);
17+
18+
module.exports = new database.model("User", User);

src/routes/user.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const express = require("express");
2+
const userRoutes = express.Router();
3+
4+
//* controller
5+
const UserController = require("../controllers/user");
6+
7+
//* middlewares
8+
const validateRegister = require("../middlewares/validateRegister");
9+
const validateCode = require("../middlewares/validateCode");
10+
11+
userRoutes.post("/register", validateRegister, (req, res) => {
12+
UserController.register(req, res);
13+
});
14+
15+
userRoutes.get("/confirm/:verifyCode", validateCode, (req, res) => {
16+
UserController.confirm(req, res);
17+
});
18+
19+
module.exports = userRoutes;

src/services/password.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const bcrypt = require("bcrypt");
2+
3+
const password = {
4+
hash(password) {
5+
const hashedPassword = bcrypt.hashSync(password, 10);
6+
return hashedPassword;
7+
},
8+
validate(password, hashPassword) {
9+
const result = bcrypt.compareSync(password, hashPassword);
10+
return result;
11+
},
12+
};
13+
14+
module.exports = password;

0 commit comments

Comments
 (0)