Start using sequelize migrations

This commit is contained in:
canove
2020-07-17 11:40:15 -03:00
parent 77158df3a1
commit a41f7e63ac
12 changed files with 160 additions and 83 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.vscode

7
backend/.sequelizerc Normal file
View File

@@ -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"),
};

View File

@@ -26,12 +26,12 @@
"mysql2": "^2.1.0", "mysql2": "^2.1.0",
"qrcode-terminal": "^0.12.0", "qrcode-terminal": "^0.12.0",
"sequelize": "^5.21.13", "sequelize": "^5.21.13",
"sequelize-cli": "^5.5.1",
"socket.io": "^2.3.0", "socket.io": "^2.3.0",
"whatsapp-web.js": "^1.7.0", "whatsapp-web.js": "^1.7.0",
"youch": "^2.0.10" "youch": "^2.0.10"
}, },
"devDependencies": { "devDependencies": {
"nodemon": "^2.0.4" "nodemon": "^2.0.4",
"sequelize-cli": "^5.5.1"
} }
} }

View File

@@ -1,19 +1,21 @@
require("express-async-errors"); require("express-async-errors");
require("dotenv/config");
require("./database");
const express = require("express"); const express = require("express");
const path = require("path"); const path = require("path");
const Youch = require("youch"); const Youch = require("youch");
const cors = require("cors"); const cors = require("cors");
const sequelize = require("./database/"); // const sequelize = require("./database/");
const multer = require("multer"); const multer = require("multer");
const wBot = require("./libs/wbot"); // const wBot = require("./libs/wbot");
const wbotMessageListener = require("./services/wbotMessageListener"); // const wbotMessageListener = require("./services/wbotMessageListener");
const wbotMonitor = require("./services/wbotMonitor"); // const wbotMonitor = require("./services/wbotMonitor");
const MessagesRoutes = require("./routes/messages"); // const MessagesRoutes = require("./routes/messages");
const ContactsRoutes = require("./routes/contacts"); // const ContactsRoutes = require("./routes/contacts");
const AuthRoutes = require("./routes/auth"); const AuthRoutes = require("./routes/auth");
const WhatsRoutes = require("./routes/whatsapp"); // const WhatsRoutes = require("./routes/whatsapp");
const app = express(); const app = express();
@@ -31,11 +33,16 @@ app.use(express.json());
app.use(multer({ storage: fileStorage }).single("media")); app.use(multer({ storage: fileStorage }).single("media"));
app.use("/public", express.static(path.join(__dirname, "public"))); app.use("/public", express.static(path.join(__dirname, "public")));
app.use(MessagesRoutes);
app.use(ContactsRoutes);
app.use(WhatsRoutes);
app.use("/auth", AuthRoutes); 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) => { app.use(async (err, req, res, next) => {
if (process.env.NODE_ENV === "development") { if (process.env.NODE_ENV === "development") {
const errors = await new Youch(err, req).toJSON(); 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" }); return res.status(500).json({ error: "Internal server error" });
}); });
sequelize // sequelize
.sync() // .sync()
.then(() => { // .then(() => {
const server = app.listen(process.env.PORT); // const server = app.listen(process.env.PORT);
const io = require("./libs/socket").init(server); // const io = require("./libs/socket").init(server);
io.on("connection", socket => { // io.on("connection", socket => {
console.log("Client Connected"); // console.log("Client Connected");
socket.on("joinChatBox", contactId => { // socket.on("joinChatBox", contactId => {
socket.join(contactId); // socket.join(contactId);
}); // });
socket.on("joinNotification", () => { // socket.on("joinNotification", () => {
console.log("chat entrou no canal de notificações"); // console.log("chat entrou no canal de notificações");
socket.join("notification"); // socket.join("notification");
}); // });
socket.on("disconnect", () => { // socket.on("disconnect", () => {
console.log("Client disconnected"); // console.log("Client disconnected");
}); // });
}); // });
wBot.init().then(() => { // wBot.init().then(() => {
wbotMessageListener(); // wbotMessageListener();
wbotMonitor(); // wbotMonitor();
}); // });
console.log("Server started on", process.env.PORT); // console.log("Server started on", process.env.PORT);
}) // })
.catch(err => { // .catch(err => {
console.log(err); // console.log(err);
}); // });

View File

@@ -0,0 +1,4 @@
module.exports = {
secret: "mysecret",
expiresIn: "7d",
};

View File

@@ -11,5 +11,5 @@ module.exports = {
database: process.env.DB_NAME, database: process.env.DB_NAME,
username: process.env.DB_USER, username: process.env.DB_USER,
password: process.env.DB_PASS, password: process.env.DB_PASS,
logging: false, logging: true,
}; };

