diff --git a/.env b/.env new file mode 100644 index 0000000..29af2ba --- /dev/null +++ b/.env @@ -0,0 +1,9 @@ +PORT=5000 + +AUTOMAILER_ID = "mailerID@mailserver.domain" +AUTOMAILER_APP_PASSWD = "mailerpasswd" + +JWTSECRET="somerandomstring" + +ADMIN_USER = "ADMIN_USER" +ADMIN_PASSWD = "SOME_ADMIN_PASSWD" \ No newline at end of file diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..be4800e --- /dev/null +++ b/.env.development @@ -0,0 +1,5 @@ +DB_USERNAME='your_local_db_username' +DB_PASSWORD='your_local_db_password' +DB_NAME='your_local_db_name' + +CAPTCHA_SECRET = "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe" diff --git a/README.md b/README.md index 02e54d1..0571787 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,18 @@ -# Back-end server template +# Express-Sequelize backend server template -- Run npm i to install all dependencies first -- Env config: .env, .env.development, .env.staging, .env.production -- npm run staging_prep and npm run staging to deploy on Render after configuring a new web service on Render dashboard \ No newline at end of file +### To get started: +- Clone this repo: `git clone https://gitlab.com/ctf-tech-2023/backend-template` +- Reset the git remote repo URL: `git remote rm origin` +- Set new git remote URL: `git remote add origin https://gitlab.com/ctf-tech-2023/new-repo-name` + +### Project setup: + +- Edit `package.json` to reflect the new name and URLs +- Run `npm i` to install all dependencies +- Before running `sequelize-cli` commands while developing, make sure to set `$env:NODE_ENV='development'` on Windows, or `NODE_ENV=development` on Linux/MacOS +- Env config: + - **.env** - All things common to all environments (port, mailer creds, JWT secret, admin data access creds, etc.) + - **.env.development** - Development environment (dev captcha secret, dev DB details) + - **.env.staging** - Staging environment (dev captcha secret, staging DB conn. string) - **for sysadmins** + - **.env.production** - Production environment (production captcha secret, prod DB conn. string) - **for sysadmins** +- Staging: `npm run staging_prep` and `npm run staging` to deploy on Render after configuring a new web service on Render dashboard diff --git a/package-lock.json b/package-lock.json index 6459ebc..0d77d5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { - "name": "induction-api-2023", - "version": "1.0.0", + "name": "backend-template", + "version": "1.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "induction-api-2023", - "version": "1.0.0", + "name": "backend-template", + "version": "1.3.0", "license": "ISC", "dependencies": { "cors": "^2.8.5", @@ -87,14 +87,14 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "14.18.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.32.tgz", - "integrity": "sha512-Y6S38pFr04yb13qqHf8uk1nHE3lXgQ30WZbv1mLliV9pt0NjvqdWttLcrOYLnXbOafknVYRHZGoMSpR9UwfYow==" + "version": "14.18.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.33.tgz", + "integrity": "sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==" }, "node_modules/@types/validator": { - "version": "13.7.9", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.9.tgz", - "integrity": "sha512-y5KJ1PjGXPpU4CZ7lThDu31s+FqvzhqwMOR6Go/x6xaQMFjgzwfzfOvCwABsylr/5n8sB1qFQm1Vi7TaCB8P+A==" + "version": "13.7.10", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.10.tgz", + "integrity": "sha512-t1yxFAR2n0+VO6hd/FJ9F2uezAZVWHLmpmlJzm1eX03+H7+HsuTAp7L8QJs+2pQCfWkP1+EXsGK9Z9v7o/qPVQ==" }, "node_modules/abbrev": { "version": "1.1.1", @@ -1920,9 +1920,9 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/sequelize": { - "version": "6.25.3", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.25.3.tgz", - "integrity": "sha512-sbbvDGft6UfSRdIC0dcZvMxxJYi6g0+IgWvIpTuk6ccEoIyLcr7Sk6nXWwGfkdlDabGeunhhhI4yH8PleVMvtw==", + "version": "6.25.4", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.25.4.tgz", + "integrity": "sha512-gD6RoEVlTKxQh9GC6Qd+pW2A9uhmqeuwBHGMGcZtDg2CchXQhrwS+k6ZnWZ1ggYZ3tUkk4q8fkFL3/XmXnMFFQ==", "funding": [ { "type": "opencollective", @@ -1981,9 +1981,9 @@ } }, "node_modules/sequelize-cli": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.5.1.tgz", - "integrity": "sha512-36hfZKNeZkIshp6L0jPVQ27xNLzgDPpiZokQsvo0M882AtAm+KhGOIViR0BecWb0Xz8+uSq03xxcl7RfMgyIRA==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.5.2.tgz", + "integrity": "sha512-ltXvQOxFFb9pVuDqPJYOS3/X32OVni9zK1S0d0JfloSjmCKZmMDFBWndZbcbJH0QBfyxTt7FLt/kSmKwTRlbsQ==", "dev": true, "dependencies": { "cli-color": "^2.0.3", @@ -2600,14 +2600,14 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "14.18.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.32.tgz", - "integrity": "sha512-Y6S38pFr04yb13qqHf8uk1nHE3lXgQ30WZbv1mLliV9pt0NjvqdWttLcrOYLnXbOafknVYRHZGoMSpR9UwfYow==" + "version": "14.18.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.33.tgz", + "integrity": "sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==" }, "@types/validator": { - "version": "13.7.9", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.9.tgz", - "integrity": "sha512-y5KJ1PjGXPpU4CZ7lThDu31s+FqvzhqwMOR6Go/x6xaQMFjgzwfzfOvCwABsylr/5n8sB1qFQm1Vi7TaCB8P+A==" + "version": "13.7.10", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.10.tgz", + "integrity": "sha512-t1yxFAR2n0+VO6hd/FJ9F2uezAZVWHLmpmlJzm1eX03+H7+HsuTAp7L8QJs+2pQCfWkP1+EXsGK9Z9v7o/qPVQ==" }, "abbrev": { "version": "1.1.1", @@ -4058,9 +4058,9 @@ } }, "sequelize": { - "version": "6.25.3", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.25.3.tgz", - "integrity": "sha512-sbbvDGft6UfSRdIC0dcZvMxxJYi6g0+IgWvIpTuk6ccEoIyLcr7Sk6nXWwGfkdlDabGeunhhhI4yH8PleVMvtw==", + "version": "6.25.4", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.25.4.tgz", + "integrity": "sha512-gD6RoEVlTKxQh9GC6Qd+pW2A9uhmqeuwBHGMGcZtDg2CchXQhrwS+k6ZnWZ1ggYZ3tUkk4q8fkFL3/XmXnMFFQ==", "requires": { "@types/debug": "^4.1.7", "@types/validator": "^13.7.1", @@ -4117,9 +4117,9 @@ } }, "sequelize-cli": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.5.1.tgz", - "integrity": "sha512-36hfZKNeZkIshp6L0jPVQ27xNLzgDPpiZokQsvo0M882AtAm+KhGOIViR0BecWb0Xz8+uSq03xxcl7RfMgyIRA==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.5.2.tgz", + "integrity": "sha512-ltXvQOxFFb9pVuDqPJYOS3/X32OVni9zK1S0d0JfloSjmCKZmMDFBWndZbcbJH0QBfyxTt7FLt/kSmKwTRlbsQ==", "dev": true, "requires": { "cli-color": "^2.0.3", diff --git a/package.json b/package.json index 3fbe2da..78ca6db 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "backend-template", - "version": "1.1.0", - "description": "Template for back-end server using Express, Node, and Sequelize.", + "version": "1.3.0", + "description": "Template for back-end server using Express and Sequelize.", "main": "index.js", "scripts": { "dev": "cross-env NODE_ENV=development nodemon --exitcrash index.js", @@ -13,7 +13,7 @@ "type": "git", "url": "git+https://gitlab.com/ctf-tech-2023/backend-template.git" }, - "author": "", + "author": "Kaushik Ravishankar ", "license": "ISC", "bugs": { "url": "https://gitlab.com/ctf-tech-2023/backend-template/issues" diff --git a/utils/mailer.js b/utils/mailer.js new file mode 100644 index 0000000..73b0619 --- /dev/null +++ b/utils/mailer.js @@ -0,0 +1,45 @@ +const mailer = require("nodemailer"); +const logger = require("./logger")(module); + +// Creates a mailer transporter object with authentication and base config +const transport = mailer.createTransport({ + host: "smtp.gmail.com", + port: 465, + secure: true, + service: "gmail", + auth: { + user: process.env.AUTOMAILER_ID, + pass: process.env.AUTOMAILER_APP_PASSWD, + } +}); + +/** + * Sends a mail from web user to a mail inside organization + * @param {string} mailTarget Target mail - must be within organization + * @param {string} mailSubject Mail subject + * @param {{name: string, email: string, message: string}} userData User details: name, email, and message + */ +const inboundMailer = (mailTarget, mailSubject, userData) => { + if (!mailTarget.endsWith("cegtechforum.in")) { + throw new Error("Invalid target mail domain."); + } + + const message = { + to: mailTarget, + subject: mailSubject, + html: + "

Name: " + userData.name + "

Email: " + userData.email + "


Message:
" + userData.message + "

" + }; + + transport.sendMail(message, (err, info) => { + if (err) { + logger.error("Failure: QUERY mail NOT sent", { err, userData }); + } else { + logger.info("Success: QUERY mail sent", { info }); + } + }); +}; + +module.exports = { + inboundMailer +}