From a41f7e63ac0e0ea36bb2a03613d1dac472d8afac Mon Sep 17 00:00:00 2001 From: canove Date: Fri, 17 Jul 2020 11:40:15 -0300 Subject: [PATCH] Start using sequelize migrations --- .gitignore | 1 + backend/.sequelizerc | 7 ++ backend/package.json | 4 +- backend/src/app.js | 81 ++++++++++--------- backend/src/config/auth.js | 4 + .../src/config/{dbConfig.js => database.js} | 2 +- backend/src/controllers/SessionController.js | 17 ++-- backend/src/controllers/UserController.js | 14 +--- backend/src/database/index.js | 20 ++++- .../migrations/20200717133438-create-users.js | 39 +++++++++ backend/src/middleware/is-auth.js | 16 ++-- backend/src/models/User.js | 38 ++++++--- 12 files changed, 160 insertions(+), 83 deletions(-) create mode 100644 .gitignore create mode 100644 backend/.sequelizerc create mode 100644 backend/src/config/auth.js rename backend/src/config/{dbConfig.js => database.js} (94%) create mode 100644 backend/src/database/migrations/20200717133438-create-users.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..600d2d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode \ No newline at end of file diff --git a/backend/.sequelizerc b/backend/.sequelizerc new file mode 100644 index 0000000..23abc5c --- /dev/null +++ b/backend/.sequelizerc @@ -0,0 +1,7 @@ +const { resolve } = require("path"); + +module.exports = { + config: resolve(__dirname, "src", "config", "database.js"), + "modules-path": resolve(__dirname, "src", "models"), + "migrations-path": resolve(__dirname, "src", "database", "migrations"), +}; diff --git a/backend/package.json b/backend/package.json index 566eb3c..6060318 100644 --- a/backend/package.json +++ b/backend/package.json @@ -26,12 +26,12 @@ "mysql2": "^2.1.0", "qrcode-terminal": "^0.12.0", "sequelize": "^5.21.13", - "sequelize-cli": "^5.5.1", "socket.io": "^2.3.0", "whatsapp-web.js": "^1.7.0", "youch": "^2.0.10" }, "devDependencies": { - "nodemon": "^2.0.4" + "nodemon": "^2.0.4", + "sequelize-cli": "^5.5.1" } } diff --git a/backend/src/app.js b/backend/src/app.js index 91ed025..3b62358 100644 --- a/backend/src/app.js +++ b/backend/src/app.js @@ -1,19 +1,21 @@ require("express-async-errors"); +require("dotenv/config"); +require("./database"); const express = require("express"); const path = require("path"); const Youch = require("youch"); const cors = require("cors"); -const sequelize = require("./database/"); +// const sequelize = require("./database/"); const multer = require("multer"); -const wBot = require("./libs/wbot"); -const wbotMessageListener = require("./services/wbotMessageListener"); -const wbotMonitor = require("./services/wbotMonitor"); +// const wBot = require("./libs/wbot"); +// const wbotMessageListener = require("./services/wbotMessageListener"); +// const wbotMonitor = require("./services/wbotMonitor"); -const MessagesRoutes = require("./routes/messages"); -const ContactsRoutes = require("./routes/contacts"); +// const MessagesRoutes = require("./routes/messages"); +// const ContactsRoutes = require("./routes/contacts"); const AuthRoutes = require("./routes/auth"); -const WhatsRoutes = require("./routes/whatsapp"); +// const WhatsRoutes = require("./routes/whatsapp"); const app = express(); @@ -31,11 +33,16 @@ app.use(express.json()); app.use(multer({ storage: fileStorage }).single("media")); app.use("/public", express.static(path.join(__dirname, "public"))); -app.use(MessagesRoutes); -app.use(ContactsRoutes); -app.use(WhatsRoutes); app.use("/auth", AuthRoutes); +app.listen(process.env.PORT, () => { + console.log(`Server started on port: ${process.env.PORT}`); +}); + +// app.use(MessagesRoutes); +// app.use(ContactsRoutes); +// app.use(WhatsRoutes); + app.use(async (err, req, res, next) => { if (process.env.NODE_ENV === "development") { const errors = await new Youch(err, req).toJSON(); @@ -46,33 +53,33 @@ app.use(async (err, req, res, next) => { return res.status(500).json({ error: "Internal server error" }); }); -sequelize - .sync() - .then(() => { - const server = app.listen(process.env.PORT); - const io = require("./libs/socket").init(server); - io.on("connection", socket => { - console.log("Client Connected"); - socket.on("joinChatBox", contactId => { - socket.join(contactId); - }); +// sequelize +// .sync() +// .then(() => { +// const server = app.listen(process.env.PORT); +// const io = require("./libs/socket").init(server); +// io.on("connection", socket => { +// console.log("Client Connected"); +// socket.on("joinChatBox", contactId => { +// socket.join(contactId); +// }); - socket.on("joinNotification", () => { - console.log("chat entrou no canal de notificações"); - socket.join("notification"); - }); +// socket.on("joinNotification", () => { +// console.log("chat entrou no canal de notificações"); +// socket.join("notification"); +// }); - socket.on("disconnect", () => { - console.log("Client disconnected"); - }); - }); +// socket.on("disconnect", () => { +// console.log("Client disconnected"); +// }); +// }); - wBot.init().then(() => { - wbotMessageListener(); - wbotMonitor(); - }); - console.log("Server started on", process.env.PORT); - }) - .catch(err => { - console.log(err); - }); +// wBot.init().then(() => { +// wbotMessageListener(); +// wbotMonitor(); +// }); +// console.log("Server started on", process.env.PORT); +// }) +// .catch(err => { +// console.log(err); +// }); diff --git a/backend/src/config/auth.js b/backend/src/config/auth.js new file mode 100644 index 0000000..77c2494 --- /dev/null +++ b/backend/src/config/auth.js @@ -0,0 +1,4 @@ +module.exports = { + secret: "mysecret", + expiresIn: "7d", +}; diff --git a/backend/src/config/dbConfig.js b/backend/src/config/database.js similarity index 94% rename from backend/src/config/dbConfig.js rename to backend/src/config/database.js index 654fd21..808817e 100644 --- a/backend/src/config/dbConfig.js +++ b/backend/src/config/database.js @@ -11,5 +11,5 @@ module.exports = { database: process.env.DB_NAME, username: process.env.DB_USER, password: process.env.DB_PASS, - logging: false, + logging: true, }; diff --git a/backend/src/controllers/SessionController.js b/backend/src/controllers/SessionController.js index 2cc1b8b..b4beb0f 100644 --- a/backend/src/controllers/SessionController.js +++ b/backend/src/controllers/SessionController.js @@ -1,6 +1,6 @@ const { validationResult } = require("express-validator"); -const bcrypt = require("bcryptjs"); const jwt = require("jsonwebtoken"); +const authConfig = require("../config/auth"); const User = require("../models/User"); @@ -9,17 +9,20 @@ exports.store = async (req, res, next) => { const user = await User.findOne({ where: { email: email } }); if (!user) { - return res.status(400).json({ error: "No user found with this email" }); + return res.status(401).json({ error: "No user found with this email" }); } - const isEqual = await bcrypt.compare(password, user.password); - if (!isEqual) { + if (!(await user.checkPassword(password))) { return res.status(401).json({ error: "Password does not match" }); } - const token = jwt.sign({ email: user.email, userId: user.id }, "mysecret", { - expiresIn: "24h", - }); + const token = jwt.sign( + { email: user.email, userId: user.id }, + authConfig.secret, + { + expiresIn: authConfig.expiresIn, + } + ); return res .status(200) diff --git a/backend/src/controllers/UserController.js b/backend/src/controllers/UserController.js index d57e41f..d170845 100644 --- a/backend/src/controllers/UserController.js +++ b/backend/src/controllers/UserController.js @@ -1,5 +1,4 @@ const { validationResult } = require("express-validator"); -const bcrypt = require("bcryptjs"); const User = require("../models/User"); @@ -12,14 +11,7 @@ exports.store = async (req, res, next) => { .json({ error: "Validation failed", data: errors.array() }); } - const { name, password, email } = req.body; - - const hashedPw = await bcrypt.hash(password, 12); - const user = User.build({ - email: email, - password: hashedPw, - name: name, - }); - const result = await user.save(); - res.status(201).json({ message: "User created!", userId: result.id }); + const { name, id, email } = await User.create(req.body); + // const result = await user.save(); + res.status(201).json({ message: "User created!", userId: id }); }; diff --git a/backend/src/database/index.js b/backend/src/database/index.js index 2bf493b..b2416d8 100644 --- a/backend/src/database/index.js +++ b/backend/src/database/index.js @@ -1,6 +1,20 @@ const Sequelize = require("sequelize"); -const dbConfig = require("../config/dbConfig"); +const dbConfig = require("../config/database"); -const sequelize = new Sequelize(dbConfig); +const User = require("../models/User"); -module.exports = sequelize; +const models = [User]; + +class Database { + constructor() { + this.init(); + } + + init() { + this.sequelize = new Sequelize(dbConfig); + + models.map(model => model.init(this.sequelize)); + } +} + +module.exports = new Database(); diff --git a/backend/src/database/migrations/20200717133438-create-users.js b/backend/src/database/migrations/20200717133438-create-users.js new file mode 100644 index 0000000..9685381 --- /dev/null +++ b/backend/src/database/migrations/20200717133438-create-users.js @@ -0,0 +1,39 @@ +"use strict"; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable("Users", { + id: { + type: Sequelize.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false, + }, + name: { + type: Sequelize.STRING, + allowNull: false, + }, + email: { + type: Sequelize.STRING, + allowNull: false, + unique: true, + }, + passwordHash: { + type: Sequelize.STRING, + allowNull: false, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + }, + }); + }, + + down: queryInterface => { + return queryInterface.dropTable("users"); + }, +}; diff --git a/backend/src/middleware/is-auth.js b/backend/src/middleware/is-auth.js index 07d07d6..b9fc728 100644 --- a/backend/src/middleware/is-auth.js +++ b/backend/src/middleware/is-auth.js @@ -1,17 +1,13 @@ const jwt = require("jsonwebtoken"); +const authConfig = require("../config/auth"); module.exports = (req, res, next) => { let decodedToken; - try { - const [, token] = req.get("Authorization").split(" "); - decodedToken = jwt.verify(token, "mysecret"); - // todo >> find user in DB and store in req.user to use latter, or throw an error if user not exists anymore - req.userId = decodedToken.userId; - } catch (err) { - err.statusCode = 401; - err.message = "invalidToken"; - next(err); - } + + const [, token] = req.get("Authorization").split(" "); + decodedToken = jwt.verify(token, authConfig.secret); + // todo >> find user in DB and store in req.user to use latter, or throw an error if user not exists anymore + req.userId = decodedToken.userId; if (!decodedToken) { return res.status(401).json({ message: "Unauthorized" }); diff --git a/backend/src/models/User.js b/backend/src/models/User.js index a6a19a2..d474366 100644 --- a/backend/src/models/User.js +++ b/backend/src/models/User.js @@ -1,17 +1,31 @@ const Sequelize = require("sequelize"); +const bcrypt = require("bcryptjs"); -const sequelize = require("../database"); +class User extends Sequelize.Model { + static init(sequelize) { + super.init( + { + name: { type: Sequelize.STRING }, + password: { type: Sequelize.VIRTUAL }, + passwordHash: { type: Sequelize.STRING }, + email: { type: Sequelize.STRING }, + }, + { + sequelize, + } + ); -const User = sequelize.define("user", { - id: { - type: Sequelize.INTEGER, - allowNull: false, - primaryKey: true, - autoIncrement: true, - }, - name: { type: Sequelize.STRING(100), allowNull: false }, - password: { type: Sequelize.STRING(100), allowNull: false }, - email: { type: Sequelize.STRING(100), allowNull: false }, -}); + this.addHook("beforeSave", async user => { + if (user.password) { + user.passwordHash = await bcrypt.hash(user.password, 8); + } + }); + return this; + } + + checkPassword(password) { + return bcrypt.compare(password, this.passwordHash); + } +} module.exports = User;