View File

@@ -1,6 +1,6 @@
const { validationResult } = require("express-validator"); const { validationResult } = require("express-validator");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken"); const jwt = require("jsonwebtoken");
const authConfig = require("../config/auth");
const User = require("../models/User"); const User = require("../models/User");
@@ -9,17 +9,20 @@ exports.store = async (req, res, next) => {
const user = await User.findOne({ where: { email: email } }); const user = await User.findOne({ where: { email: email } });
if (!user) { 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 (!(await user.checkPassword(password))) {
if (!isEqual) {
return res.status(401).json({ error: "Password does not match" }); return res.status(401).json({ error: "Password does not match" });
} }
const token = jwt.sign({ email: user.email, userId: user.id }, "mysecret", { const token = jwt.sign(
expiresIn: "24h", { email: user.email, userId: user.id },
}); authConfig.secret,
{
expiresIn: authConfig.expiresIn,
}
);
return res return res
.status(200) .status(200)

View File

@@ -1,5 +1,4 @@
const { validationResult } = require("express-validator"); const { validationResult } = require("express-validator");
const bcrypt = require("bcryptjs");
const User = require("../models/User"); const User = require("../models/User");
@@ -12,14 +11,7 @@ exports.store = async (req, res, next) => {
.json({ error: "Validation failed", data: errors.array() }); .json({ error: "Validation failed", data: errors.array() });
} }
const { name, password, email } = req.body; const { name, id, email } = await User.create(req.body);
// const result = await user.save();
const hashedPw = await bcrypt.hash(password, 12); res.status(201).json({ message: "User created!", userId: id });
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 });
}; };

View File

@@ -1,6 +1,20 @@
const Sequelize = require("sequelize"); 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();

View File

@@ -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");
},
};

View File

@@ -1,17 +1,13 @@
const jwt = require("jsonwebtoken"); const jwt = require("jsonwebtoken");
const authConfig = require("../config/auth");
module.exports = (req, res, next) => { module.exports = (req, res, next) => {
let decodedToken; let decodedToken;
try {
const [, token] = req.get("Authorization").split(" "); const [, token] = req.get("Authorization").split(" ");
decodedToken = jwt.verify(token, "mysecret"); 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 // 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; req.userId = decodedToken.userId;
} catch (err) {
err.statusCode = 401;
err.message = "invalidToken";
next(err);
}
if (!decodedToken) { if (!decodedToken) {
return res.status(401).json({ message: "Unauthorized" }); return res.status(401).json({ message: "Unauthorized" });

View File

@@ -1,17 +1,31 @@
const Sequelize = require("sequelize"); 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", { this.addHook("beforeSave", async user => {
id: { if (user.password) {
type: Sequelize.INTEGER, user.passwordHash = await bcrypt.hash(user.password, 8);
allowNull: false, }
primaryKey: true, });
autoIncrement: true, return this;
}, }
name: { type: Sequelize.STRING(100), allowNull: false },
password: { type: Sequelize.STRING(100), allowNull: false }, checkPassword(password) {
email: { type: Sequelize.STRING(100), allowNull: false }, return bcrypt.compare(password, this.passwordHash);
}); }
}
module.exports = User; module.exports = User;