From 35c3a61c0f82bb8403a8d705d561a5239173de98 Mon Sep 17 00:00:00 2001 From: abdelmounaim lallouache Date: Sat, 30 Dec 2023 19:44:01 -0600 Subject: [PATCH 1/2] update --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index ff66994e8..72a8c1013 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5552,7 +5552,7 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, "lodash.merge": { "version": "4.6.2", From 82b95b20977e600573c8c37c2261285730552b83 Mon Sep 17 00:00:00 2001 From: abdelmounaim lallouache Date: Sun, 7 Jan 2024 01:12:38 -0600 Subject: [PATCH 2/2] added endpoint for map country count --- .../profileInitialSetupController.js | 304 ++++++++++-------- src/routes/profileInitialSetupRouter.js | 1 + src/startup/middleware.js | 2 +- 3 files changed, 172 insertions(+), 135 deletions(-) diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js index 12776442e..d89f08064 100644 --- a/src/controllers/profileInitialSetupController.js +++ b/src/controllers/profileInitialSetupController.js @@ -1,10 +1,10 @@ -const mongoose = require('mongoose'); -const { v4: uuidv4 } = require('uuid'); -const moment = require('moment-timezone'); -const jwt = require('jsonwebtoken'); -const emailSender = require('../utilities/emailSender'); -const config = require('../config'); -const cache = require('../utilities/nodeCache')(); +const mongoose = require("mongoose"); +const { v4: uuidv4 } = require("uuid"); +const moment = require("moment-timezone"); +const jwt = require("jsonwebtoken"); +const emailSender = require("../utilities/emailSender"); +const config = require("../config"); +const cache = require("../utilities/nodeCache")(); // returns the email body that includes the setup link for the recipient. function sendLinkMessage(Link) { @@ -78,18 +78,10 @@ function informManagerMessage(user) { const sendEmailWithAcknowledgment = (email, subject, message) => { return new Promise((resolve, reject) => { - emailSender( - email, - subject, - message, - null, - null, - null, - (error,result) => { - if (result) resolve(result) - if (error) reject(result) - } - ); + emailSender(email, subject, message, null, null, null, (error, result) => { + if (result) resolve(result); + if (error) reject(result); + }); }); }; @@ -102,16 +94,18 @@ const profileInitialSetupController = function ( const { JWT_SECRET } = config; const setMapLocation = async (locationData) => { - const location = new MapLocation(locationData); try { - const response = await location.save() - return response + const response = await location.save(); + return response; } catch (err) { - return {type: "Error", message: err.message || 'An error occurred while saving the location'} + return { + type: "Error", + message: err.message || "An error occurred while saving the location", + }; } - } + }; /* Function to handle token generation and email process: @@ -124,13 +118,13 @@ const profileInitialSetupController = function ( let { email, baseUrl, weeklyCommittedHours } = req.body; email = email.toLowerCase(); const token = uuidv4(); - const expiration = moment().tz('America/Los_Angeles').add(1, 'week'); + const expiration = moment().tz("America/Los_Angeles").add(1, "week"); try { const existingEmail = await userProfile.findOne({ email, }); if (existingEmail) { - res.status(400).send('email already in use'); + res.status(400).send("email already in use"); } else { await ProfileInitialSetupToken.findOneAndDelete({ email }); @@ -149,7 +143,7 @@ const profileInitialSetupController = function ( "NEEDED: Complete your One Community profile setup", sendLinkMessage(link) ); - + res.status(200).send(acknowledgment); } } catch (error) { @@ -164,7 +158,7 @@ const profileInitialSetupController = function ( */ const validateSetupToken = async (req, res) => { const { token } = req.body; - const currentMoment = moment.tz('America/Los_Angeles'); + const currentMoment = moment.tz("America/Los_Angeles"); try { const foundToken = await ProfileInitialSetupToken.findOne({ token }); @@ -174,10 +168,10 @@ const profileInitialSetupController = function ( if (expirationMoment.isAfter(currentMoment)) { res.status(200).send(foundToken); } else { - res.status(400).send('Invalid token'); + res.status(400).send("Invalid token"); } } else { - res.status(404).send('Token not found'); + res.status(404).send("Token not found"); } } catch (error) { res.status(500).send(`Error finding token: ${error}`); @@ -195,119 +189,120 @@ const profileInitialSetupController = function ( */ const setUpNewUser = async (req, res) => { const { token } = req.body; - const currentMoment = moment.tz('America/Los_Angeles'); + const currentMoment = moment.tz("America/Los_Angeles"); try { const foundToken = await ProfileInitialSetupToken.findOne({ token }); const existingEmail = await userProfile.findOne({ email: foundToken.email, }); if (existingEmail) { - res.status(400).send('email already in use'); + res.status(400).send("email already in use"); } else if (foundToken) { - const expirationMoment = moment(foundToken.expiration); - - if (expirationMoment.isAfter(currentMoment)) { - const defaultProject = await Project.findOne({ - projectName: 'Orientation and Initial Setup', - }); - - const newUser = new userProfile(); - newUser.password = req.body.password; - newUser.role = 'Volunteer'; - newUser.firstName = req.body.firstName; - newUser.lastName = req.body.lastName; - newUser.jobTitle = req.body.jobTitle; - newUser.phoneNumber = req.body.phoneNumber; - newUser.bio = ''; - newUser.weeklycommittedHours = foundToken.weeklyCommittedHours; - newUser.weeklycommittedHoursHistory = [ - { - hours: newUser.weeklycommittedHours, - dateChanged: Date.now(), - }, - ]; - newUser.personalLinks = []; - newUser.adminLinks = []; - newUser.teams = Array.from(new Set([])); - newUser.projects = Array.from(new Set([defaultProject])); - newUser.createdDate = Date.now(); - newUser.email = req.body.email; - newUser.weeklySummaries = [{ summary: '' }]; - newUser.weeklySummariesCount = 0; - newUser.weeklySummaryOption = 'Required'; - newUser.mediaUrl = ''; - newUser.collaborationPreference = req.body.collaborationPreference; - newUser.timeZone = req.body.timeZone || 'America/Los_Angeles'; - newUser.location = req.body.location; - newUser.profilePic = req.body.profilePicture; - newUser.permissions = { - frontPermissions: [], - backPermissions: [], - }; - newUser.bioPosted = 'default'; - newUser.privacySettings.email = req.body.privacySettings.email; - newUser.privacySettings.phoneNumber = req.body.privacySettings.phoneNumber; - newUser.teamCode = ''; - newUser.isFirstTimelog = true; - - const savedUser = await newUser.save(); - - emailSender( - process.env.MANAGER_EMAIL || 'jae@onecommunityglobal.org', // "jae@onecommunityglobal.org" - `NEW USER REGISTERED: ${savedUser.firstName} ${savedUser.lastName}`, - informManagerMessage(savedUser), - null, - null, - ); - await ProfileInitialSetupToken.findByIdAndDelete(foundToken._id); - - const jwtPayload = { - userid: savedUser._id, - role: savedUser.role, - permissions: savedUser.permissions, - expiryTimestamp: moment().add( - config.TOKEN.Lifetime, - config.TOKEN.Units, - ), - }; - - const token = jwt.sign(jwtPayload, JWT_SECRET); - - const locationData = { - firstName: req.body.firstName, - lastName: req.body.lastName, - jobTitle: req.body.jobTitle, - location: req.body.homeCountry, - } - - res.send({ token }).status(200); - - const mapEntryResult = await setMapLocation(locationData) - if(mapEntryResult.type === "Error"){ - console.log(mapEntryResult.message) - } - - const NewUserCache = { - permissions: savedUser.permissions, - isActive: true, - weeklycommittedHours: savedUser.weeklycommittedHours, - createdDate: savedUser.createdDate.toISOString(), - _id: savedUser._id, - role: savedUser.role, - firstName: savedUser.firstName, - lastName: savedUser.lastName, - email: savedUser.email, - }; - - const allUserCache = JSON.parse(cache.getCache('allusers')); - allUserCache.push(NewUserCache); - cache.setCache('allusers', JSON.stringify(allUserCache)); - } else { - res.status(400).send('Token is expired'); + const expirationMoment = moment(foundToken.expiration); + + if (expirationMoment.isAfter(currentMoment)) { + const defaultProject = await Project.findOne({ + projectName: "Orientation and Initial Setup", + }); + + const newUser = new userProfile(); + newUser.password = req.body.password; + newUser.role = "Volunteer"; + newUser.firstName = req.body.firstName; + newUser.lastName = req.body.lastName; + newUser.jobTitle = req.body.jobTitle; + newUser.phoneNumber = req.body.phoneNumber; + newUser.bio = ""; + newUser.weeklycommittedHours = foundToken.weeklyCommittedHours; + newUser.weeklycommittedHoursHistory = [ + { + hours: newUser.weeklycommittedHours, + dateChanged: Date.now(), + }, + ]; + newUser.personalLinks = []; + newUser.adminLinks = []; + newUser.teams = Array.from(new Set([])); + newUser.projects = Array.from(new Set([defaultProject])); + newUser.createdDate = Date.now(); + newUser.email = req.body.email; + newUser.weeklySummaries = [{ summary: "" }]; + newUser.weeklySummariesCount = 0; + newUser.weeklySummaryOption = "Required"; + newUser.mediaUrl = ""; + newUser.collaborationPreference = req.body.collaborationPreference; + newUser.timeZone = req.body.timeZone || "America/Los_Angeles"; + newUser.location = req.body.location; + newUser.profilePic = req.body.profilePicture; + newUser.permissions = { + frontPermissions: [], + backPermissions: [], + }; + newUser.bioPosted = "default"; + newUser.privacySettings.email = req.body.privacySettings.email; + newUser.privacySettings.phoneNumber = + req.body.privacySettings.phoneNumber; + newUser.teamCode = ""; + newUser.isFirstTimelog = true; + + const savedUser = await newUser.save(); + + emailSender( + process.env.MANAGER_EMAIL || "jae@onecommunityglobal.org", // "jae@onecommunityglobal.org" + `NEW USER REGISTERED: ${savedUser.firstName} ${savedUser.lastName}`, + informManagerMessage(savedUser), + null, + null + ); + await ProfileInitialSetupToken.findByIdAndDelete(foundToken._id); + + const jwtPayload = { + userid: savedUser._id, + role: savedUser.role, + permissions: savedUser.permissions, + expiryTimestamp: moment().add( + config.TOKEN.Lifetime, + config.TOKEN.Units + ), + }; + + const token = jwt.sign(jwtPayload, JWT_SECRET); + + const locationData = { + firstName: req.body.firstName, + lastName: req.body.lastName, + jobTitle: req.body.jobTitle, + location: req.body.homeCountry, + }; + + res.send({ token }).status(200); + + const mapEntryResult = await setMapLocation(locationData); + if (mapEntryResult.type === "Error") { + console.log(mapEntryResult.message); } + + const NewUserCache = { + permissions: savedUser.permissions, + isActive: true, + weeklycommittedHours: savedUser.weeklycommittedHours, + createdDate: savedUser.createdDate.toISOString(), + _id: savedUser._id, + role: savedUser.role, + firstName: savedUser.firstName, + lastName: savedUser.lastName, + email: savedUser.email, + }; + + const allUserCache = JSON.parse(cache.getCache("allusers")); + allUserCache.push(NewUserCache); + cache.setCache("allusers", JSON.stringify(allUserCache)); } else { - res.status(400).send('Invalid token'); + res.status(400).send("Token is expired"); } + } else { + res.status(400).send("Invalid token"); + } } catch (error) { res.status(500).send(`Error: ${error}`); } @@ -331,13 +326,54 @@ const profileInitialSetupController = function ( } }; - + const getTotalCountryCount = async (req, res) => { + try { + const users = []; + const results = await userProfile.find( + {}, + "location totalTangibleHrs hoursByCategory" + ); + + results.forEach((item) => { + if ( + (item.location?.coords.lat && + item.location?.coords.lng && + item.totalTangibleHrs >= 10) || + (item.location?.coords.lat && + item.location?.coords.lng && + calculateTotalHours(item.hoursByCategory) >= 10) + ) { + users.push(item); + } + }); + const modifiedUsers = users.map((item) => ({ + location: item.location, + })); + + const mapUsers = await MapLocation.find({}); + const combined = [...modifiedUsers, ...mapUsers]; + const countries = combined.map((user) => user.location.country); + const totalUniqueCountries = [...new Set(countries)].length; + res.status(200).send({ CountryCount: totalUniqueCountries }); + } catch (error) { + res.status(500).send(`Error: ${error}`); + } + }; + + function calculateTotalHours(hoursByCategory) { + let hours = 0; + Object.keys(hoursByCategory).forEach((x) => { + hours += hoursByCategory[x]; + }); + return hours; + } return { getSetupToken, setUpNewUser, validateSetupToken, getTimeZoneAPIKeyByToken, + getTotalCountryCount, }; }; diff --git a/src/routes/profileInitialSetupRouter.js b/src/routes/profileInitialSetupRouter.js index 12f677224..b514dbe53 100644 --- a/src/routes/profileInitialSetupRouter.js +++ b/src/routes/profileInitialSetupRouter.js @@ -8,6 +8,7 @@ const routes = function (ProfileInitialSetupToken, userProfile, Project , mapLoc ProfileInitialSetup.route('/ProfileInitialSetup').post(controller.setUpNewUser); ProfileInitialSetup.route('/validateToken').post(controller.validateSetupToken); ProfileInitialSetup.route('/getTimeZoneAPIKeyByToken').post(controller.getTimeZoneAPIKeyByToken); + ProfileInitialSetup.route('/getTotalCountryCount').get(controller.getTotalCountryCount); return ProfileInitialSetup; }; diff --git a/src/startup/middleware.js b/src/startup/middleware.js index 23ce1d4a6..5f79f77b8 100644 --- a/src/startup/middleware.js +++ b/src/startup/middleware.js @@ -22,7 +22,7 @@ module.exports = function (app) { next(); return; } - if (req.originalUrl === '/api/ProfileInitialSetup' || req.originalUrl === '/api/validateToken' || req.originalUrl === '/api/getTimeZoneAPIKeyByToken' && req.method === 'POST' + if (req.originalUrl === '/api/ProfileInitialSetup' || req.originalUrl === '/api/validateToken' || req.originalUrl === '/api/getTimeZoneAPIKeyByToken' && req.method === 'POST' || req.originalUrl === '/api/getTotalCountryCount' && req.method === 'GET' ) { next(); return;