diff --git a/.env.sample b/.env.sample index 2c1d8922b..d7c60609e 100644 --- a/.env.sample +++ b/.env.sample @@ -1,3 +1,45 @@ # Mentoring User Service Config -APPLICATION_PORT = 3000 -APPLICATION_ENV = development \ No newline at end of file + +APPLICATION_PORT = 3000 // Port on which service runs + +APPLICATION_ENV = development // Service environment + +MONGODB_URL = mongodb://localhost:27017/elevate-user // Database connectivity url + +SALT_ROUNDS = 10 // Number of rounds for encryption + +ACCESS_TOKEN_SECRET = 'bsj82AHBxahusub12yexlashsbxAXADHBlaj' // Token secret to generate access token + +REFRESH_TOKEN_SECRET = 'baXDUDQ7YEXKH182ELXKJHJKLhasjxlADahgdsd' // Token secret to generate refresh token + +# KAFKA Configurations + +KAFKA_URL = localhost:9092 // Kafka hosted server url +KAFKA_GROUP_ID = userservice // Kafka group to which consumer belongs +KAFKA_TOPIC = // Kafka topic to consume data from +NOTIFICATION_KAFKA_TOPIC = notificationtopic // Kafka topic to push notification data + +# CLOUD STOARGE TYPE + +CLOUD_STORAGE = 'GCP/AWS/AZURE' // Any one of three features available for cloud storage + +# GCP Credentials + +GCP_PATH = 'gcp.json' // Gcp json config file path +DEFAULT_GCP_BUCKET_NAME = 'gcp-bucket-storage-name' // Gcp bucket name which stores files +GCP_PROJECT_ID = 'project-id' // Gcp project id + +# AWS Credentials + +AWS_ACCESS_KEY_ID = 'ashdaqwgeiqwye739182xo1y371xo1237o' // Aws access key id +AWS_SECRET_ACCESS_KEY = '189273bxoyeb1yxliuxb173t71x17x173o1' // Aws secret access key +AWS_BUCKET_REGION = 'ap-south-1' // Aws region where bucket will be located +AWS_BUCKET_ENDPOINT = 's3.ap-south-1.amazonaws.com' // Aws end point +DEFAULT_AWS_BUCKET_NAME = 'aws-bucket-storage-name' // Aws bucket name which stores files + +# AZURE Credentials + +AZURE_ACCOUNT_NAME = 'account-name' // Azure storage account name +AZURE_ACCOUNT_KEY = 'xbad1y381xuhebbi27234724x1yphqbe848hkqje1u3==' // Azure storage account key +DEFAULT_AZURE_CONTAINER_NAME = 'azure-container-storage-name' // Azure storage container which stores files +INTERNAL_ACCESS_TOKEN = 'baXDUDQ7YEXKH182ELXKJHJKLhasjxlADahgdsd' \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6e8cd0dff..89e3de70f 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ build/Release # Dependency directories node_modules +tmp jspm_packages doc .vscode @@ -58,9 +59,13 @@ package-lock.json public/assessment/web public/assessment/web2 +public/tmp .env # Ignore all credentials generics/helpers/credentials/* +gcp.json +gcp1.json + diff --git a/app.js b/app.js index 0ddd29e04..59e315095 100644 --- a/app.js +++ b/app.js @@ -8,12 +8,17 @@ const express = require('express'); const bodyParser = require('body-parser'); const cors = require('cors'); -require("dotenv").config({ path: './.env.sample' }); +const expressFileUpload = require('express-fileupload'); + +require('dotenv').config({ path: './.env' }); +require('./configs'); const app = express(); app.use(cors()); +app.use(expressFileUpload()); + app.use(bodyParser.urlencoded({ extended: true, limit: '50MB' })); app.use(bodyParser.json({ limit: '50MB' })); diff --git a/configs/db-config.js b/configs/db-config.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/configs/elastic-search-config.js b/configs/elastic-search-config.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/configs/index.js b/configs/index.js index 31e579029..8416aa200 100644 --- a/configs/index.js +++ b/configs/index.js @@ -3,4 +3,54 @@ * author : Aman Kumar Gupta * Date : 31-Sep-2021 * Description : Contains connections of all configs - */ \ No newline at end of file + */ + + require("./mongodb")(); + + require("./kafka")(); + const path = require("path"); + const fs = require("fs"); + const requireAll = require("require-all"); + + global.PROJECT_ROOT_DIRECTORY = path.join(__dirname, '..'); + + //load base v1 controllers + const pathToController = PROJECT_ROOT_DIRECTORY + "/controllers/v1/"; + + fs.readdirSync(pathToController).forEach(function (file) { + checkWhetherFolderExistsOrNot(pathToController, file); + }); + + /** +* Check whether folder exists or Not. +* @method +* @name checkWhetherFolderExistsOrNot +* @param {String} pathToFolder - path to folder. +* @param {String} file - File name. +*/ + + function checkWhetherFolderExistsOrNot(pathToFolder, file) { + + let folderExists = fs.lstatSync(pathToFolder + file).isDirectory(); + + if (folderExists) { + fs.readdirSync(pathToFolder + file).forEach(function (folderOrFile) { + checkWhetherFolderExistsOrNot(pathToFolder + file + "/", folderOrFile); + }) + + } else { + if (file.match(/\.js$/) !== null) { + require(pathToFolder + file); + } + } + + } + + + // All controllers + global.controllers = requireAll({ + dirname: PROJECT_ROOT_DIRECTORY + "/controllers", + resolve: function (Controller) { + return new Controller(); + } + }); \ No newline at end of file diff --git a/configs/kafka-config.js b/configs/kafka-config.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/configs/kafka.js b/configs/kafka.js new file mode 100644 index 000000000..b5c9518d6 --- /dev/null +++ b/configs/kafka.js @@ -0,0 +1,50 @@ +/** + * name : configs/kafka + * author : Aman Gupta + * Date : 08-Nov-2021 + * Description : Kafka connection configurations +*/ + +const Kafka = require('kafka-node'); + +module.exports = () => { + const Producer = Kafka.Producer; + const KafkaClient = new Kafka.KafkaClient({ + kafkaHost: process.env.KAFKA_URL + }); + const producer = new Producer(KafkaClient); + + /* Uncomment while writing consuming actions for this service */ + // const Consumer = Kafka.Consumer; + // const consumer = new Consumer(KafkaClient, [ { topic: process.env.KAFKA_TOPIC } ], { autoCommit: true, groupId: process.env.KAFKA_GROUP_ID }) + + /* Registered events */ + + KafkaClient.on('error', error => { + console.log('Kafka connection error: ', error); + }); + + KafkaClient.on('connect', () => { + console.log('Connected to kafka client'); + }); + + producer.on('error', error => { + console.log('Kafka producer intialization error: ', error); + }); + + producer.on('ready', () => { + console.log('Producer intialized successfully'); + }); + + // consumer.on('error', error => { + // console.log('Kafka consumer intialization error: ', error); + // }); + + // consumer.on('message', message => { + // // perform action using message + // }); + + global.kafkaProducer = producer; + global.kafkaClient = KafkaClient; + +}; \ No newline at end of file diff --git a/configs/mongodb.js b/configs/mongodb.js new file mode 100644 index 000000000..68b97c0d9 --- /dev/null +++ b/configs/mongodb.js @@ -0,0 +1,43 @@ +/** + * name : configs/mongodb + * author : Aman + * Date : 07-Oct-2021 + * Description : Mongodb connections configurations +*/ + +const mongoose = require("mongoose"); +const mongoose_autopopulate = require("mongoose-autopopulate"); +const mongoose_timestamp = require("mongoose-timestamp"); +const mongoose_paginate = require('mongoose-paginate-v2'); + +module.exports = function () { + + // Added to remove depreciation warnings from logs. + mongoose.set('useCreateIndex', true) + mongoose.set('useFindAndModify', false) + mongoose.set('useUnifiedTopology', true) + + const db = mongoose.createConnection( + process.env.MONGODB_URL, + { + useNewUrlParser: true + } + ); + + db.on("error", function () { + console.log("Database connection error:") + }); + + db.once("open", function () { + console.log("Connected to DB"); + }); + + mongoose.plugin(mongoose_timestamp, { + createdAt: "createdAt", + updatedAt: "updatedAt" + }); + + mongoose.plugin(mongoose_autopopulate); + mongoose.plugin(mongoose_paginate); + global.db = db; +}; diff --git a/constants/api-responses.js b/constants/api-responses.js index 1b1c7547d..3881ea1b8 100644 --- a/constants/api-responses.js +++ b/constants/api-responses.js @@ -1,3 +1,42 @@ module.exports = { - 'registeredSuccessfully': 'User Registered Successfully' + "EMAIL_INVALID": "Email Id is invalid", + "PASSWORD_INVALID": "Password is invalid", + "USER_ALREADY_EXISTS": "User already exists", + "USER_DOESNOT_EXISTS": "User doesnot exists", + "USER_CREATED_SUCCESSFULLY": "User created successfully", + "LOGGED_IN_SUCCESSFULLY": "User logged in successfully", + "LOGGED_OUT_SUCCESSFULLY": "User logged out successfully", + "UNAUTHORIZED_REQUEST": "Unauthorized request", + "REFRESH_TOKEN_EXPIRED": "Refresh token expired", + "ACCESS_TOKEN_EXPIRED": "Access token expired", + "ACCESS_TOKEN_GENERATED_SUCCESSFULLY": "Access token generated successfully", + "INVALID_REFRESH_TOKEN": "Invalid refresh token", + "REFRESH_TOKEN_NOT_FOUND": "Refresh token not found", + "PROFILE_UPDATED_SUCCESSFULLY": "Profile updated successfully", + "PROFILE_FETCHED_SUCCESSFULLY": "Profile fetched successfully", + "FORM_ALREADY_EXISTS": "Form already exists", + "FORM_CREATED_SUCCESSFULLY": "Form created successfully", + "FORM_UPDATED_SUCCESSFULLY": "Form updated successfully", + "FORM_FETCHED_SUCCESSFULLY": "Form fetched successfully", + "FORM_NOT_FOUND": "Form not found", + "USER_ENTITY_NOT_FOUND": "User entity not found", + "USER_ENTITY_ALREADY_EXISTS": "User entity already exists", + "USER_ENTITY_ALREADY_DELETED": "User entity already deleted", + "USER_ENTITY_CREATED_SUCCESSFULLY": "User entity created successfully", + "USER_ENTITY_UPDATED_SUCCESSFULLY": "User entity updated successfully", + "USER_ENTITY_DELETED_SUCCESSFULLY": "User entity deleted successfully", + "USER_ENTITY_FETCHED_SUCCESSFULLY": "User entity fetched successfully", + "OTP_SENT_SUCCESSFULLY": "Otp sent successfully", + "PASSWORD_RESET_SUCCESSFULLY": "Password reset successfully", + "OTP_INVALID": "Invalid otp", + "SYSTEM_USER_ALREADY_EXISTS": "System User already exists", + "NOT_AN_ADMIN": "Not an admin", + "MENTOR_LIST": "Mentor list fetched successfully", + "FILE_NOT_PROVIDED": "File not provided", + "FILE_UPLOADED_SUCCESSFULLY": "File uploaded successfully", + "SIGNED_URL_GENERATED_SUCCESSFULLY": "Signed Url Generated Successfully", + "INCORRECT_INTERNAL_ACCESS_TOKEN": "Invalid internal access token", + "USER_IS_A_MENTOR":"User has mentor access", + "USER_IS_NOT_A_MENTOR":"User does't have mentor access", + "USER_UPDATED_SUCCESSFULLY": "User successfully updated" }; \ No newline at end of file diff --git a/constants/common.js b/constants/common.js index bd26711e1..86bc40671 100644 --- a/constants/common.js +++ b/constants/common.js @@ -5,19 +5,19 @@ * Description : All commonly used constants through out the service */ -const successResponse = (statusCode = 500, message, data = [], totalCounts = undefined, token = undefined) => { +const successResponse = ({statusCode = 500, responseCode = 'OK', message, result = []}) => { return { statusCode, + responseCode, message, - data, - totalCounts, - token + result } }; -const failureResponse = ({ message = "Oops! Something Went Wrong.", statusCode = 500 }) => { +const failureResponse = ({ message = "Oops! Something Went Wrong.", statusCode = 500, responseCode }) => { const error = new Error(message); error.statusCode = statusCode; + error.responseCode = responseCode; return error; }; @@ -27,5 +27,18 @@ module.exports = { DEFAULT_PAGE_SIZE: 100, }, successResponse, - failureResponse + failureResponse, + guestUrls: [ + '/user/v1/account/login', + '/user/v1/account/create', + '/user/v1/account/generateToken', + '/user/v1/account/generateOtp', + '/user/v1/account/resetPassword', + '/user/v1/systemUsers/create', + '/user/v1/systemUsers/login' + ], + uploadUrls: [ + 'bulkCreateMentors', + '/user/v1/account/verifyMentor' + ] }; \ No newline at end of file diff --git a/constants/end-points.js b/constants/end-points.js deleted file mode 100644 index a88cc7481..000000000 --- a/constants/end-points.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - -}; \ No newline at end of file diff --git a/controllers/v1/account.js b/controllers/v1/account.js new file mode 100644 index 000000000..e89c6712f --- /dev/null +++ b/controllers/v1/account.js @@ -0,0 +1,167 @@ +/** + * name : account.js + * author : Aman + * created-date : 07-Oct-2021 + * Description : User Account. + */ + +// Dependencies +const accountHelper = require("../../services/helper/account"); +const csv = require("csvtojson"); + +module.exports = class Account { + + /** + * create mentee account + * @method + * @name create + * @param {Object} req -request data. + * @returns {JSON} - accounts creation. + */ + + async create(req) { + const params = req.body; + try { + const createdAccount = await accountHelper.create(params); + return createdAccount; + } catch (error) { + return error; + } + } + + /** + * login user account + * @method + * @name login + * @param {Object} req -request data. + * @returns {JSON} - login details. + */ + + async login(req) { + const params = req.body; + try { + const loggedInAccount = await accountHelper.login(params); + return loggedInAccount; + } catch (error) { + return error; + } + } + + /** + * logout user account + * @method + * @name create + * @param {Object} req -request data. + * @returns {JSON} - accounts loggedout. + */ + + async logout(req) { + const params = req.body; + params.loggedInId = req.decodedToken._id; + try { + const loggedOutAccount = await accountHelper.logout(params); + return loggedOutAccount; + } catch (error) { + return error; + } + } + + /** + * regenerate access token + * @method + * @name regenerate + * @param {Object} req -request data. + * @returns {JSON} - access token info + */ + + async generateToken(req) { + const params = req.body; + try { + const createdToken = await accountHelper.generateToken(params); + return createdToken; + } catch (error) { + return error; + } + } + + /** + * generate otp + * @method + * @name generateOtp + * @param {Object} req -request data. + * @returns {JSON} - otp success response + */ + + async generateOtp(req) { + const params = req.body; + try { + const result = await accountHelper.generateOtp(params); + return result; + } catch (error) { + return error; + } + } + + /** + * Reset password + * @method + * @name generateOtp + * @param {Object} req -request data. + * @returns {JSON} - password reset response + */ + + async resetPassword(req) { + const params = req.body; + try { + const result = await accountHelper.resetPassword(params); + return result; + } catch (error) { + return error; + } + } + + /** + * Bulk create mentors + * @method + * @name bulkCreateMentors + * @param {Object} req -request data. + * @returns {CSV} - created mentors. + */ + + async bulkCreateMentors(req) { + try { + const mentors = await csv().fromString(req.files.mentors.data.toString()); + const createdMentors = await accountHelper.bulkCreateMentors(mentors,req.decodedToken); + return createdMentors; + } catch (error) { + return error; + } + } + + /** + * Reset password + * @method + * @name verifyMentor + * @param {Object} req -request data. + * @returns {JSON} - verifies user is mentor or not + */ + + + async verifyMentor(req) { + try { + const result = await accountHelper.verifyMentor(req.query.userId); + return result; + } catch (error) { + return error; + } + } + + async acceptTermsAndCondition(req) { + try { + const result = await accountHelper.acceptTermsAndCondition(req.decodedToken._id); + return result; + } catch (error) { + return error; + } + } +} \ No newline at end of file diff --git a/controllers/v1/cloud-services/file.js b/controllers/v1/cloud-services/file.js new file mode 100644 index 000000000..7e261fb7a --- /dev/null +++ b/controllers/v1/cloud-services/file.js @@ -0,0 +1,77 @@ +/** + * name : gcp.js + * author : Aman Gupta + * created-date : 09-Nov-2021 + * Description : Google cloud services methods. + */ +const path = require('path'); + +const httpStatusCode = require("../../../generics/http-status"); +const apiResponses = require("../../../constants/api-responses"); +const common = require('../../../constants/common'); +const filesHelpers = require('../../../generics/files-helper'); +const utils = require('../../../generics/utils'); + +module.exports = class File { + + /** + * Upload file + * @method + * @name upload + * @param {Request} - req request body. + * @param {files} - req.files.file - actual file to upload + * @returns {JSON} - Response with status message and result. + */ + async upload(req) { + try { + if (req.files && req.files.file) { + const filePath = path.join(__dirname, '../../../', req.files.file.tempFilePath); + const destFileName = new Date().getTime() + req.files.file.name; + let response; + let imageUrl; + if (process.env.CLOUD_STORAGE === 'GCP') { + response = await filesHelpers.uploadFileInGcp(filePath, destFileName); + imageUrl = `https://storage.googleapis.com/${response.bucket}/${response.name}`; + } else if (process.env.CLOUD_STORAGE === 'AWS') { + response = await filesHelpers.uploadFileInAws(filePath, destFileName); + imageUrl = response.Location; + } else if (process.env.CLOUD_STORAGE === 'AZURE') { + response = await filesHelpers.uploadFileInAzure(filePath, destFileName); + imageUrl = `https://${response.accountName}.blob.core.windows.net/${response.containerName}/${destFileName}`; + } + utils.clearFile(filePath); + return common.successResponse({ message: apiResponses.FILE_UPLOADED_SUCCESSFULLY, statusCode: httpStatusCode.ok, responseCode: 'OK', result: { fileName: destFileName, fileLocation: imageUrl } }); + } else { + return common.failureResponse({ message: apiResponses.FILE_NOT_PROVIDED, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + } catch (error) { + return error; + } + } + + /** + * Get Signed Url + * @method + * @name getSignedUrl + * @param {JSON} req request body. + * @returns {JSON} Response with status message and result. + */ + async getSignedUrl(req) { + try { + const destFilePath = `users/${req.decodedToken._id}-${new Date().getTime()}-${req.query.fileName}`; + let response; + if (process.env.CLOUD_STORAGE === 'GCP') { + response = await filesHelpers.getGcpSignedUrl(destFilePath); + } else if (process.env.CLOUD_STORAGE === 'AWS') { + response = await filesHelpers.getAwsSignedUrl(destFilePath); + } else if (process.env.CLOUD_STORAGE === 'AZURE') { + response = await filesHelpers.getAzureSignedUrl(destFilePath); + } + response.destFilePath = destFilePath + return common.successResponse({ message: apiResponses.SIGNED_URL_GENERATED_SUCCESSFULLY, statusCode: httpStatusCode.ok, responseCode: 'OK', result: response }); + } catch (error) { + return error; + } + } + +} \ No newline at end of file diff --git a/controllers/v1/form.js b/controllers/v1/form.js new file mode 100644 index 000000000..c6fb08cbf --- /dev/null +++ b/controllers/v1/form.js @@ -0,0 +1,66 @@ +/** + * name : form.js + * author : Aman Gupta + * created-date : 03-Nov-2021 + * Description : Form Controller. + */ + +// Dependencies +const formsHelper = require("../../services/helper/form"); + +module.exports = class Form { + + /** + * create users form + * @method + * @name create + * @param {Object} req -request data. + * @returns {JSON} - forms creation object. + */ + + async create(req) { + const params = req.body; + try { + const createdForm = await formsHelper.create(params); + return createdForm; + } catch (error) { + return error; + } + } + + /** + * update users form + * @method + * @name update + * @param {Object} req - request data. + * @returns {JSON} - forms updation response. + */ + + async update(req) { + const params = req.body; + try { + const updatedForm = await formsHelper.update(params); + return updatedForm; + } catch (error) { + return error; + } + } + + /** + * reads user form + * @method + * @name read + * @param {Object} req -request data. + * @returns {JSON} - form object. + */ + + async read(req) { + const params = req.body; + try { + const form = await formsHelper.read(params); + return form; + } catch (error) { + return error; + } + } +} \ No newline at end of file diff --git a/controllers/v1/mentors.js b/controllers/v1/mentors.js new file mode 100644 index 000000000..8885b9c39 --- /dev/null +++ b/controllers/v1/mentors.js @@ -0,0 +1,29 @@ +/** + * name : mentors.js + * author : Aman + * created-date : 10-Nov-2021 + * Description : User mentors + */ + +// Dependencies +const mentorsHelper = require("../../services/helper/mentors"); + +module.exports = class Mentors { + + /** + * List of mentors + * @method + * @name list + * @param {Object} req -request data. + * @returns {Array} - Mentors + */ + + async list(req) { + try { + const mentors = await mentorsHelper.list(req.pageNo,req.pageSize,req.searchText); + return mentors; + } catch (error) { + return error; + } + } +} \ No newline at end of file diff --git a/controllers/v1/profile.js b/controllers/v1/profile.js index e69de29bb..c9a86876e 100644 --- a/controllers/v1/profile.js +++ b/controllers/v1/profile.js @@ -0,0 +1,47 @@ +/** + * name : profile.js + * author : Aman + * created-date : 02-Nov-2021 + * Description : User Profile. + */ + +// Dependencies +const profileHelper = require("../../services/helper/profile"); + +module.exports = class Profile { + + /** + * Updates user profile + * @method + * @name update + * @param {Object} req -request data. + * @returns {JSON} - response data. + */ + + async update(req) { + const params = req.body; + try { + const updatedProfile = await profileHelper.update(params, req.decodedToken._id); + return updatedProfile; + } catch (error) { + return error; + } + } + + /** + * User profile details + * @method + * @name details + * @param {Object} req -request data. + * @returns {JSON} - profile details. + */ + + async details(req) { + try { + const profileDetails = await profileHelper.details(req.params.id ? req.params.id : req.decodedToken._id); + return profileDetails; + } catch (error) { + return error; + } + } +} \ No newline at end of file diff --git a/controllers/v1/systemUsers.js b/controllers/v1/systemUsers.js new file mode 100644 index 000000000..aa98efedb --- /dev/null +++ b/controllers/v1/systemUsers.js @@ -0,0 +1,48 @@ +/** + * name : systemUsers.js + * author : Aman + * created-date : 10-Nov-2021 + * Description : System User Create account. + */ + +// Dependencies +const systemUsersHelper = require("../../services/helper/systemUsers"); + +module.exports = class SystemUsers { + + /** + * create system users + * @method + * @name create + * @param {Object} req -request data. + * @returns {JSON} - accounts creation. + */ + + async create(req) { + const params = req.body; + try { + const createdAccount = await systemUsersHelper.create(params); + return createdAccount; + } catch (error) { + return error; + } + } + + /** + * login system user + * @method + * @name login + * @param {Object} req -request data. + * @returns {JSON} - login details. + */ + + async login(req) { + const params = req.body; + try { + const loggedInAccount = await systemUsersHelper.login(params); + return loggedInAccount; + } catch (error) { + return error; + } + } +} \ No newline at end of file diff --git a/controllers/v1/user.js b/controllers/v1/user.js deleted file mode 100644 index 7da6bce01..000000000 --- a/controllers/v1/user.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * name : controllers/v1/user/User - * author : Aman Kumar Gupta - * Date : 30-Sep-2021 - * Description : User controller to process the data - */ - - const UserService = require('../../core-services/v1/user/user'); - - class User { - - async register (req) { - console.log('Register Triggered'); - const serviceResponse = await UserService.register(); - return serviceResponse; - } - - login () { - - } - }; - - module.exports = new User(); \ No newline at end of file diff --git a/controllers/v1/userentity.js b/controllers/v1/userentity.js new file mode 100644 index 000000000..3f311302c --- /dev/null +++ b/controllers/v1/userentity.js @@ -0,0 +1,107 @@ +/** + * name : userentity.js + * author : Aman Gupta + * created-date : 04-Nov-2021 + * Description : User Entity Controller. + */ + +// Dependencies +const userEntityHelper = require("../../services/helper/userentity"); + +module.exports = class UserEntity { + + /** + * @api {post} /user/v1/userentity/create + * @apiVersion 1.0.0 + * @apiName Creates User Entity + * @apiGroup userentity + * @apiParamExample {json} Request-Body: + * { + * "value": "DO", + * "label": "District Official", + * "type": "roles" + * } + * @apiSampleRequest /user/v1/form/create + * @apiParamExample {json} Response: + * { + * "responseCode": 'OK', + * "message": "User entity created successfully", + * "result": [] + * } + * @apiUse successBody + * @apiUse errorBody + */ + + /** + * create user entity + * @method + * @name create + * @param {Object} req -request data. + * @returns {JSON} - user entities creation object. + */ + + async create(req) { + const params = req.body; + try { + const createdUserEntity = await userEntityHelper.create(params, req.decodedToken._id); + return createdUserEntity; + } catch (error) { + return error; + } + } + + /** + * updates user entity + * @method + * @name update + * @param {Object} req - request data. + * @returns {JSON} - user entities updation response. + */ + + async update(req) { + const params = req.body; + const _id = req.params.id + try { + const updatedEntity = await userEntityHelper.update(params, _id, req.decodedToken._id); + return updatedEntity; + } catch (error) { + return error; + } + } + + /** + * reads user entities + * @method + * @name read + * @param {Object} req - request data. + * @returns {JSON} - user entities. + */ + + async read(req) { + const params = req.query; + try { + const form = await userEntityHelper.read(params); + return form; + } catch (error) { + return error; + } + } + + /** + * deletes user entity + * @method + * @name delete + * @param {Object} req - request data. + * @returns {JSON} - user entities deletion response. + */ + + async delete(req) { + const _id = req.params.id + try { + const updatedEntity = await userEntityHelper.delete(_id); + return updatedEntity; + } catch (error) { + return error; + } + } +} \ No newline at end of file diff --git a/controllers/v2/user.js b/controllers/v2/user.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/core-services/v1/profile/profile.js b/core-services/v1/profile/profile.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/core-services/v1/profile/profile.test.js b/core-services/v1/profile/profile.test.js deleted file mode 100644 index f218c1a1e..000000000 --- a/core-services/v1/profile/profile.test.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * name : core-services/v1/profile/profile.test - * author : Aman Kumar Gupta - * Date : 01-Oct-2021 - * Description : Contains unit test cases for profile service - */ \ No newline at end of file diff --git a/core-services/v1/user/user.js b/core-services/v1/user/user.js deleted file mode 100644 index 423c66edf..000000000 --- a/core-services/v1/user/user.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * name : core-services/v1/user/user/UserService - * author : Aman Kumar Gupta - * Date : 30-Sep-2021 - * Description : User service containing core business logic - */ - -const { successResponse, failureResponse } = require('../../../constants/common'); -const httpStatus = require('../../../constants/http-status'); -const apiResponses = require('../../../constants/api-responses'); - -module.exports = new class UserService { - - async register() { - try { - console.log('Register Service Triggered'); - /* Enable this to check error flow */ - // throw failureResponse({ message: 'Test Error Not Found', statusCode: httpStatus.bad_request }); - - return successResponse(httpStatus.created, apiResponses.registeredSuccessfully); - } catch (error) { - return error; - } - } - - login() { - - } -}; \ No newline at end of file diff --git a/core-services/v1/user/user.test.js b/core-services/v1/user/user.test.js deleted file mode 100644 index 634ff9124..000000000 --- a/core-services/v1/user/user.test.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * name : core-services/v1/user/user.test - * author : Aman Kumar Gupta - * Date : 01-Oct-2021 - * Description : Contains unit test cases for user service - */ \ No newline at end of file diff --git a/core-services/v2/user/user.js b/core-services/v2/user/user.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/core-services/v2/user/user.test.js b/core-services/v2/user/user.test.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/db/forms/model.js b/db/forms/model.js new file mode 100644 index 000000000..43d2565c8 --- /dev/null +++ b/db/forms/model.js @@ -0,0 +1,42 @@ +/** + * name : db/forms/model + * author : Aman Gupta + * Date : 03-Nov-2021 + * Description : Forms schema + */ + +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; + +const formSchema = new Schema({ + type: { + type: String, + required: true + }, + subType: { + type: String, + required: true + }, + action: { + type: String, + required: true + }, + ver: { + type: String, + required: true + }, + data: { + templateName: { + type: String, + required: true + }, + fields: { + type: Object, + required: true + } + } +}); + +const Forms = db.model("forms", formSchema); + +module.exports = Forms; \ No newline at end of file diff --git a/db/forms/queries.js b/db/forms/queries.js new file mode 100644 index 000000000..5fc25e809 --- /dev/null +++ b/db/forms/queries.js @@ -0,0 +1,50 @@ +/** + * name : models/forms/query + * author : Aman karki + * Date : 07-Oct-2021 + * Description : Users database operations + */ + +const Forms = require("./model"); + +module.exports = class FormsData { + + static createForm(data) { + return new Promise(async (resolve, reject) => { + try { + await (new Forms(data)).save(); + resolve(true) + } catch (error) { + reject(error); + } + }); + } + + static findOneForm(filter, projection = {}) { + return new Promise(async (resolve,reject) => { + try { + const formData = await Forms.findOne(filter, projection); + resolve(formData); + } catch(error) { + reject(error); + } + }) + } + + static updateOneForm(filter, update, options = {}) { + return new Promise(async (resolve, reject) => { + try { + const res = await Forms.updateOne(filter, update, options); + if (res.n === 1 && res.nModified === 1) { + resolve('ENTITY_UPDATED') + } else if (res.n === 1 && res.nModified === 0){ + resolve('ENTITY_ALREADY_EXISTS') + } else { + resolve('ENTITY_NOT_FOUND'); + } + } catch (error) { + reject(error); + } + }); + } +} diff --git a/db/systemUsers/model.js b/db/systemUsers/model.js new file mode 100644 index 000000000..25659b89a --- /dev/null +++ b/db/systemUsers/model.js @@ -0,0 +1,38 @@ +/** + * name : db/users/model + * author : Aman Karki + * Date : 10-Nov-2021 + * Description : System User schema data + */ + + const mongoose = require('mongoose'); + const Schema = mongoose.Schema; + + const userSchema = new Schema({ + email: { + address: { + type: String, + index: { + unique: true + }, + required: true + }, + verified: { + type: Boolean, + default: false + } + }, + password: { + type: String, + required: true + }, + name: { + type: String, + required: true + }, + role: String + }); + + const SystemUsers = db.model("systemUsers", userSchema); + + module.exports = SystemUsers; \ No newline at end of file diff --git a/db/systemUsers/queries.js b/db/systemUsers/queries.js new file mode 100644 index 000000000..ce6389767 --- /dev/null +++ b/db/systemUsers/queries.js @@ -0,0 +1,33 @@ +/** + * name : models/systemUsers/queries + * author : Aman karki + * Date : 07-Oct-2021 + * Description : System Users database operations + */ + +const SystemUsers = require("./model"); + +module.exports = class SystemUsersData { + + static findUsersByEmail(email) { + return new Promise(async (resolve,reject) => { + try { + const userData = await SystemUsers.findOne({'email.address': email}).lean(); + resolve(userData); + } catch(error) { + reject(error); + } + }) + } + + static create(data) { + return new Promise(async (resolve, reject) => { + try { + await (new SystemUsers(data)).save(); + resolve(true) + } catch (error) { + reject(error); + } + }); + } +} diff --git a/db/userentities/model.js b/db/userentities/model.js new file mode 100644 index 000000000..d30c6ff75 --- /dev/null +++ b/db/userentities/model.js @@ -0,0 +1,45 @@ +/** + * name : db/userentities/model + * author : Aman Gupta + * Date : 04-Nov-2021 + * Description : User Entity schema + */ +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; + +const userEntitySchema = new Schema({ + value: { + type: String, + required: true + }, + label: { + type: String, + required: true + }, + status: { + type: String, + default: 'ACTIVE', + required: true + }, + deleted: { + type: Boolean, + default: false, + required: true + }, + type: { + type: String, + required: true + }, + createdBy: { + type: mongoose.Types.ObjectId, + required: true + }, + updatedBy: { + type: mongoose.Types.ObjectId, + required: true + } +}); + +const UserEntities = db.model("userEntities", userEntitySchema); + +module.exports = UserEntities; \ No newline at end of file diff --git a/db/userentities/query.js b/db/userentities/query.js new file mode 100644 index 000000000..3cf38404c --- /dev/null +++ b/db/userentities/query.js @@ -0,0 +1,61 @@ +/** + * name : models/entities/query + * author : Aman Gupta + * Date : 04-Nov-2021 + * Description : Users entities database operations + */ + +const UserEntities = require("./model"); + +module.exports = class UserEntityData { + + static createEntity(data) { + return new Promise(async (resolve, reject) => { + try { + await (new UserEntities(data)).save(); + resolve(true) + } catch (error) { + reject(error); + } + }); + } + + static findOneEntity(filter, projection = {}) { + return new Promise(async (resolve, reject) => { + try { + const userEntityData = await UserEntities.findOne(filter, projection); + resolve(userEntityData); + } catch (error) { + reject(error); + } + }) + } + + static findAllEntities(filter, projection = {}) { + return new Promise(async (resolve, reject) => { + try { + const userEntitiesData = await UserEntities.find(filter, projection); + resolve(userEntitiesData); + } catch (error) { + reject(error); + } + }) + } + + static updateOneEntity(filter, update, options = {}) { + return new Promise(async (resolve, reject) => { + try { + const res = await UserEntities.updateOne(filter, update, options); + if (res.n === 1 && res.nModified === 1) { + resolve('ENTITY_UPDATED') + } else if (res.n === 1 && res.nModified === 0) { + resolve('ENTITY_ALREADY_EXISTS') + } else { + resolve('ENTITY_NOT_FOUND'); + } + } catch (error) { + reject(error); + } + }); + } +} diff --git a/db/users/model.js b/db/users/model.js new file mode 100644 index 000000000..25a99814f --- /dev/null +++ b/db/users/model.js @@ -0,0 +1,64 @@ +/** + * name : db/users/model + * author : Aman Karki + * Date : 07-Oct-2021 + * Description : User schema data + */ + +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; + +const userSchema = new Schema({ + email: { + address: { + type: String, + index: { + unique: true + }, + required: true + }, + verified: { + type: Boolean, + default: false + } + }, + password: { + type: String, + required: true + }, + name: { + type: String, + required: true + }, + gender: String, + designation: [{ value: String, label: String }], + location: [{ value: String, label: String }], + about: String, + areasOfExpertise: [{ value: String, label: String }], + image: String, + experience: String, + lastLoggedInAt: Date, + isAMentor: { + type: Boolean, + default: false, + index: true + }, + hasAcceptedTAndC: { + type: Boolean, + default: false + }, + deleted: { + type: Boolean, + default: false, + required: true + }, + refreshTokens: [{ token: String, exp: Number }], + otpInfo: { + otp: Number, + exp: Number + } +}); + +const Users = db.model("users", userSchema); + +module.exports = Users; \ No newline at end of file diff --git a/db/users/queries.js b/db/users/queries.js new file mode 100644 index 000000000..344b5dd0f --- /dev/null +++ b/db/users/queries.js @@ -0,0 +1,99 @@ +/** + * name : models/users/query + * author : Aman karki + * Date : 07-Oct-2021 + * Description : Users database operations + */ + +const Users = require("./model"); + +module.exports = class UsersData { + + static findOne(filter, projection = {}) { + return new Promise(async (resolve,reject) => { + try { + const userData = await Users.findOne(filter, projection); + resolve(userData); + } catch(error) { + reject(error); + } + }) + } + + static createUser(data) { + return new Promise(async (resolve, reject) => { + try { + await (new Users(data)).save(); + resolve(true) + } catch (error) { + reject(error); + } + }); + } + + static updateOneUser(filter, update, options = {}) { + return new Promise(async (resolve, reject) => { + try { + const res = await Users.updateOne(filter, update, options); + if (res.ok === 1 && res.nModified === 1) { + resolve(true) + } else { + resolve(false) + } + } catch (error) { + reject(error); + } + }); + } + + static searchMentors(page,limit,search) { + return new Promise(async (resolve, reject) => { + try { + + let users = await Users.aggregate([ + { + $match: { + deleted: false, + isAMentor: true, + $or: [ + { name: new RegExp(search, 'i') } + ] + }, + }, + { + $sort: {"name": 1} + }, + { + $project: { + name: 1, + image: 1, + areasOfExpertise: 1 + } + }, + { + $facet: { + "totalCount": [ + { "$count": "count" } + ], + "data": [ + { $skip: limit * (page - 1) }, + { $limit: limit } + ], + } + }, { + $project: { + "data": 1, + "count": { + $arrayElemAt: ["$totalCount.count", 0] + } + } + } + ]); + + return resolve(users); + } catch (error) { + return reject(error); + } + }) + } +} diff --git a/generics/file-stream.js b/generics/file-stream.js new file mode 100644 index 000000000..60ba55392 --- /dev/null +++ b/generics/file-stream.js @@ -0,0 +1,71 @@ +/** + * name : file-stream.js + * author : Aman Karki + * Date : 13-July-2020 + * Description : json2csvtransform (Streaming API). + */ + +// Dependencies +const json2Csv = require('json2csv').Transform; +const stream = require("stream"); +const fs = require("fs"); +const moment = require("moment-timezone"); + +/** + * FileStream + * @class +*/ + +let FileStream = class FileStream { + + constructor(fileName) { + const currentDate = new Date(); + const fileExtensionWithTime = moment(currentDate).tz("Asia/Kolkata").format("YYYY_MM_DD_HH_mm") + ".csv"; + + if( !fs.existsSync("public")) { + fs.mkdirSync("public"); + } + + if( !fs.existsSync("public" + "/" + "reports")) { + fs.mkdirSync("public" + "/" + "reports"); + } + const filePath = `${"public"}/${"reports"}/${moment(currentDate).tz("Asia/Kolkata").format("YYYY_MM_DD")}/`; + this.ensureDirectoryPath(filePath); + this.input = new stream.Readable({ objectMode: true }); + this.fileName = filePath + fileName + "_" + fileExtensionWithTime; + this.output = fs.createWriteStream(this.fileName, { encoding: 'utf8' }); + this.processor = null; + } + + initStream() { + this.input._read = () => { }; + const opts = {}; + const transformOpts = { objectMode: true }; + const json2csv = new json2Csv(opts, transformOpts); + this.processor = this.input.pipe(json2csv).pipe(this.output); + return this.input; + } + + getProcessorPromise() { + const processor = this.processor; + return new Promise(function (resolve, reject) { + processor.on('finish', resolve); + }); + } + + fileNameWithPath() { + return this.fileName; + } + + ensureDirectoryPath(filePath) { + try { + fs.mkdirSync(filePath, { recursive: true }); + } catch (err) { + console.log(err) + if (err.code !== 'EEXIST') throw err + } + } + +}; + +module.exports = FileStream; diff --git a/generics/files-helper.js b/generics/files-helper.js new file mode 100644 index 000000000..d7509b9a9 --- /dev/null +++ b/generics/files-helper.js @@ -0,0 +1,193 @@ +/** + * name : generics/files-helper.js + * author : Aman Gupta + * created-date : 09-Nov-2021 + * Description : cloud services helpers methods. +*/ + +const path = require('path'); +const fs = require('fs'); + +const { Storage } = require('@google-cloud/storage'); +const S3 = require('aws-sdk/clients/s3'); +const { BlobServiceClient, generateBlobSASQueryParameters, BlobSASPermissions, StorageSharedKeyCredential } = require('@azure/storage-blob'); + +module.exports = class FilesHelper { + + /** + * Upload file to GCP + * @method + * @name uploadFileInGcp + * @param {string} filePath - Stored file path in file system. + * @param {string} destFileName - fileName to be saved in gc + * @param {string} bucketName - cloud storage location in which file gets saved + * @returns {Promise} Uploaded json result. + */ + static async uploadFileInGcp(filePath, destFileName, bucketName) { + const storage = new Storage({ + projectId: process.env.GCP_PROJECT_ID, + keyFilename: path.join(__dirname, '../', process.env.GCP_PATH) + }); + bucketName = bucketName || process.env.DEFAULT_GCP_BUCKET_NAME; + try { + const uploadedFile = await storage.bucket(bucketName).upload(filePath, { + destination: destFileName, + metadata: {} + }); + return uploadedFile[0].metadata; + } catch (error) { + error = new Error(error.response.data.error_description); + error.statusCode = 500; + throw error; + } + + } + + static async getGcpSignedUrl(destFilePath, bucketName, actionType = 'write') { + const storage = new Storage({ + projectId: process.env.GCP_PROJECT_ID, + keyFilename: path.join(__dirname, '../', process.env.GCP_PATH) + }); + bucketName = bucketName || process.env.DEFAULT_GCP_BUCKET_NAME; + const bucket = storage.bucket(bucketName); + const file = bucket.file(destFilePath); + const expiry = Date.now() + 1000 * 60 * 30 // 30 Min + + try { + const signedUrl = await file.getSignedUrl({ + action: actionType, + expires: expiry, + contentType: 'multipart/form-data' + }); + return { signedUrl: signedUrl[0] } + } catch (error) { + throw error; + } + } + + /** + * Upload file to AWS + * @method + * @name uploadFileInAws + * @param {string} filePath - Stored file path in file system. + * @param {string} destFileName - fileName to be saved in aws + * @param {string} bucketName - cloud storage location in which file gets saved + * @returns {Promise} - Upload result. + */ + static async uploadFileInAws(filePath, destFileName, bucketName) { + const s3 = new S3({ + accessKeyId: process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + signatureVersion: 'v4', + region: process.env.AWS_BUCKET_REGION + }); + bucketName = bucketName || process.env.DEFAULT_AWS_BUCKET_NAME; + + // Read content from the file as buffer + const fileContent = fs.readFileSync(filePath); + + try { + const uploadedFile = await s3.upload({ + Bucket: bucketName, + Key: destFileName, + Body: fileContent + }).promise(); + return uploadedFile; + } catch (error) { + throw error; + } + + } + + static async getAwsSignedUrl(destFilePath, bucketName, actionType = 'putObject') { + const s3 = new S3({ + accessKeyId: process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + signatureVersion: 'v4', + region: process.env.AWS_BUCKET_REGION + }); + bucketName = bucketName || process.env.DEFAULT_AWS_BUCKET_NAME; + const expiry = 30 * 60; // In seconds, 30 Min + + try { + const signedUrl = await s3.getSignedUrlPromise(actionType, { + Bucket: bucketName, + Key: destFilePath, + Expires: expiry + }); + return { signedUrl }; + } catch (error) { + throw error; + } + } + + /** + * Upload file to AZURE + * @method + * @name uploadFileInAzure + * @param {string} filePath - Stored file path in directory (project). + * @param {string} destFileName - fileName to be saved in azure + * @param {string} containerName - cloud storage container in which file gets saved + * @returns {Promise} - uploadedBlobResponse + */ + static async uploadFileInAzure(filePath, destFileName, containerName) { + containerName = containerName || process.env.DEFAULT_AZURE_CONTAINER_NAME; + + const sharedKeyCredential = new StorageSharedKeyCredential(process.env.AZURE_ACCOUNT_NAME, process.env.AZURE_ACCOUNT_KEY); + + // Create the BlobServiceClient object which will be used to create a container client + const blobServiceClient = new BlobServiceClient( // The storage account used via blobServiceClient + `https://${process.env.AZURE_ACCOUNT_NAME}.blob.core.windows.net`, + sharedKeyCredential + ); + + const containerClient = blobServiceClient.getContainerClient(containerName); + // const content = fs.readFileSync(filePath); + const blobName = destFileName; + const blockBlobClient = containerClient.getBlockBlobClient(blobName); + + try { + const uploadBlobResponse = await blockBlobClient.uploadFile(filePath); + uploadBlobResponse.containerName = containerName; + uploadBlobResponse.accountName = process.env.AZURE_ACCOUNT_NAME; + return uploadBlobResponse; + } catch (error) { + error = new Error(error.message); + error.statusCode = 500; + throw error; + } + + } + + static async getAzureSignedUrl(destFilePath, containerName) { + containerName = containerName || process.env.DEFAULT_AZURE_CONTAINER_NAME; + + const sharedKeyCredential = new StorageSharedKeyCredential(process.env.AZURE_ACCOUNT_NAME, process.env.AZURE_ACCOUNT_KEY); + + const blobServiceClient = new BlobServiceClient( + `https://${process.env.AZURE_ACCOUNT_NAME}.blob.core.windows.net`, + sharedKeyCredential + ); + + const containerClient = blobServiceClient.getContainerClient(containerName); + + const startDate = new Date(); + + const expiryDate = new Date(startDate); + expiryDate.setMinutes(startDate.getMinutes() + 30); + + let sasToken = generateBlobSASQueryParameters({ + containerName: containerName, + blobName: destFilePath, + permissions: BlobSASPermissions.parse("w"), + startsOn: startDate, + expiresOn: expiryDate, + contentType: 'mulitpart/form-data' + }, sharedKeyCredential).toString(); + + const signedUrl = containerClient.url + "/" + destFilePath + "?" + sasToken; + return { signedUrl } + } + +} + diff --git a/constants/http-status.js b/generics/http-status.js similarity index 100% rename from constants/http-status.js rename to generics/http-status.js diff --git a/generics/kafka-communication.js b/generics/kafka-communication.js index 2c9edd9ce..5ec7af70b 100644 --- a/generics/kafka-communication.js +++ b/generics/kafka-communication.js @@ -1,6 +1,30 @@ /** * name : generics/kafka-communication - * author : Aman Kumar Gupta - * Date : 01-Oct-2021 - * Description : Contains producer consumer logic for kafka - */ \ No newline at end of file + * author : Aman Gupta + * Date : 08-Nov-2021 + * Description : Kafka producer methods +*/ + +const sendOtpEmailToKafka = async message => { + try { + const payload = [{ topic: process.env.NOTIFICATION_KAFKA_TOPIC, messages: JSON.stringify(message) }]; + return await pushPayloadToKafka(payload) + } catch (error) { + throw error; + } +}; + +const pushPayloadToKafka = (payload) => { + return new Promise((resolve, reject) => { + kafkaProducer.send(payload, (error, data) => { + if (error) { + reject(error); + } + resolve(data); + }); + }); +}; + +module.exports = { + sendOtpEmailToKafka + }; \ No newline at end of file diff --git a/generics/services/index.js b/generics/services/index.js deleted file mode 100644 index fa79a06cf..000000000 --- a/generics/services/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * name : generics/services - * author : Aman Kumar Gupta - * Date : 01-Oct-2021 - * Description : Contains internal call to other micro services - */ \ No newline at end of file diff --git a/generics/utils.js b/generics/utils.js new file mode 100644 index 000000000..686d94e09 --- /dev/null +++ b/generics/utils.js @@ -0,0 +1,37 @@ +/** + * name : utils.js + * author : Aman + * created-date : 07-Oct-2021 + * Description : Utils helper function. + */ + +const bcryptJs = require('bcryptjs'); +const fs = require('fs'); +const jwt = require('jsonwebtoken'); + +const generateToken = (tokenData, secretKey, expiresIn) => { + return jwt.sign(tokenData, secretKey, { expiresIn }); +}; + +const hashPassword = (password) => { + const salt = bcryptJs.genSaltSync(10); + let hashPassword = bcryptJs.hashSync(password, salt); + return hashPassword; +} + +const comparePassword = (password1,password2) => { + return bcryptJs.compareSync(password1, password2); +} + +const clearFile = (filePath) => { + fs.unlink(filePath, err => { + if (err) console.log(err); + }) +}; + +module.exports = { + generateToken, + hashPassword, + comparePassword, + clearFile +} \ No newline at end of file diff --git a/middlewares/authenticator.js b/middlewares/authenticator.js index 41c25b7b5..fce615bae 100644 --- a/middlewares/authenticator.js +++ b/middlewares/authenticator.js @@ -1,6 +1,69 @@ /** * name : middlewares/authenticator * author : Aman Kumar Gupta - * Date : 01-Oct-2021 + * Date : 21-Oct-2021 * Description : Validating authorized requests - */ \ No newline at end of file + */ + +const jwt = require('jsonwebtoken'); + +const httpStatusCode = require('../generics/http-status'); +const apiResponses = require('../constants/api-responses'); +const common = require('../constants/common'); + +module.exports = async function (req, res, next) { + + + + let internalAccess = false; + await Promise.all(common.uploadUrls.map(async function (path) { + if (req.path.includes(path)) { + if (req.headers.internal_access_token && process.env.INTERNAL_ACCESS_TOKEN == req.headers.internal_access_token) { + internalAccess =true; + } + } + })); + if (internalAccess == true) { + next(); + return; + } + else if (!common.guestUrls.includes(req.url)) { + + + + const authHeader = req.get('X-auth-token'); + if (!authHeader) { + throw common.failureResponse({ message: apiResponses.UNAUTHORIZED_REQUEST, statusCode: httpStatusCode.unauthorized, responseCode: 'UNAUTHORIZED' }); + } + + + // let splittedUrl = req.url.split('/'); + // if (common.uploadUrls.includes(splittedUrl[splittedUrl.length - 1])) { + // if (!req.headers.internal_access_token || process.env.INTERNAL_ACCESS_TOKEN !== req.headers.internal_access_token) { + // throw common.failureResponse({ message: apiResponses.INCORRECT_INTERNAL_ACCESS_TOKEN, statusCode: httpStatusCode.unauthorized, responseCode: 'UNAUTHORIZED' }); + // } + // } + + + const authHeaderArray = authHeader.split(' '); + if (authHeaderArray[0] !== 'bearer') { + throw common.failureResponse({ message: apiResponses.UNAUTHORIZED_REQUEST, statusCode: httpStatusCode.unauthorized, responseCode: 'UNAUTHORIZED' }); + } + try { + decodedToken = jwt.verify(authHeaderArray[1], process.env.ACCESS_TOKEN_SECRET); + } catch (err) { + err.statusCode = httpStatusCode.unauthorized; + err.responseCode = 'UNAUTHORIZED'; + err.message = apiResponses.ACCESS_TOKEN_EXPIRED; + throw err; + } + + if (!decodedToken) { + throw common.failureResponse({ message: apiResponses.UNAUTHORIZED_REQUEST, statusCode: httpStatusCode.unauthorized, responseCode: 'UNAUTHORIZED' }); + } + + req.decodedToken = decodedToken.data; + } + + next(); +}; diff --git a/middlewares/pagination.js b/middlewares/pagination.js new file mode 100644 index 000000000..55826d84b --- /dev/null +++ b/middlewares/pagination.js @@ -0,0 +1,25 @@ +/** + * name : pagination.js + * author : Aman Karki + * Date : 13-July-2020 + * Description : Pagination + */ + +module.exports = (req, res, next) => { + req.pageNo = (req.query.page && Number(req.query.page) > 0) + ? Number(req.query.page) : 1; + + req.pageSize = (req.query.limit && Number(req.query.limit) > 0 && + Number(req.query.limit) <= 100) ? + Number(req.query.limit) : 100; + + req.searchText = (req.query.search && req.query.search != "") + ? decodeURI(req.query.search) : ""; + + delete req.query.page; + delete req.query.limit; + next(); + return; +} + + diff --git a/middlewares/validator.js b/middlewares/validator.js index 73d7cf9b6..797c6772a 100644 --- a/middlewares/validator.js +++ b/middlewares/validator.js @@ -1,6 +1,17 @@ /** * name : middlewares/validator * author : Aman Kumar Gupta - * Date : 01-Oct-2021 + * Date : 20-Oct-2021 * Description : Contains logic to call required validator from validators directory to validate request data - */ \ No newline at end of file + */ +const fs = require("fs"); + +module.exports = (req, res, next) => { + + try { + require(`../validators/${req.params.version}/${req.params.controller}`)[req.params.method](req); + } catch (error) { + + } + next(); +}; \ No newline at end of file diff --git a/models/profile/database-layer.js b/models/profile/database-layer.js deleted file mode 100644 index 910e4d747..000000000 --- a/models/profile/database-layer.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * name : models/profile/database-layer - * author : Aman Kumar Gupta - * Date : 01-Oct-2021 - * Description : Contains database access methods for profile module - */ \ No newline at end of file diff --git a/models/profile/schema.js b/models/profile/schema.js deleted file mode 100644 index ca5e3fa8d..000000000 --- a/models/profile/schema.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * name : models/profile/schema - * author : Aman Kumar Gupta - * Date : 01-Oct-2021 - * Description : Contains profile model schema - */ \ No newline at end of file diff --git a/models/user/database-layer.js b/models/user/database-layer.js deleted file mode 100644 index d06b1e530..000000000 --- a/models/user/database-layer.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * name : models/user/database-layer - * author : Aman Kumar Gupta - * Date : 01-Oct-2021 - * Description : Contains database access methods for user module - */ \ No newline at end of file diff --git a/models/user/schema.js b/models/user/schema.js deleted file mode 100644 index 8a48303be..000000000 --- a/models/user/schema.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * name : models/user/schema - * author : Aman Kumar Gupta - * Date : 01-Oct-2021 - * Description : Contains user model schema - */ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 31b6fdd5c..ba2de90d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,221 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@azure/abort-controller": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.4.tgz", + "integrity": "sha512-lNUmDRVGpanCsiUN3NWxFTdwmdFI53xwhkTFfHDGTYk46ca7Ind3nanJc+U6Zj9Tv+9nTCWRBscWEW1DyKOpTw==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@azure/core-asynciterator-polyfill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.0.tgz", + "integrity": "sha512-kmv8CGrPfN9SwMwrkiBK9VTQYxdFQEGe0BmQk+M8io56P9KNzpAxcWE/1fxJj7uouwN4kXF0BHW8DNlgx+wtCg==" + }, + "@azure/core-auth": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.3.2.tgz", + "integrity": "sha512-7CU6DmCHIZp5ZPiZ9r3J17lTKMmYsm/zGvNkjArQwPkrLlZ1TZ+EUYfGgh2X31OLMVAQCTJZW4cXHJi02EbJnA==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "tslib": "^2.2.0" + } + }, + "@azure/core-http": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-2.2.2.tgz", + "integrity": "sha512-V1DdoO9V/sFimKpdWoNBgsE+QUjQgpXYnxrTdUp5RyhsTJjvEVn/HKmTQXIHuLUUo6IyIWj+B+Dg4VaXse9dIA==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-asynciterator-polyfill": "^1.0.0", + "@azure/core-auth": "^1.3.0", + "@azure/core-tracing": "1.0.0-preview.13", + "@azure/logger": "^1.0.0", + "@types/node-fetch": "^2.5.0", + "@types/tunnel": "^0.0.3", + "form-data": "^4.0.0", + "node-fetch": "^2.6.0", + "process": "^0.11.10", + "tough-cookie": "^4.0.0", + "tslib": "^2.2.0", + "tunnel": "^0.0.6", + "uuid": "^8.3.0", + "xml2js": "^0.4.19" + } + }, + "@azure/core-lro": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.2.1.tgz", + "integrity": "sha512-HE6PBl+mlKa0eBsLwusHqAqjLc5n9ByxeDo3Hz4kF3B1hqHvRkBr4oMgoT6tX7Hc3q97KfDctDUon7EhvoeHPA==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-tracing": "1.0.0-preview.13", + "@azure/logger": "^1.0.0", + "tslib": "^2.2.0" + } + }, + "@azure/core-paging": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.2.0.tgz", + "integrity": "sha512-ZX1bCjm/MjKPCN6kQD/9GJErYSoKA8YWp6YWoo5EIzcTWlSBLXu3gNaBTUl8usGl+UShiKo7b4Gdy1NSTIlpZg==", + "requires": { + "@azure/core-asynciterator-polyfill": "^1.0.0", + "tslib": "^2.2.0" + } + }, + "@azure/core-tracing": { + "version": "1.0.0-preview.13", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz", + "integrity": "sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ==", + "requires": { + "@opentelemetry/api": "^1.0.1", + "tslib": "^2.2.0" + } + }, + "@azure/logger": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.3.tgz", + "integrity": "sha512-aK4s3Xxjrx3daZr3VylxejK3vG5ExXck5WOHDJ8in/k9AqlfIyFMMT1uG7u8mNjX+QRILTIn0/Xgschfh/dQ9g==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@azure/storage-blob": { + "version": "12.8.0", + "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.8.0.tgz", + "integrity": "sha512-c8+Wz19xauW0bGkTCoqZH4dYfbtBniPiGiRQOn1ca6G5jsjr4azwaTk9gwjVY8r3vY2Taf95eivLzipfIfiS4A==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-http": "^2.0.0", + "@azure/core-lro": "^2.2.0", + "@azure/core-paging": "^1.1.1", + "@azure/core-tracing": "1.0.0-preview.13", + "@azure/logger": "^1.0.0", + "events": "^3.0.0", + "tslib": "^2.2.0" + }, + "dependencies": { + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + } + } + }, + "@google-cloud/common": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-3.8.1.tgz", + "integrity": "sha512-FOs3NFU6bDt5mXE7IFpwIeqzLwRZNu9lJYl+bHVNkwmxX/w4VyDZAiGjQHhpV1Ek+muNKlX8HPchxaIxNTuOhw==", + "requires": { + "@google-cloud/projectify": "^2.0.0", + "@google-cloud/promisify": "^2.0.0", + "arrify": "^2.0.1", + "duplexify": "^4.1.1", + "ent": "^2.2.0", + "extend": "^3.0.2", + "google-auth-library": "^7.9.2", + "retry-request": "^4.2.2", + "teeny-request": "^7.0.0" + } + }, + "@google-cloud/paginator": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.6.tgz", + "integrity": "sha512-XCTm/GfQIlc1ZxpNtTSs/mnZxC2cePNhxU3X8EzHXKIJ2JFncmJj2Fcd2IP+gbmZaSZnY0juFxbUCkIeuu/2eQ==", + "requires": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + } + }, + "@google-cloud/projectify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.1.1.tgz", + "integrity": "sha512-+rssMZHnlh0twl122gXY4/aCrk0G1acBqkHFfYddtsqpYXGxA29nj9V5V9SfC+GyOG00l650f6lG9KL+EpFEWQ==" + }, + "@google-cloud/promisify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.4.tgz", + "integrity": "sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA==" + }, + "@google-cloud/storage": { + "version": "5.15.6", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.15.6.tgz", + "integrity": "sha512-3SBDB6zjvsOuS4sx79QhU42c0TOFM1TalK9Rovcc6BtxGuf8zLzTgyLNkmofP1kjpIbdqLWmqmHdkjAUYZvkKg==", + "requires": { + "@google-cloud/common": "^3.8.1", + "@google-cloud/paginator": "^3.0.0", + "@google-cloud/promisify": "^2.0.0", + "arrify": "^2.0.0", + "async-retry": "^1.3.1", + "compressible": "^2.0.12", + "date-and-time": "^2.0.0", + "duplexify": "^4.0.0", + "extend": "^3.0.2", + "gcs-resumable-upload": "^3.5.1", + "get-stream": "^6.0.0", + "hash-stream-validation": "^0.2.2", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "pumpify": "^2.0.0", + "snakeize": "^0.1.0", + "stream-events": "^1.0.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==" + } + } + }, + "@mapbox/node-pre-gyp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", + "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", + "requires": { + "detect-libc": "^1.0.3", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.1", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "rimraf": "^3.0.2", + "semver": "^7.3.4", + "tar": "^6.1.0" + }, + "dependencies": { + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@opentelemetry/api": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.0.3.tgz", + "integrity": "sha512-puWxACExDe9nxbBB3lOymQFrLYml2dVOrd7USiVRnSbgXE+KwBu+HxFvxrzfqsiSda9IWsXJG1ef7C1O2/GmKQ==" + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -19,11 +234,62 @@ "defer-to-connect": "^1.0.1" } }, + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" + }, + "@types/bson": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz", + "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==", + "requires": { + "@types/node": "*" + } + }, + "@types/mongodb": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.20.tgz", + "integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==", + "requires": { + "@types/bson": "*", + "@types/node": "*" + } + }, "@types/node": { "version": "16.10.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.1.tgz", "integrity": "sha512-4/Z9DMPKFexZj/Gn3LylFgamNKHm4K3QDi0gz9B26Uk0c8izYf97B5fxfpspMNkWlFupblKM/nV8+NA9Ffvr+w==" }, + "@types/node-fetch": { + "version": "2.5.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", + "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, + "@types/tunnel": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/tunnel/-/tunnel-0.0.3.tgz", + "integrity": "sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==", + "requires": { + "@types/node": "*" + } + }, "@types/webidl-conversions": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", @@ -41,8 +307,15 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } }, "accepts": { "version": "1.3.7", @@ -53,6 +326,29 @@ "negotiator": "0.6.2" } }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -65,8 +361,7 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", @@ -87,11 +382,96 @@ "picomatch": "^2.0.4" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "requires": { + "retry": "0.13.1" + }, + "dependencies": { + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + } + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sdk": { + "version": "2.1025.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1025.0.tgz", + "integrity": "sha512-1AR2xIHcbIWj5y3fh9JHd2fLgiGqpn9Ww+8y9kZDnrsIousJkR6L+QkG0mRhChu/AjpFVQ44fiTBoE4J88Dqyw==", + "requires": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, "axios": { "version": "0.21.4", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", @@ -103,25 +483,70 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, + "bcrypt": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" + } + }, "bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" }, + "bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" + }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -159,7 +584,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -191,11 +615,59 @@ "ieee754": "^1.1.13" } }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "optional": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "optional": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "optional": true + }, + "buffermaker": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/buffermaker/-/buffermaker-1.2.1.tgz", + "integrity": "sha512-IdnyU2jDHU65U63JuVQNTHiWjPRH0CS3aYd/WPaEwyX84rFdukhOduAVb1jwUScmb5X0JWPw8NZOrhoLMiyAHQ==", + "requires": { + "long": "1.1.2" + } + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" + }, + "busboy": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", + "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", + "requires": { + "dicer": "0.3.0" + } + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -239,6 +711,14 @@ "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", "dev": true }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -282,6 +762,11 @@ "readdirp": "~3.6.0" } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -294,6 +779,11 @@ "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -303,6 +793,11 @@ "mimic-response": "^1.0.0" } }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -318,17 +813,36 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, "requires": { "dot-prop": "^5.2.0", "graceful-fs": "^4.1.2", @@ -338,6 +852,11 @@ "xdg-basedir": "^4.0.0" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -361,6 +880,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -373,8 +897,22 @@ "crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, + "csvtojson": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz", + "integrity": "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ==", + "requires": { + "bluebird": "^3.5.1", + "lodash": "^4.17.3", + "strip-bom": "^2.0.0" + } + }, + "date-and-time": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-2.0.1.tgz", + "integrity": "sha512-O7Xe5dLaqvY/aF/MFWArsAM1J4j7w1CSZlPCX9uHgmb+6SbkPd8Q4YOvfvH/cZGvFlJFfHOZKxQtmMUOoZhc/w==" }, "debug": { "version": "2.6.9", @@ -388,7 +926,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, "requires": { "mimic-response": "^1.0.0" } @@ -396,8 +933,15 @@ "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + } }, "defer-to-connect": { "version": "1.1.3", @@ -405,6 +949,16 @@ "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", "dev": true }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, "denque": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", @@ -420,11 +974,23 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "dicer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", + "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", + "requires": { + "streamsearch": "0.1.2" + } + }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, "requires": { "is-obj": "^2.0.0" } @@ -440,6 +1006,29 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -453,11 +1042,15 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "emitter-component": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.1.tgz", + "integrity": "sha1-Bl4tvtaVm/RwZ57avq95gdEAOrY=" + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "encodeurl": { "version": "1.0.2", @@ -468,11 +1061,15 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "requires": { "once": "^1.4.0" } }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" + }, "escape-goat": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", @@ -489,6 +1086,22 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "optional": true + }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -526,15 +1139,39 @@ "vary": "~1.1.2" } }, + "express-fileupload": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.2.1.tgz", + "integrity": "sha512-fWPNAkBj+Azt9Itmcz/Reqdg3LeBfaXptDEev2JM8bCC0yDptglCnlizhf0YZauyU5X/g6v7v4Xxqhg8tmEfEA==", + "requires": { + "busboy": "^0.3.1" + } + }, "express-validator": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.12.2.tgz", - "integrity": "sha512-UMVck7ZWrKH7eX75CRYk/pAc9jxZk8Ddsdkukw1R7LTWuQNiDaooz6nVfIdg33qZUHCuv2m2o+RS4pTMaLjGmA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-5.3.1.tgz", + "integrity": "sha512-g8xkipBF6VxHbO1+ksC7nxUU7+pWif0+OZXjZTybKJ/V0aTVhuCoHbyhIPgSYVldwQLocGExPtB2pE0DqK4jsw==", "requires": { - "lodash": "^4.17.21", - "validator": "^13.5.2" + "lodash": "^4.17.10", + "validator": "^10.4.0" } }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "fast-text-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", + "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -563,6 +1200,16 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==" }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -573,6 +1220,25 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "optional": true + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -580,6 +1246,90 @@ "dev": true, "optional": true }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "gaxios": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.2.tgz", + "integrity": "sha512-T+ap6GM6UZ0c4E6yb1y/hy2UB6hTrqhglp3XfmU9qbLCGRYhLVV5aRPpC4EmoG8N8zOnkYCgoBz+ScvGAARY6Q==", + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.1" + } + }, + "gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "requires": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + } + }, + "gcs-resumable-upload": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-3.5.1.tgz", + "integrity": "sha512-yq8h+z2zx9pUUdho07ORfNkrzlXNZTXi1fnqf0K1oh8VwleQjRq/2zgkN88MYDpXlaykvzvqbWJGq/78nufuJg==", + "requires": { + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "configstore": "^5.0.0", + "extend": "^3.0.2", + "gaxios": "^4.0.0", + "google-auth-library": "^7.0.0", + "pumpify": "^2.0.0", + "stream-events": "^1.0.4" + } + }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -589,6 +1339,25 @@ "pump": "^3.0.0" } }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "optional": true + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -607,6 +1376,51 @@ "ini": "2.0.0" } }, + "google-auth-library": { + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.10.2.tgz", + "integrity": "sha512-M37o9Kxa/TLvOLgF71SXvLeVEP5sbSTmKl1zlIgl72SFy5PtsU3pOdu8G8MIHHpQ3/NZabDI8rQkA9DvQVKkPA==", + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "dependencies": { + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + } + } + }, + "google-p12-pem": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.2.tgz", + "integrity": "sha512-tjf3IQIt7tWCDsa0ofDQ1qqSCNzahXDxdAGJDbruWqu3eCg5CKLYKN+hi0s6lfvzYZ1GDVr+oDF9OOWlDSdf0A==", + "requires": { + "node-forge": "^0.10.0" + } + }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -629,8 +1443,38 @@ "graceful-fs": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + }, + "gtoken": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.1.tgz", + "integrity": "sha512-yqOREjzLHcbzz1UrQoxhBtpk8KjrVhuqPE7od1K2uhyxG2BHjKZetlbLw/SPZak/QqTIQW+addS+EcjqQsZbwQ==", + "requires": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.0.3", + "jws": "^4.0.0" + }, + "dependencies": { + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + } + } }, "has-flag": { "version": "3.0.0", @@ -638,12 +1482,22 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, "has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "dev": true }, + "hash-stream-validation": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz", + "integrity": "sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ==" + }, "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -662,6 +1516,55 @@ "toidentifier": "1.0.0" } }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -690,8 +1593,16 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.3", @@ -736,8 +1647,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-glob": { "version": "4.0.2", @@ -773,8 +1683,7 @@ "is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" }, "is-path-inside": { "version": "3.0.3", @@ -782,11 +1691,20 @@ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, "is-yarn-global": { "version": "0.3.0", @@ -794,12 +1712,45 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "requires": { + "bignumber.js": "^9.0.0" + } + }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", "dev": true }, + "json2csv": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-5.0.6.tgz", + "integrity": "sha512-0/4Lv6IenJV0qj2oBdgPIAmFiKKnh8qh7bmLFJ+/ZZHLjSeiL3fKKGX3UryvKPbxFbhV+JcYo9KUC19GJ/Z/4A==", + "requires": { + "commander": "^6.1.0", + "jsonparse": "^1.3.1", + "lodash.get": "^4.4.2" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, "jsonwebtoken": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", @@ -843,6 +1794,39 @@ "safe-buffer": "^5.0.1" } }, + "kafka-node": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/kafka-node/-/kafka-node-5.0.0.tgz", + "integrity": "sha512-dD2ga5gLcQhsq1yNoQdy1MU4x4z7YnXM5bcG9SdQuiNr5KKuAmXixH1Mggwdah5o7EfholFbcNDPSVA6BIfaug==", + "requires": { + "async": "^2.6.2", + "binary": "~0.3.0", + "bl": "^2.2.0", + "buffer-crc32": "~0.2.5", + "buffermaker": "~1.2.0", + "debug": "^2.1.3", + "denque": "^1.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "nested-error-stacks": "^2.0.0", + "optional": "^0.1.3", + "retry": "^0.10.1", + "snappy": "^6.0.1", + "uuid": "^3.0.0" + }, + "dependencies": { + "denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, "kareem": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", @@ -871,6 +1855,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -906,6 +1895,11 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" }, + "long": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/long/-/long-1.1.2.tgz", + "integrity": "sha1-6u9ZUcp1UdlpJrgtokLbnWso+1M=" + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -916,7 +1910,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -925,16 +1918,14 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, "requires": { "semver": "^6.0.0" }, "dependencies": { "semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -980,14 +1971,12 @@ "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -995,14 +1984,43 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "minipass": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz", + "integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, "moment": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" }, + "moment-timezone": { + "version": "0.5.34", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", + "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", + "requires": { + "moment": ">= 2.9.0" + } + }, "mongodb": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.1.2.tgz", @@ -1024,71 +2042,123 @@ } }, "mongoose": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.0.8.tgz", - "integrity": "sha512-7XZ5TUoDtF8af7+mKfL58s8dN2BKmldQPTlmkb41PaRAleBVGeAck7Mj6JlIh9SOCi+64GT+afebiJaeyXe1Lw==", + "version": "5.13.12", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.12.tgz", + "integrity": "sha512-ZEuZ3X/yop9XyOyuCYMz+oxJxXBclm9LIsjKHB0QX2eaNqKNqkvZFzkElbJCj8FDvYmBZFh0OFHlkREhtie6uA==", "requires": { - "bson": "^4.2.2", + "@types/bson": "1.x || 4.0.x", + "@types/mongodb": "^3.5.27", + "bson": "^1.1.4", "kareem": "2.3.2", - "mongodb": "4.1.1", + "mongodb": "3.7.2", + "mongoose-legacy-pluralize": "1.0.2", "mpath": "0.8.4", - "mquery": "4.0.0", + "mquery": "3.2.5", "ms": "2.1.2", + "optional-require": "1.0.x", "regexp-clone": "1.0.0", + "safe-buffer": "5.2.1", "sift": "13.5.2", "sliced": "1.0.1" }, "dependencies": { + "bson": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", + "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==" + }, "denque": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" }, "mongodb": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.1.1.tgz", - "integrity": "sha512-fbACrWEyvr6yl0sSiCGV0sqEiBwTtDJ8iSojmkDjAfw9JnOZSAkUyv9seFSPYhPPKwxp1PDtyjvBNfMDz0WBLQ==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.2.tgz", + "integrity": "sha512-/Qi0LmOjzIoV66Y2JQkqmIIfFOy7ZKsXnQNlUXPFXChOw3FCdNqVD5zvci9ybm6pkMe/Nw+Rz9I0Zsk2a+05iQ==", "requires": { - "bson": "^4.5.1", - "denque": "^1.5.0", - "mongodb-connection-string-url": "^2.0.0", + "bl": "^2.2.1", + "bson": "^1.1.4", + "denque": "^1.4.1", + "optional-require": "^1.1.8", + "safe-buffer": "^5.1.2", "saslprep": "^1.0.0" + }, + "dependencies": { + "optional-require": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", + "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", + "requires": { + "require-at": "^1.0.6" + } + } } }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" } } }, + "mongoose-autopopulate": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/mongoose-autopopulate/-/mongoose-autopopulate-0.16.0.tgz", + "integrity": "sha512-OSRETKRTk6B3cF7cSLYPE+iUs/DTIY5+07gVYNzCdTRu4oB3uMahc0qjZYepZqZJKm+nv8SihtSHRM5gScn+fA==" + }, + "mongoose-delete": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mongoose-delete/-/mongoose-delete-0.5.4.tgz", + "integrity": "sha512-zKkcWFEwTneVG4Oiy+qJRJPFCiGlqOJToHeU3a3meJybWsHCnWxdHkGEkFWNY5cmYEv5av3WwByOhPlQ6I+FmQ==" + }, + "mongoose-legacy-pluralize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" + }, + "mongoose-paginate-v2": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/mongoose-paginate-v2/-/mongoose-paginate-v2-1.4.2.tgz", + "integrity": "sha512-b7FBe7fasJazhlTIfMSPyIST04yvobASXKmUt3ducnvYThulCyGSPhPcSYOzXcPmqBR4tpMnafIJxv+8GjM+UA==" + }, + "mongoose-timestamp": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/mongoose-timestamp/-/mongoose-timestamp-0.6.0.tgz", + "integrity": "sha1-2lQRDKjm1MK5lXoDZoNsNi7Scr4=", + "requires": { + "defaults": "^1.0.3" + } + }, "mpath": { "version": "0.8.4", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==" }, "mquery": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-4.0.0.tgz", - "integrity": "sha512-nGjm89lHja+T/b8cybAby6H0YgA4qYC/lx6UlwvHGqvTq8bDaNeCwl1sY8uRELrNbVWJzIihxVd+vphGGn1vBw==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz", + "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==", "requires": { - "debug": "4.x", + "bluebird": "3.5.1", + "debug": "3.1.0", "regexp-clone": "^1.0.0", + "safe-buffer": "5.1.2", "sliced": "1.0.1" }, "dependencies": { "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "requires": { - "ms": "2.1.2" + "ms": "2.0.0" } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" } } }, @@ -1097,11 +2167,76 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "optional": true + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "optional": true + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, + "nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==" + }, + "node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "optional": true, + "requires": { + "semver": "^5.4.1" + } + }, + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + }, + "node-fetch": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", + "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" + }, "nodemon": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.13.tgz", @@ -1137,6 +2272,12 @@ } } }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", + "optional": true + }, "nopt": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", @@ -1158,6 +2299,22 @@ "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1175,17 +2332,40 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } }, + "optional": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/optional/-/optional-0.1.4.tgz", + "integrity": "sha512-gtvrrCfkE08wKcgXaVwQVgwEQ8vel2dc5DDBn9RLQZ3YtmtkBss6A2HY6BnJH4N/4Ku97Ri/SF8sNWE2225WJw==" + }, + "optional-require": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz", + "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==" + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "optional": true + }, "p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", "dev": true }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, "package-json": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", @@ -1211,6 +2391,11 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -1222,12 +2407,67 @@ "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, + "prebuild-install": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.0.tgz", + "integrity": "sha512-aaLVANlj4HgZweKttFNUVNRxDukytuIuxeK2boIMHjagNJCiVKWFsKF4tCE3ql3GbrD2tExPQ7/pwtEJcHNZeg==", + "optional": true, + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "os-homedir": "^1.0.1", + "pump": "^2.0.1", + "rc": "^1.2.7", + "simple-get": "^2.7.0", + "tar-fs": "^1.13.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "optional": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1237,6 +2477,11 @@ "ipaddr.js": "1.9.1" } }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, "pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -1247,12 +2492,21 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, + "pumpify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", + "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "requires": { + "duplexify": "^4.1.1", + "inherits": "^2.0.3", + "pump": "^3.0.0" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -1272,6 +2526,11 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -1292,7 +2551,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, "requires": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -1303,11 +2561,24 @@ "ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" } } }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -1345,6 +2616,11 @@ "resolved": "https://registry.npmjs.org/require-all/-/require-all-3.0.0.tgz", "integrity": "sha1-Rz1JcEvjEBFc4ST3c4Ox69hnExI=" }, + "require-at": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", + "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" + }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -1354,6 +2630,43 @@ "lowercase-keys": "^1.0.0" } }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" + }, + "retry-request": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.2.2.tgz", + "integrity": "sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg==", + "requires": { + "debug": "^4.1.1", + "extend": "^3.0.2" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -1373,6 +2686,11 @@ "sparse-bitfield": "^3.0.3" } }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -1433,6 +2751,11 @@ "send": "0.17.1" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", @@ -1446,14 +2769,46 @@ "signal-exit": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.4.tgz", - "integrity": "sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q==", - "dev": true + "integrity": "sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "optional": true + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "optional": true, + "requires": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } }, "sliced": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" }, + "snakeize": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", + "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=" + }, + "snappy": { + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/snappy/-/snappy-6.3.5.tgz", + "integrity": "sha512-lonrUtdp1b1uDn1dbwgQbBsb5BbaiLeKq+AGwOk2No+en+VvJThwmtztwulEQsLinRF681pBqib0NUZaizKLIA==", + "optional": true, + "requires": { + "bindings": "^1.3.1", + "nan": "^2.14.1", + "prebuild-install": "5.3.0" + } + }, "sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", @@ -1468,31 +2823,75 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "stream": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stream/-/stream-0.0.2.tgz", + "integrity": "sha1-f1Nj8Ff2WSxVlfALyAon9c7B8O8=", + "requires": { + "emitter-component": "^1.1.1" + } + }, + "stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "requires": { + "stubs": "^3.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" } }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=" }, "supports-color": { "version": "5.5.0", @@ -1503,6 +2902,103 @@ "has-flag": "^3.0.0" } }, + "tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "optional": true, + "requires": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + }, + "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "optional": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "optional": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "optional": true, + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "dependencies": { + "bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "optional": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + } + } + }, + "teeny-request": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.1.3.tgz", + "integrity": "sha512-Ew3aoFzgQEatLA5OBIjdr1DWJUaC1xardG+qbPPo5k/y/3fMwXLxpjh5UB5dVfElktLaQbbMs80chkz53ByvSg==", + "requires": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^8.0.0" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "optional": true + }, "to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", @@ -1532,6 +3028,16 @@ "nopt": "~1.0.10" } }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + }, "tr46": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", @@ -1540,6 +3046,30 @@ "punycode": "^2.1.1" } }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "optional": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -1559,7 +3089,6 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, "requires": { "is-typedarray": "^1.0.0" } @@ -1577,11 +3106,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, "requires": { "crypto-random-string": "^2.0.0" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -1620,6 +3153,22 @@ } } }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -1629,6 +3178,11 @@ "prepend-http": "^2.0.0" } }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -1640,9 +3194,9 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "validator": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz", - "integrity": "sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg==" + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" }, "vary": { "version": "1.1.2", @@ -1663,6 +3217,20 @@ "webidl-conversions": "^6.1.0" } }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "optional": true + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -1686,14 +3254,12 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write-file-atomic": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, "requires": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -1704,14 +3270,37 @@ "xdg-basedir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "optional": true }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" } } } diff --git a/package.json b/package.json index 68353b63a..35a275364 100644 --- a/package.json +++ b/package.json @@ -5,25 +5,40 @@ "main": "app.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "start": "nodemon app.js", - "prod": "node app.js", - "stage": "node app.js" + "start": "NODE_ENV=development nodemon app.js", + "prod": "NODE_ENV=production node app.js", + "stage": "NODE_ENV=stage node app.js", + "qa": "NODE_ENV=qa node app.js" }, "author": "Aman Kumar Gupta ", "license": "ISC", "dependencies": { + "@azure/storage-blob": "^12.8.0", + "@google-cloud/storage": "^5.15.6", + "aws-sdk": "^2.1025.0", "axios": "^0.21.4", + "bcrypt": "^5.0.1", "bcryptjs": "^2.4.3", "body-parser": "^1.19.0", "cors": "^2.8.5", + "csvtojson": "^2.0.10", "dotenv": "^10.0.0", "express": "^4.17.1", - "express-validator": "^6.12.2", + "express-fileupload": "^1.2.1", + "express-validator": "^5.3.1", + "json2csv": "^5.0.6", "jsonwebtoken": "^8.5.1", + "kafka-node": "^5.0.0", "moment": "^2.29.1", + "moment-timezone": "^0.5.34", "mongodb": "^4.1.2", - "mongoose": "^6.0.8", + "mongoose": "^5.0.17", + "mongoose-autopopulate": "^0.16.0", + "mongoose-delete": "^0.5.4", + "mongoose-paginate-v2": "^1.4.2", + "mongoose-timestamp": "^0.6.0", "require-all": "^3.0.0", + "stream": "^0.0.2", "uuid": "^8.3.2" }, "devDependencies": { diff --git a/routes/index.js b/routes/index.js index 53122d8e4..f12273922 100644 --- a/routes/index.js +++ b/routes/index.js @@ -5,42 +5,114 @@ * Description : Routes for available service */ +const validator = require('../middlewares/validator'); +const authenticator = require('../middlewares/authenticator'); +const pagination = require('../middlewares/pagination'); +const expressValidator = require('express-validator'); +const fs = require("fs"); + module.exports = (app) => { + app.use(authenticator); + app.use(pagination); + app.use(expressValidator()); + async function router(req, res, next) { - let controller; let controllerResponse; + let validationError; + + /* Check for input validation error */ try { - /* Dynamically loaded requested controller */ - // and required here to minimize space complexity so that the memory to controller will only get allocated when request is made and then it gets destroyed when response is sent - controller = require(`../controllers/${req.params.version}/${req.params.controller}`) - } catch (error) { // if module not get found, say some one requested unsupported version or controller - return next(); + validationError = req.validationErrors(); + } catch (error) { + error.statusCode = 422; + error.responseCode = 'CLIENT_ERROR'; + return next(error); } - try { - controllerResponse = await controller[req.params.method](req); - } catch (error) { // if requested resource not found, i.e method does not exists - return next(); + if (validationError.length) { + const error = new Error('Validation failed, Entered data is incorrect!'); + error.statusCode = 422; + error.responseCode = 'CLIENT_ERROR'; + error.data = validationError; + return next(error); } - if (controllerResponse.statusCode !== 200 && controllerResponse.statusCode !== 201 && controllerResponse.statusCode !== 202) { - /* If error obtained then global error handler gets executed */ - return next(controllerResponse); + + if (!req.params.version) { + next(); + } else if (!controllers[req.params.version]) { + next(); + } else if (!controllers[req.params.version][req.params.controller]) { + next(); + } else if (!(controllers[req.params.version][req.params.controller][req.params.method] || + controllers[req.params.version][req.params.controller][req.params.file][req.params.method])) { + next(); + } else if (req.params.method.startsWith("_")) { + next(); + } else { + try { + + if (req.params.file) { + controllerResponse = + await controllers[req.params.version][req.params.controller][req.params.file][req.params.method](req); + } else { + controllerResponse = + await controllers[req.params.version][req.params.controller][req.params.method](req); + } + + + } catch (error) { // If controller or service throws some random error + return next(error); + } + + if (controllerResponse.isResponseAStream && controllerResponse.isResponseAStream == true) { + fs.exists(controllerResponse.fileNameWithPath, function (exists) { + + if (exists) { + + res.setHeader( + 'Content-disposition', + 'attachment; filename=' + controllerResponse.fileNameWithPath.split('/').pop() + ); + res.set('Content-Type', 'application/octet-stream'); + fs.createReadStream(controllerResponse.fileNameWithPath).pipe(res); + + } else {} + }); + } else { + if (controllerResponse.statusCode !== 200 && controllerResponse.statusCode !== 201 && controllerResponse.statusCode !== 202) { + /* If error obtained then global error handler gets executed */ + return next(controllerResponse); + } + + res.status(controllerResponse.statusCode).json({ + responseCode: controllerResponse.responseCode, + message: controllerResponse.message, + result: controllerResponse.result + }); + } } - res.status(controllerResponse.statusCode).json(controllerResponse); + } - app.all("/:version/:controller/:method", router); - app.all("/:version/:controller/:method/:id", router); + + app.all("/user/:version/:controller/:method", validator, router); + app.all("/user/:version/:controller/:file/:method", validator, router); + app.all("/user/:version/:controller/:method/:id", validator, router); + app.all("/user/:version/:controller/:file/:method/:id", validator, router); app.use((req, res, next) => { - res.status(404).send('Requested resource not found!'); + res.status(404).json({ + responseCode: 'RESOURCE_ERROR', + message: 'Requested resource not found!', + }); }); // Global error handling middleware, should be present in last in the stack of a middleware's app.use((error, req, res, next) => { const status = error.statusCode || 500; + const responseCode = error.responseCode || 'SERVER_ERROR'; const message = error.message || ''; let errorData = []; @@ -48,9 +120,8 @@ module.exports = (app) => { errorData = error.data; } res.status(status).json({ - message: message, - status: 'failure', - statusCode: status, + responseCode, + message, error: errorData }); }); diff --git a/services/helper/account.js b/services/helper/account.js new file mode 100644 index 000000000..19ab5ca2d --- /dev/null +++ b/services/helper/account.js @@ -0,0 +1,300 @@ +const bcryptJs = require('bcryptjs'); +const jwt = require('jsonwebtoken'); +const ObjectId = require('mongoose').Types.ObjectId; + +const utilsHelper = require("../../generics/utils"); +const httpStatusCode = require("../../generics/http-status"); +const apiResponses = require("../../constants/api-responses"); +const common = require('../../constants/common'); +const usersData = require("../../db/users/queries"); +const kafkaCommunication = require('../../generics/kafka-communication'); +const systemUserData = require("../../db/systemUsers/queries"); +const FILESTREAM = require("../../generics/file-stream"); + +module.exports = class AccountHelper { + + static async create(bodyData) { + try { + const email = bodyData.email; + const user = await usersData.findOne({ 'email.address': email }); + if (user) { + return common.failureResponse({ message: apiResponses.USER_ALREADY_EXISTS, statusCode: httpStatusCode.not_acceptable, responseCode: 'CLIENT_ERROR' }); + } + const salt = bcryptJs.genSaltSync(10); + bodyData.password = bcryptJs.hashSync(bodyData.password, salt); + bodyData.email = { address: email, verified: false }; + await usersData.createUser(bodyData); + return common.successResponse({ statusCode: httpStatusCode.created, message: apiResponses.USER_CREATED_SUCCESSFULLY }); + } catch (error) { + throw error; + } + } + + static async login(bodyData) { + const projection = { refreshTokens: 0, "designation.deleted": 0, "designation._id": 0, "areasOfExpertise.deleted": 0, "areasOfExpertise._id": 0, "location.deleted": 0, "location._id": 0, otpInfo: 0}; + try { + let user = await usersData.findOne({ "email.address": bodyData.email }, projection); + if (!user) { + return common.failureResponse({ message: apiResponses.USER_DOESNOT_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + const isPasswordCorrect = bcryptJs.compareSync(bodyData.password, user.password); + if (!isPasswordCorrect) { + return common.failureResponse({ message: apiResponses.PASSWORD_INVALID, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + + const tokenDetail = { + data: { + _id: user._id, + email: user.email.address, + name: user.name, + isAMentor: user.isAMentor + } + }; + + const accessToken = utilsHelper.generateToken(tokenDetail, process.env.ACCESS_TOKEN_SECRET, '1d'); + const refreshToken = utilsHelper.generateToken(tokenDetail, process.env.REFRESH_TOKEN_SECRET, '183d'); + + const update = { + $push: { + refreshTokens: { token: refreshToken, exp: new Date().getTime() } + }, + lastLoggedInAt: new Date().getTime() + }; + await usersData.updateOneUser({ _id: ObjectId(user._id) }, update); + + /* Mongoose schema is in strict mode, so can not delete password directly */ + user = { ...user._doc }; + delete user.password; + const result = { access_token: accessToken, refresh_token: refreshToken, user }; + + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.LOGGED_IN_SUCCESSFULLY, result }); + } catch (error) { + throw error; + } + } + + static async logout(bodyData) { + try { + const user = await usersData.findOne({ _id: ObjectId(bodyData.loggedInId) }); + if (!user) { + return common.failureResponse({ message: apiResponses.USER_DOESNOT_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + + const update = { + $pull: { + refreshTokens: { 'token': bodyData.refreshToken } + } + }; + /* Destroy refresh token for user */ + const res = await usersData.updateOneUser({ _id: ObjectId(user._id) }, update); + + /* If user doc not updated because of stored token does not matched with bodyData.refreshToken */ + if (!res) { + return common.failureResponse({ message: apiResponses.INVALID_REFRESH_TOKEN, statusCode: httpStatusCode.unauthorized, responseCode: 'UNAUTHORIZED' }); + } + + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.LOGGED_OUT_SUCCESSFULLY }); + } catch (error) { + throw error; + } + } + + static async generateToken(bodyData) { + + let decodedToken; + try { + decodedToken = jwt.verify(bodyData.refreshToken, process.env.REFRESH_TOKEN_SECRET); + } catch (error) { + /* If refresh token is expired */ + error.statusCode = httpStatusCode.unauthorized; + error.message = apiResponses.REFRESH_TOKEN_EXPIRED; + throw error; + } + + const user = await usersData.findOne({ _id: ObjectId(decodedToken.data._id) }); + + /* Check valid user */ + if (!user) { + return common.failureResponse({ message: apiResponses.USER_DOESNOT_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + + /* Check valid refresh token stored in db */ + if (user.refreshTokens.length) { + const token = user.refreshTokens.find(tokenData => tokenData.token === bodyData.refreshToken); + if (!token) { + return common.failureResponse({ message: apiResponses.REFRESH_TOKEN_NOT_FOUND, statusCode: httpStatusCode.internal_server_error, responseCode: 'CLIENT_ERROR' }); + } + + /* Generate new access token */ + const accessToken = utilsHelper.generateToken({ data: decodedToken.data }, process.env.ACCESS_TOKEN_SECRET, '1d'); + + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.ACCESS_TOKEN_GENERATED_SUCCESSFULLY, result: { access_token: accessToken } }); + } + return common.failureResponse({ message: apiResponses.REFRESH_TOKEN_NOT_FOUND, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + + static async generateOtp(bodyData) { + try { + let otp; + let expiresIn + let isValidOtpExist = true; + const user = await usersData.findOne({ 'email.address': bodyData.email }); + if (!user) { + return common.failureResponse({ message: apiResponses.USER_DOESNOT_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + + if (!user.otpInfo.otp || new Date().getTime() > user.otpInfo.exp) { + isValidOtpExist = false; + } else { + otp = user.otpInfo.otp // If valid then get previuosly generated otp + } + + if (!isValidOtpExist) { + otp = Math.floor(Math.random() * 900000 + 100000); // 6 digit otp + expiresIn = new Date().getTime() + (24 * 60 * 60 * 1000); // 1 day expiration time + await usersData.updateOneUser({ _id: user._id }, { otpInfo: { otp, exp: expiresIn } }); + } + + // Push otp to kafka + const payload = { + type: 'email', + email: { + to: bodyData.email, + subject: 'Reset Password', + body: `Dear ${user.name}, Your OTP to reset your password is ${otp}. Please enter the OTP to reset your password. For your security, please do not share this OTP with anyone.` + } + }; + + await kafkaCommunication.sendOtpEmailToKafka(payload); + + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.OTP_SENT_SUCCESSFULLY }); + } catch (error) { + throw error; + } + } + + static async resetPassword(bodyData) { + const projection = { refreshTokens: 0, "designation.deleted": 0, "designation._id": 0, "areasOfExpertise.deleted": 0, "areasOfExpertise._id": 0, "location.deleted": 0, "location._id": 0, password: 0}; + try { + let user = await usersData.findOne({ 'email.address': bodyData.email }, projection); + if (!user) { + return common.failureResponse({ message: apiResponses.USER_DOESNOT_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + + if (user.otpInfo.otp != bodyData.otp || new Date().getTime() > user.otpInfo.exp) { + return common.failureResponse({ message: apiResponses.OTP_INVALID, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + + const salt = bcryptJs.genSaltSync(10); + bodyData.password = bcryptJs.hashSync(bodyData.password, salt); + + const tokenDetail = { + data: { + _id: user._id, + email: user.email.address, + name: user.name, + isAMentor: user.isAMentor + } + }; + + const accessToken = utilsHelper.generateToken(tokenDetail, process.env.ACCESS_TOKEN_SECRET, '1d'); + const refreshToken = utilsHelper.generateToken(tokenDetail, process.env.REFRESH_TOKEN_SECRET, '183d'); + + const updateParams = { + $push: { + refreshTokens: { token: refreshToken, exp: new Date().getTime() } + }, + lastLoggedInAt: new Date().getTime(), + password: bodyData.password + }; + await usersData.updateOneUser({ _id: user._id }, updateParams); + + /* Mongoose schema is in strict mode, so can not delete otpInfo directly */ + user = { ...user._doc }; + delete user.otpInfo; + const result = { access_token: accessToken, refresh_token: refreshToken, user }; + + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.PASSWORD_RESET_SUCCESSFULLY, result }); + } catch (error) { + throw error; + } + } + + static async bulkCreateMentors(mentors,tokenInformation) { + return new Promise(async (resolve, reject) => { + try { + const systemUser = await systemUserData.findUsersByEmail(tokenInformation.email); + + if (!systemUser) { + return common.failureResponse({ message: apiResponses.USER_DOESNOT_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + + if (systemUser.role.toLowerCase() !== "admin") { + return common.failureResponse({ message: apiResponses.NOT_AN_ADMIN, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + + const fileName = `mentors-creation`; + let fileStream = new FILESTREAM(fileName); + let input = fileStream.initStream(); + + (async function () { + await fileStream.getProcessorPromise(); + return resolve({ + isResponseAStream: true, + fileNameWithPath: fileStream.fileNameWithPath() + }); + })(); + + for (const mentor of mentors) { + mentor.isAMentor = true; + const data = await this.create(mentor); + mentor.email = mentor.email.address; + mentor.status = data.message; + input.push(mentor); + } + + input.push(null); + } catch(error) { + throw error; + } + }) + } + + + static async verifyMentor(userId) { + try { + + let user = await usersData.findOne({ '_id': userId },{ "isAMentor":1 }); + if(!user){ + return common.failureResponse({ message: apiResponses.USER_DOESNOT_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } else if(user && user.isAMentor==true){ + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.USER_IS_A_MENTOR, result:user }); + } else { + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.USER_IS_NOT_A_MENTOR, result:user }); + } + + } catch(error) { + throw error; + } + } + + static async acceptTermsAndCondition(userId) { + try { + const user = await usersData.findOne({_id: userId},{_id: 1}); + + if(!user){ + return common.failureResponse({ message: apiResponses.USER_DOESNOT_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + + await usersData.updateOneUser({ + _id: userId + },{ + hasAcceptedTAndC: true + }); + + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.USER_UPDATED_SUCCESSFULLY }); + } catch(error) { + throw error; + } + } +} \ No newline at end of file diff --git a/services/helper/form.js b/services/helper/form.js new file mode 100644 index 000000000..5cfa69327 --- /dev/null +++ b/services/helper/form.js @@ -0,0 +1,52 @@ +const ObjectId = require('mongoose').Types.ObjectId; + +const utilsHelper = require("../../generics/utils"); +const httpStatusCode = require("../../generics/http-status"); +const apiResponses = require("../../constants/api-responses"); +const common = require('../../constants/common'); +const formsData = require("../../db/forms/queries"); + +module.exports = class FormsHelper { + + static async create(bodyData) { + try { + const filter = { type: bodyData.type, subType: bodyData.subType, action: bodyData.action, ver: bodyData.ver, "data.templateName": bodyData.data.templateName } + const form = await formsData.findOneForm(filter); + if (form) { + return common.failureResponse({ message: apiResponses.FORM_ALREADY_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + await formsData.createForm(bodyData); + return common.successResponse({ statusCode: httpStatusCode.created, message: apiResponses.FORM_CREATED_SUCCESSFULLY }); + } catch (error) { + throw error; + } + } + + static async update(bodyData) { + try { + const filter = { type: bodyData.type, subType: bodyData.subType, action: bodyData.action, ver: bodyData.ver, 'data.templateName': bodyData.data.templateName }; + const result = await formsData.updateOneForm(filter, bodyData); + if (result === 'ENTITY_ALREADY_EXISTS') { + return common.failureResponse({ message: apiResponses.FORM_ALREADY_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } else if (result === 'ENTITY_NOT_FOUND') { + return common.failureResponse({ message: apiResponses.FORM_NOT_FOUND, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + return common.successResponse({ statusCode: httpStatusCode.accepted, message: apiResponses.FORM_UPDATED_SUCCESSFULLY }); + } catch (error) { + throw error; + } + } + + static async read(bodyData) { + try { + const filter = { type: bodyData.type, subType: bodyData.subType, action: bodyData.action, ver: bodyData.ver, "data.templateName": bodyData.templateName } + const form = await formsData.findOneForm(filter); + if (!form) { + return common.failureResponse({ message: apiResponses.FORM_NOT_FOUND, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.FORM_FETCHED_SUCCESSFULLY, result: form ? form : {} }); + } catch (error) { + throw error; + } + } +} \ No newline at end of file diff --git a/services/helper/mentors.js b/services/helper/mentors.js new file mode 100644 index 000000000..c63a933fe --- /dev/null +++ b/services/helper/mentors.js @@ -0,0 +1,62 @@ +/** + * name : services/helper/mentors.js + * author : Aman + * created-date : 12-Nov-2021 + * Description : User Profile Service Helper. + */ + +const usersData = require("../../db/users/queries"); +const apiResponses = require("../../constants/api-responses"); +const common = require('../../constants/common'); +const httpStatusCode = require("../../generics/http-status"); + + module.exports = class MentorsHelper { + + static async list(page,limit,search) { + try { + const mentors = await usersData.searchMentors(page,limit,search); + + if (mentors[0].data.length < 1 ) { + return common.successResponse({ + "statusCode": httpStatusCode.ok, + "message": apiResponses.MENTOR_LIST, + "result": { + "data": [], + "count": 0 + } + }) + } + + let foundKeys = {}; + let result = []; + + for (let mentor of mentors[0].data) { + let firstChar = mentor.name.charAt(0); + firstChar = firstChar.toUpperCase(); + + if (!foundKeys[firstChar]) { + result.push({ + key: firstChar, + values: [mentor] + }); + foundKeys[firstChar] = result.length; + } else { + let index = foundKeys[firstChar] - 1; + result[index].values.push(mentor); + } + } + + return common.successResponse({ + statusCode: httpStatusCode.ok, + message: apiResponses.MENTOR_LIST, + result: { + data: result, + count: mentors[0].count + } + }); + + } catch (error) { + throw error; + } + } + } \ No newline at end of file diff --git a/services/helper/profile.js b/services/helper/profile.js new file mode 100644 index 000000000..26e352c2f --- /dev/null +++ b/services/helper/profile.js @@ -0,0 +1,46 @@ +/** + * name : services/helper/profile.js + * author : Aman + * created-date : 02-Nov-2021 + * Description : User Profile Service Helper. + */ + +const ObjectId = require('mongoose').Types.ObjectId; + +const utilsHelper = require("../../generics/utils"); +const httpStatusCode = require("../../generics/http-status"); +const apiResponses = require("../../constants/api-responses"); +const common = require('../../constants/common'); +const usersData = require("../../db/users/queries"); + +module.exports = class ProfileHelper { + + static async update(bodyData, _id) { + bodyData.updatedAt = new Date().getTime(); + try { + await usersData.updateOneUser({ _id: ObjectId(_id) }, bodyData); + return common.successResponse({ statusCode: httpStatusCode.accepted, message: apiResponses.PROFILE_UPDATED_SUCCESSFULLY }); + } catch (error) { + throw error; + } + } + + static async details(_id) { + const projection = { password: 0, "designation.deleted": 0, "designation._id": 0, "areasOfExpertise.deleted": 0, "areasOfExpertise._id": 0, "location.deleted": 0, "location._id": 0, refreshTokens: 0} + try { + const user = await usersData.findOne({ _id: ObjectId(_id) }, projection); + if (user && user.image) { + if (process.env.CLOUD_STORAGE === 'GCP') { + user.image = `https://storage.googleapis.com/${process.env.DEFAULT_GCP_BUCKET_NAME}/${user.image}`; + } else if (process.env.CLOUD_STORAGE === 'AWS') { + user.image = `https://${process.env.DEFAULT_AWS_BUCKET_NAME}.s3.ap-south-1.amazonaws.com/${user.image}`; + } else if (process.env.CLOUD_STORAGE === 'AZURE') { + user.image = `https://${process.env.AZURE_ACCOUNT_NAME}.blob.core.windows.net/${process.env.DEFAULT_AZURE_CONTAINER_NAME}/${user.image}`; + } + } + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.PROFILE_FETCHED_SUCCESSFULLY, result: user ? user : {}}); + } catch (error) { + throw error; + } + } +} \ No newline at end of file diff --git a/services/helper/systemUsers.js b/services/helper/systemUsers.js new file mode 100644 index 000000000..a14844c22 --- /dev/null +++ b/services/helper/systemUsers.js @@ -0,0 +1,56 @@ +const utilsHelper = require("../../generics/utils"); +const httpStatusCode = require("../../generics/http-status"); +const apiResponses = require("../../constants/api-responses"); +const common = require('../../constants/common'); +const systemUserData = require("../../db/systemUsers/queries"); + +module.exports = class SystemUsersHelper { + + static async create(bodyData) { + try { + const email = bodyData.email; + const user = await systemUserData.findUsersByEmail(email); + if (user) { + return common.failureResponse({ message: apiResponses.SYSTEM_USER_ALREADY_EXISTS, statusCode: httpStatusCode.not_acceptable, responseCode: 'CLIENT_ERROR' }); + } + + bodyData.password = utilsHelper.hashPassword(bodyData.password); + bodyData.email = { address: email, verified: false }; + await systemUserData.create(bodyData); + return common.successResponse({ statusCode: httpStatusCode.created, message: apiResponses.USER_CREATED_SUCCESSFULLY }); + } catch (error) { + throw error; + } + } + + static async login(bodyData) { + try { + let user = await systemUserData.findUsersByEmail(bodyData.email); + if (!user) { + return common.failureResponse({ message: apiResponses.USER_DOESNOT_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + const isPasswordCorrect = utilsHelper.comparePassword(bodyData.password, user.password); + if (!isPasswordCorrect) { + return common.failureResponse({ message: apiResponses.PASSWORD_INVALID, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + + const tokenDetail = { + data: { + _id: user._id, + email: user.email.address, + role: user.role + } + }; + + const accessToken = utilsHelper.generateToken(tokenDetail, process.env.ACCESS_TOKEN_SECRET, '1d'); + const refreshToken = utilsHelper.generateToken(tokenDetail, process.env.REFRESH_TOKEN_SECRET, '183d'); + + delete user.password; + const result = { access_token: accessToken, refresh_token: refreshToken, user }; + + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.LOGGED_IN_SUCCESSFULLY, result }); + } catch (error) { + throw error; + } + } +} \ No newline at end of file diff --git a/services/helper/userentity.js b/services/helper/userentity.js new file mode 100644 index 000000000..93d3b8935 --- /dev/null +++ b/services/helper/userentity.js @@ -0,0 +1,69 @@ +const ObjectId = require('mongoose').Types.ObjectId; + +const utilsHelper = require("../../generics/utils"); +const httpStatusCode = require("../../generics/http-status"); +const apiResponses = require("../../constants/api-responses"); +const common = require('../../constants/common'); +const userEntitiesData = require("../../db/userentities/query"); + +module.exports = class UserEntityHelper { + + static async create(bodyData, _id) { + bodyData.createdBy = ObjectId(_id); + bodyData.updatedBy = ObjectId(_id); + try { + const filter = { type: bodyData.type, code: bodyData.code }; + const entity = await userEntitiesData.findOneEntity(filter); + if (entity) { + return common.failureResponse({ message: apiResponses.USER_ENTITY_ALREADY_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + await userEntitiesData.createEntity(bodyData); + return common.successResponse({ statusCode: httpStatusCode.created, message: apiResponses.USER_ENTITY_CREATED_SUCCESSFULLY }); + } catch (error) { + throw error; + } + } + + static async update(bodyData, _id, loggedInUserId) { + bodyData.updatedBy = ObjectId(loggedInUserId); + bodyData.updatedAt = new Date().getTime(); + try { + const result = await userEntitiesData.updateOneEntity({ _id: ObjectId(_id) }, bodyData); + if (result === 'ENTITY_ALREADY_EXISTS') { + return common.failureResponse({ message: apiResponses.USER_ENTITY_ALREADY_EXISTS, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } else if (result === 'ENTITY_NOT_FOUND') { + return common.failureResponse({ message: apiResponses.USER_ENTITY_NOT_FOUND, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + return common.successResponse({ statusCode: httpStatusCode.accepted, message: apiResponses.USER_ENTITY_UPDATED_SUCCESSFULLY }); + } catch (error) { + throw error; + } + } + + static async read(bodyData) { + const projection = { value: 1, label: 1, _id: 0 }; + if (!bodyData.deleted) { + bodyData.deleted = false; + } + try { + const entities = await userEntitiesData.findAllEntities(bodyData, projection); + return common.successResponse({ statusCode: httpStatusCode.ok, message: apiResponses.USER_ENTITY_FETCHED_SUCCESSFULLY, result: entities }); + } catch (error) { + throw error; + } + } + + static async delete(_id) { + try { + const result = await userEntitiesData.updateOneEntity({ _id: ObjectId(_id) }, { deleted: true }); + if (result === 'ENTITY_ALREADY_EXISTS') { + return common.failureResponse({ message: apiResponses.USER_ENTITY_ALREADY_DELETED, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } else if (result === 'ENTITY_NOT_FOUND') { + return common.failureResponse({ message: apiResponses.USER_ENTITY_NOT_FOUND, statusCode: httpStatusCode.bad_request, responseCode: 'CLIENT_ERROR' }); + } + return common.successResponse({ statusCode: httpStatusCode.accepted, message: apiResponses.USER_ENTITY_DELETED_SUCCESSFULLY }); + } catch (error) { + throw error; + } + } +} \ No newline at end of file diff --git a/validators/v1/account.js b/validators/v1/account.js new file mode 100644 index 000000000..5267e5a94 --- /dev/null +++ b/validators/v1/account.js @@ -0,0 +1,85 @@ +/** + * name : validators/v1/accounts.js + * author : Aman Gupta + * Date : 20-Oct-2021 + * Description : Validations of accounts controller +*/ + +module.exports = { + create: (req) => { + req.checkBody('name') + .trim() + .notEmpty() + .withMessage('name field is empty') + .matches(/^[A-Za-z ]+$/) + .withMessage('name is invalid'); + + req.checkBody('email') + .trim() + .notEmpty() + .withMessage('email field is empty') + .isEmail() + .withMessage('email is invalid') + .normalizeEmail(); + + req.checkBody('password') + .trim() + .notEmpty() + .withMessage('password field is empty'); + }, + + login: (req) => { + req.checkBody('email') + .trim() + .notEmpty() + .withMessage('email field is empty') + .isEmail() + .withMessage('email is invalid') + .normalizeEmail(); + + req.checkBody('password') + .trim() + .notEmpty() + .withMessage('password field is empty'); + }, + + logout: (req) => { + req.checkBody('refreshToken') + .notEmpty() + .withMessage('refreshToken field is empty'); + }, + + generateToken: (req) => { + req.checkBody('refreshToken') + .notEmpty() + .withMessage('refreshToken field is empty'); + }, + + generateOtp: (req) => { + req.checkBody('email') + .notEmpty() + .withMessage('email field is empty') + .isEmail() + .withMessage('email is invalid'); + }, + + resetPassword: (req) => { + req.checkBody('email') + .notEmpty() + .withMessage('email field is empty') + .isEmail() + .withMessage('email is invalid'); + + req.checkBody('password') + .notEmpty() + .withMessage('password field is empty'); + + req.checkBody('otp') + .notEmpty() + .withMessage('otp field is empty') + .matches(/^[0-9]+$/) + .withMessage('otp should be number') + .isLength({ min: 6, max: 6 }) + .withMessage('otp is invalid'); + } +}; \ No newline at end of file diff --git a/validators/v1/cloud-services.js b/validators/v1/cloud-services.js new file mode 100644 index 000000000..ee8a4eb32 --- /dev/null +++ b/validators/v1/cloud-services.js @@ -0,0 +1,15 @@ +/** + * name : validators/v1/cloud-services.js + * author : Aman Gupta + * Date : 16-Nov-2021 + * Description : Validations of cloud-services controller +*/ + +module.exports = { + getSignedUrl: (req) => { + req.checkQuery('fileName') + .trim() + .notEmpty() + .withMessage('fileName field is empty'); + } +}; \ No newline at end of file diff --git a/validators/v1/form.js b/validators/v1/form.js new file mode 100644 index 000000000..bcaca24ca --- /dev/null +++ b/validators/v1/form.js @@ -0,0 +1,139 @@ +/** + * name : validators/v1/form.js + * author : Aman Gupta + * Date : 03-Nov-2021 + * Description : Validations of forms controller +*/ + +module.exports = { + create: (req) => { + req.checkBody('type') + .trim() + .notEmpty() + .withMessage('type field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('type is invalid'); + + req.checkBody('subType') + .trim() + .notEmpty() + .withMessage('subType field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('subType is invalid'); + + req.checkBody('action') + .trim() + .notEmpty() + .withMessage('action field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('action is invalid'); + + req.checkBody('ver') + .trim() + .notEmpty() + .withMessage('ver field is empty') + .isString() + .withMessage('ver is invalid'); + + req.checkBody('data') + .notEmpty() + .withMessage('data field is empty'); + + req.checkBody('data.templateName') + .trim() + .notEmpty() + .withMessage('templateName field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('templateName is invalid, must be string'); + + req.checkBody('data.fields') + .notEmpty() + .withMessage('fields field is empty'); + + }, + + update: (req) => { + + req.checkBody('type') + .notEmpty() + .withMessage('type field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('type is invalid'); + + req.checkBody('subType') + .notEmpty() + .withMessage('subType field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('subType is invalid'); + + req.checkBody('action') + .notEmpty() + .withMessage('action field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('action is invalid'); + + req.checkBody('ver') + .notEmpty() + .withMessage('ver field is empty') + .isString() + .withMessage('ver is invalid'); + + req.checkBody('data.templateName') + .notEmpty() + .withMessage('data.templateName field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('templateName is invalid') + .custom((value) => { + if (!req.body.data.fields) { + throw new Error('fields key is not passed while passing data.templateName'); + } + return true; + }); + + req.checkBody('data.fields') + .optional() + .custom((value) => { + if (!req.body.data.templateName) { + throw new Error('templateName key is not passed while updating data.fields'); + } + return true; + }); + }, + + read: (req) => { + req.checkBody('type') + .trim() + .notEmpty() + .withMessage('type field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('type is invalid'); + + req.checkBody('subType') + .trim() + .notEmpty() + .withMessage('subType field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('subType is invalid'); + + req.checkBody('action') + .trim() + .notEmpty() + .withMessage('action field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('action is invalid'); + + req.checkBody('ver') + .trim() + .notEmpty() + .withMessage('ver field is empty') + .isString() + .withMessage('ver is invalid'); + + req.checkBody('templateName') + .trim() + .notEmpty() + .withMessage('templateName field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('templateName is invalid'); + } +}; \ No newline at end of file diff --git a/validators/v1/profile.js b/validators/v1/profile.js index e67d31278..1aef34b53 100644 --- a/validators/v1/profile.js +++ b/validators/v1/profile.js @@ -1,6 +1,65 @@ /** - * name : validators/v1/profile - * author : Aman Kumar Gupta - * Date : 01-Oct-2021 - * Description : Contains express-validators for profile request data - */ \ No newline at end of file + * name : validators/v1/profile.js + * author : Aman Gupta + * Date : 01-Nov-2021 + * Description : Validations of profiles controller +*/ + +module.exports = { + update: (req) => { + req.checkBody('gender') + .trim() + .optional() + .isIn(['MALE', 'FEMALE', 'OTHER']) + .withMessage('gender is invalid, must be either MALE, FEMALE or OTHER'); + + req.checkBody('name') + .trim() + .notEmpty() + .withMessage('name field is empty') + .matches(/^[A-Za-z ]+$/) + .withMessage('name is invalid'); + + req.checkBody('designation') + .notEmpty() + .withMessage('designation field is empty') + .isArray() + .withMessage('designation is invalid') + + req.checkBody('location') + .notEmpty() + .withMessage('location field is empty') + .isArray() + .withMessage('location is invalid') + + req.checkBody('about') + .notEmpty() + .withMessage('about field is empty') + + req.checkBody('areasOfExpertise') + .notEmpty() + .withMessage('areasOfExpertise field is empty') + .isArray() + .withMessage('areasOfExpertise is invalid') + + req.checkBody('experience') + .notEmpty() + .withMessage('experience field is empty') + .isFloat() + .withMessage('experience is invalid') + + req.checkBody('hasAcceptedTAndC') + .optional() + .isBoolean() + .withMessage('hasAcceptedTAndC field is invalid') + + req.checkBody('image') + .optional() + .isString() + .withMessage('image field must be string only') + }, + + details: (req) => { + + } +}; \ No newline at end of file diff --git a/validators/v1/systemUsers.js b/validators/v1/systemUsers.js new file mode 100644 index 000000000..9e8a6797a --- /dev/null +++ b/validators/v1/systemUsers.js @@ -0,0 +1,52 @@ +/** + * name : validators/v1/accounts.js + * author : Aman Gupta + * Date : 20-Oct-2021 + * Description : Validations of accounts controller +*/ + +module.exports = { + create: (req) => { + req.checkBody('name') + .trim() + .notEmpty() + .withMessage('name field is empty') + .matches(/^[A-Za-z ]+$/) + .withMessage('name is invalid'); + + req.checkBody('email') + .trim() + .notEmpty() + .withMessage('email field is empty') + .isEmail() + .withMessage('email is invalid') + .normalizeEmail(); + + req.checkBody('password') + .trim() + .notEmpty() + .withMessage('password field is empty'); + + req.checkBody('role') + .trim() + .notEmpty() + .withMessage('role field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('role is invalid, and should not contain spaces'); + }, + + login: (req) => { + req.checkBody('email') + .trim() + .notEmpty() + .withMessage('email field is empty') + .isEmail() + .withMessage('email is invalid') + .normalizeEmail(); + + req.checkBody('password') + .trim() + .notEmpty() + .withMessage('password field is empty'); + } +}; \ No newline at end of file diff --git a/validators/v1/user.js b/validators/v1/user.js deleted file mode 100644 index a622e1a7e..000000000 --- a/validators/v1/user.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * name : validators/v1/user - * author : Aman Kumar Gupta - * Date : 01-Oct-2021 - * Description : Contains express-validators for user request data - */ \ No newline at end of file diff --git a/validators/v1/userentity.js b/validators/v1/userentity.js new file mode 100644 index 000000000..44525d90e --- /dev/null +++ b/validators/v1/userentity.js @@ -0,0 +1,94 @@ +/** + * name : validators/v1/userentity.js + * author : Aman Gupta + * Date : 04-Nov-2021 + * Description : Validations of user entities controller +*/ + +module.exports = { + create: (req) => { + req.checkBody('value') + .trim() + .notEmpty() + .withMessage('value field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('value is invalid, must not contain spaces'); + + req.checkBody('label') + .trim() + .notEmpty() + .withMessage('label field is empty') + .matches(/^[A-Za-z0-9 ]+$/) + .withMessage('label is invalid'); + + req.checkBody('type') + .trim() + .notEmpty() + .withMessage('type field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('type is invalid, must not contain spaces'); + }, + + update: (req) => { + + req.checkParams('id') + .notEmpty() + .withMessage('id param is empty') + .isMongoId() + .withMessage('id is invalid'); + + req.checkBody('value') + .optional() + .matches(/^[A-Za-z]+$/) + .withMessage('value is invalid, must not contain spaces'); + + req.checkBody('label') + .optional() + .matches(/^[A-Za-z0-9 ]+$/) + .withMessage('label is invalid'); + + req.checkBody('status') + .optional() + .matches(/^[A-Z]+$/) + .withMessage('status is invalid, must be in all caps'); + + req.checkBody('deleted') + .optional() + .isBoolean() + .withMessage('deleted is invalid'); + + req.checkBody('type') + .optional() + .matches(/^[A-Za-z]+$/) + .withMessage('type is invalid, must not contain spaces'); + }, + + read: (req) => { + req.checkQuery('type') + .trim() + .notEmpty() + .withMessage('type field is empty') + .matches(/^[A-Za-z]+$/) + .withMessage('type is invalid, must not contain spaces'); + + req.checkQuery('deleted') + .optional() + .isBoolean() + .withMessage('deleted is invalid'); + + req.checkQuery('status') + .optional() + .trim() + .matches(/^[A-Z]+$/) + .withMessage('status is invalid, must be in all caps'); + }, + + delete: (req) => { + + req.checkParams('id') + .notEmpty() + .withMessage('id param is empty') + .isMongoId() + .withMessage('id is invalid'); + }, +}; \ No newline at end of file diff --git a/validators/v2/user.js b/validators/v2/user.js deleted file mode 100644 index ac31db204..000000000 --- a/validators/v2/user.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * name : validators/v2/user - * author : Aman Kumar Gupta - * Date : 01-Oct-2021 - * Description : Contains express-validators for user request data - */ \ No newline at end of file