From d10967d5c2b2b11860e83320624658496523782b Mon Sep 17 00:00:00 2001 From: irfan-iiitr Date: Wed, 15 May 2024 09:52:01 +0530 Subject: [PATCH 1/3] added email --- config/database.js | 19 ++-- config/emailConfig.js | 12 +++ controllers/authController.js | 1 + controllers/bookingController.js | 5 +- models/user.js | 5 ++ package-lock.json | 144 +++++++++++++++++++++++++++---- package.json | 6 +- utils/emailService.js | 15 ++++ 8 files changed, 183 insertions(+), 24 deletions(-) create mode 100644 config/emailConfig.js create mode 100644 utils/emailService.js diff --git a/config/database.js b/config/database.js index 7b1cc92..5eeaec2 100644 --- a/config/database.js +++ b/config/database.js @@ -1,9 +1,16 @@ -const { Sequelize } = require('sequelize'); require('dotenv').config(); +const Sequelize = require('sequelize'); +const pg = require('pg'); -const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, { - host: process.env.DB_HOST, - dialect: 'postgres', -}); +const sequelize = new Sequelize( + process.env.DB_NAME, + process.env.DB_USER, + process.env.DB_PASSWORD, + { + host: "localhost", + dialect: "postgres", + dialectModule: pg, + } +) -module.exports = sequelize; +module.exports = sequelize; \ No newline at end of file diff --git a/config/emailConfig.js b/config/emailConfig.js new file mode 100644 index 0000000..b7de0e5 --- /dev/null +++ b/config/emailConfig.js @@ -0,0 +1,12 @@ +const nodemailer= require('nodemailer'); + + +const transporter = nodemailer.createTransport({ + service: 'Gmail', + auth: { + user: process.env.process.env.EMAIL_PASS, + pass: process.env.EMAIL_PASS + } +}); + +module.exports = transporter; \ No newline at end of file diff --git a/controllers/authController.js b/controllers/authController.js index ff72b37..be28f44 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -9,6 +9,7 @@ const registerUser = async (req, res) => { const hashedPassword = await bcrypt.hash(req.body.password, 10); const user = await User.create({ username: req.body.username, + email: req.body.email, password: hashedPassword, role: req.body.role }); diff --git a/controllers/bookingController.js b/controllers/bookingController.js index 0fc6f85..245f611 100644 --- a/controllers/bookingController.js +++ b/controllers/bookingController.js @@ -16,6 +16,7 @@ const bookSeat = async (req, res) => { try { const train = await Train.findByPk(train_id, { transaction: t }); if (!train) { + console.log('Could not find train'); await t.rollback(); return res.status(404).json({ message: 'Train not found' }); } @@ -28,7 +29,9 @@ const bookSeat = async (req, res) => { TrainId: train_id }, { transaction: t }); - await t.commit(); + await t.commit(); + + res.status(201).json(booking); } else { await t.rollback(); diff --git a/models/user.js b/models/user.js index b90942d..810bab6 100644 --- a/models/user.js +++ b/models/user.js @@ -7,6 +7,11 @@ const User = sequelize.define('User', { autoIncrement: true, primaryKey: true }, + email:{ + type: DataTypes.STRING, + unique: true, + allowNull: false + }, username: { type: DataTypes.STRING, unique: true, diff --git a/package-lock.json b/package-lock.json index 99b1bad..e8a2588 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,9 +14,13 @@ "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", + "i": "^0.3.7", + "iconv-lite": "^0.6.3", "jsonwebtoken": "^9.0.2", + "nodemailer": "^6.9.13", "pg": "^8.11.5", "pg-hstore": "^2.3.4", + "pg-types": "^4.0.2", "sequelize": "^6.37.3" } }, @@ -185,6 +189,17 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -696,12 +711,20 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/i": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", + "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" @@ -1023,6 +1046,14 @@ } } }, + "node_modules/nodemailer": { + "version": "6.9.13", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.13.tgz", + "integrity": "sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -1064,6 +1095,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -1160,6 +1196,14 @@ "node": ">=4.0.0" } }, + "node_modules/pg-numeric": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", + "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", + "engines": { + "node": ">=4" + } + }, "node_modules/pg-pool": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.2.tgz", @@ -1174,6 +1218,23 @@ "integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==" }, "node_modules/pg-types": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz", + "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", + "dependencies": { + "pg-int8": "1.0.1", + "pg-numeric": "1.0.2", + "postgres-array": "~3.0.1", + "postgres-bytea": "~3.0.0", + "postgres-date": "~2.1.0", + "postgres-interval": "^3.0.0", + "postgres-range": "^1.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pg/node_modules/pg-types": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", @@ -1188,15 +1249,7 @@ "node": ">=4" } }, - "node_modules/pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "dependencies": { - "split2": "^4.1.0" - } - }, - "node_modules/postgres-array": { + "node_modules/pg/node_modules/postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", @@ -1204,7 +1257,7 @@ "node": ">=4" } }, - "node_modules/postgres-bytea": { + "node_modules/pg/node_modules/postgres-bytea": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", @@ -1212,7 +1265,7 @@ "node": ">=0.10.0" } }, - "node_modules/postgres-date": { + "node_modules/pg/node_modules/postgres-date": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", @@ -1220,7 +1273,7 @@ "node": ">=0.10.0" } }, - "node_modules/postgres-interval": { + "node_modules/pg/node_modules/postgres-interval": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", @@ -1231,6 +1284,54 @@ "node": ">=0.10.0" } }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/postgres-array": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-bytea": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "dependencies": { + "obuf": "~1.1.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postgres-date": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz", + "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-interval": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-range": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz", + "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1279,6 +1380,17 @@ "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", diff --git a/package.json b/package.json index ce161da..7f64f40 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "start": "node app.js", - "setdb":"node sync-db.js" + "setdb": "node sync-db.js" }, "keywords": [], "author": "", @@ -16,9 +16,13 @@ "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", + "i": "^0.3.7", + "iconv-lite": "^0.6.3", "jsonwebtoken": "^9.0.2", + "nodemailer": "^6.9.13", "pg": "^8.11.5", "pg-hstore": "^2.3.4", + "pg-types": "^4.0.2", "sequelize": "^6.37.3" } } diff --git a/utils/emailService.js b/utils/emailService.js new file mode 100644 index 0000000..ed36d01 --- /dev/null +++ b/utils/emailService.js @@ -0,0 +1,15 @@ +const transporter = require('../config/emailConfig'); + + +const sendBasicEmail = async (mailFrom, mailTo, mailSubject, mailBody) => { + try { + const response = await transporter.sendMail({ + from: mailFrom, + to: mailTo, + subject: mailSubject, + text: mailBody + }); + } catch (error) { + console.log(error); + } +} \ No newline at end of file From ca0bfa9484b813ee3ba58420c04a01aa9018ac73 Mon Sep 17 00:00:00 2001 From: irfan-iiitr Date: Wed, 15 May 2024 11:20:47 +0530 Subject: [PATCH 2/3] email-service added --- config/emailConfig.js | 2 +- controllers/bookingController.js | 16 +++++++++++++++- utils/emailService.js | 11 ++++++++--- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/config/emailConfig.js b/config/emailConfig.js index b7de0e5..501a1a1 100644 --- a/config/emailConfig.js +++ b/config/emailConfig.js @@ -4,7 +4,7 @@ const nodemailer= require('nodemailer'); const transporter = nodemailer.createTransport({ service: 'Gmail', auth: { - user: process.env.process.env.EMAIL_PASS, + user: process.env.EMAIL_ID, pass: process.env.EMAIL_PASS } }); diff --git a/controllers/bookingController.js b/controllers/bookingController.js index 245f611..ef976d4 100644 --- a/controllers/bookingController.js +++ b/controllers/bookingController.js @@ -2,6 +2,7 @@ const sequelize = require('../config/database'); const Booking = require('../models/booking'); const Train = require('../models/train'); const User = require("../models/user") +const sendBasicEmail = require('../utils/emailService'); const bookSeat = async (req, res) => { const { train_id } = req.body; @@ -20,7 +21,9 @@ const bookSeat = async (req, res) => { await t.rollback(); return res.status(404).json({ message: 'Train not found' }); } + if (train.available_seats > 0) { + train.available_seats -= 1; await train.save({ transaction: t }); @@ -31,7 +34,18 @@ const bookSeat = async (req, res) => { await t.commit(); - + // Send email to the user + try{ + const user = await User.findByPk(userId); + const mailSubject = 'Booking Confirmation'; + const mailBody = `Dear ${user.username},\n\nYour booking has been confirmed. Details:\nBooking ID: ${booking.id}\nBooking Time: ${booking.booking_time}\nTrain Name: ${train.train_name}\nSource: ${train.source}\nDestination: ${train.destination}\n\nThank you for choosing our service.`; + await sendBasicEmail(user.email, mailSubject, mailBody); + console.log('Email sent'); + } + catch(error){ + console.log('Error sending email'); + console.log(error); + } res.status(201).json(booking); } else { await t.rollback(); diff --git a/utils/emailService.js b/utils/emailService.js index ed36d01..fb7dc68 100644 --- a/utils/emailService.js +++ b/utils/emailService.js @@ -1,10 +1,13 @@ const transporter = require('../config/emailConfig'); -const sendBasicEmail = async (mailFrom, mailTo, mailSubject, mailBody) => { +const sendBasicEmail = async ( mailTo, mailSubject, mailBody) => { try { const response = await transporter.sendMail({ - from: mailFrom, + from: { + name: 'IRCTC Backend Service', + address: "irctc-backend-service@gmail.com" + }, to: mailTo, subject: mailSubject, text: mailBody @@ -12,4 +15,6 @@ const sendBasicEmail = async (mailFrom, mailTo, mailSubject, mailBody) => { } catch (error) { console.log(error); } -} \ No newline at end of file +} + +module.exports = sendBasicEmail; \ No newline at end of file From 0ced2f3fecd9c360160ba3d6a1cb8385f413b418 Mon Sep 17 00:00:00 2001 From: irfan-iiitr Date: Wed, 15 May 2024 11:26:55 +0530 Subject: [PATCH 3/3] minor changes --- controllers/bookingController.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/controllers/bookingController.js b/controllers/bookingController.js index ef976d4..28535e9 100644 --- a/controllers/bookingController.js +++ b/controllers/bookingController.js @@ -43,8 +43,7 @@ const bookSeat = async (req, res) => { console.log('Email sent'); } catch(error){ - console.log('Error sending email'); - console.log(error); + console.log('Error sending email',error); } res.status(201).json(booking); } else {