diff --git a/server/email/sendemail.js b/server/email/sendemail.js index 3a07486b7..65b5a60ce 100644 --- a/server/email/sendemail.js +++ b/server/email/sendemail.js @@ -96,6 +96,20 @@ const sendServerEmail = async ({ subject, text }) => { } }; +const sendProManagerWelcomeEmail = async (to, subject, html) => { + try { + await transporter.sendMail({ + from: `ProManager `, + to, + subject, + html + }); + } catch (error) { + console.log(error); + logger.log("server-email-failure", "error", null, null, error); + } +}; + const sendTaskEmail = async ({ to, subject, type = "text", html, text, attachments }) => { try { transporter.sendMail( @@ -309,5 +323,6 @@ module.exports = { sendEmail, sendServerEmail, sendTaskEmail, + sendProManagerWelcomeEmail, emailBounce }; diff --git a/server/firebase/firebase-handler.js b/server/firebase/firebase-handler.js index 509bedce9..e47eeffc1 100644 --- a/server/firebase/firebase-handler.js +++ b/server/firebase/firebase-handler.js @@ -1,30 +1,28 @@ -const admin = require("firebase-admin"); -const logger = require("../utils/logger"); const path = require("path"); -const { auth } = require("firebase-admin"); - require("dotenv").config({ path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`) }); -const client = require("../graphql-client/graphql-client").client; +const admin = require("firebase-admin"); +const logger = require("../utils/logger"); +const { sendProManagerWelcomeEmail } = require("../email/sendemail"); +const client = require("../graphql-client/graphql-client").client; const serviceAccount = require(process.env.FIREBASE_ADMINSDK_JSON); -const adminEmail = require("../utils/adminEmail"); +const generateEmailTemplate = require("../email/generateTemplate"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: process.env.FIREBASE_DATABASE_URL }); -exports.admin = admin; - -exports.createUser = async (req, res) => { +const createUser = async (req, res) => { logger.log("admin-create-user", "ADMIN", req.user.email, null, { request: req.body, ioadmin: true }); - const { email, displayName, password, shopid, authlevel } = req.body; + const { email, displayName, password, shopid, authlevel, validemail } = req.body; + try { const userRecord = await admin.auth().createUser({ email, displayName, password }); @@ -42,6 +40,7 @@ exports.createUser = async (req, res) => { user: { email: email.toLowerCase(), authid: userRecord.uid, + validemail, associations: { data: [{ shopid, authlevel, active: true }] } @@ -58,21 +57,115 @@ exports.createUser = async (req, res) => { } }; -exports.updateUser = (req, res) => { +const sendPromanagerWelcomeEmail = (req, res) => { + const { authid, email } = req.body; + + // Fetch user from Firebase + admin + .auth() + .getUser(authid) + .then((userRecord) => { + if (!userRecord) { + return Promise.reject({ status: 404, message: "User not found in Firebase." }); + } + + // Fetch user data from the database using GraphQL + return client.request( + ` + query GET_USER_BY_EMAIL($email: String!) { + users(where: { email: { _eq: $email } }) { + email + validemail + associations { + id + shopid + bodyshop { + id + convenient_company + } + } + } + }`, + { email: email.toLowerCase() } + ); + }) + .then((dbUserResult) => { + const dbUser = dbUserResult?.users?.[0]; + if (!dbUser) { + return Promise.reject({ status: 404, message: "User not found in database." }); + } + + // Validate email before proceeding + if (!dbUser.validemail) { + logger.log("admin-send-welcome-email-skip", "ADMIN", req.user.email, null, { + message: "User email is not valid, skipping email.", + email + }); + return res.status(200).json({ message: "User email is not valid, email not sent." }); + } + + // Check if the user's company is ProManager + const convenientCompany = dbUser.associations?.[0]?.bodyshop?.convenient_company; + if (convenientCompany !== "promanager") { + logger.log("admin-send-welcome-email-skip", "ADMIN", req.user.email, null, { + message: 'convenient_company is not "promanager", skipping email.', + convenientCompany + }); + return res.status(200).json({ message: `convenient_company is not "promanager", email not sent.` }); + } + + // Generate password reset link + return admin + .auth() + .generatePasswordResetLink(dbUser.email) + .then((resetLink) => ({ dbUser, resetLink })); + }) + .then(({ dbUser, resetLink }) => { + // Send welcome email (replace with your actual email-sending service) + return sendProManagerWelcomeEmail({ + to: dbUser.email, + subject: "Welcome to the ProManager platform.", + html: generateEmailTemplate({ + header: "", + subHeader: "", + body: ` +

Welcome to the ProManager platform. Please click the link below to reset your password:

+

Reset your password

+

User Details:

+ + ` + }) + }); + }) + .then(() => { + // Log success and return response + logger.log("admin-send-welcome-email", "ADMIN", req.user.email, null, { + request: req.body, + ioadmin: true, + emailSentTo: email + }); + res.status(200).json({ message: "Welcome email sent successfully." }); + }) + .catch((error) => { + logger.log("admin-send-welcome-email-error", "ERROR", req.user.email, null, { error }); + + if (!res.headersSent) { + res.status(error.status || 500).json({ + message: error.message || "Error sending welcome email.", + error + }); + } + }); +}; + +const updateUser = (req, res) => { logger.log("admin-update-user", "ADMIN", req.user.email, null, { request: req.body, ioadmin: true }); - if (!adminEmail.includes(req.user.email) && !req.user.ioadmin) { - logger.log("admin-update-user-unauthorized", "ERROR", req.user.email, null, { - request: req.body, - user: req.user - }); - res.sendStatus(404); - return; - } - admin .auth() .updateUser( @@ -105,26 +198,46 @@ exports.updateUser = (req, res) => { }); }; -exports.getUser = (req, res) => { +const getUser = (req, res) => { logger.log("admin-get-user", "ADMIN", req.user.email, null, { request: req.body, ioadmin: true }); - if (!adminEmail.includes(req.user.email) && !req.user.ioadmin) { - logger.log("admin-update-user-unauthorized", "ERROR", req.user.email, null, { - request: req.body, - user: req.user - }); - res.sendStatus(404); - return; - } - admin .auth() .getUser(req.body.uid) .then((userRecord) => { - res.json(userRecord); + return client + .request( + ` + query GET_USER_BY_AUTHID($authid: String!) { + users(where: { authid: { _eq: $authid } }) { + email + displayName + validemail + associations { + id + shopid + bodyshop { + id + convenient_company + } + } + } + } + `, + { authid: req.body.uid } + ) + .then((dbUserResult) => { + res.json({ + ...userRecord, + db: { + validemail: dbUserResult?.users?.[0]?.validemail, + company: dbUserResult?.users?.[0]?.associations?.[0]?.bodyshop?.convenient_company + } + }); + }); }) .catch((error) => { logger.log("admin-get-user-error", "ERROR", req.user.email, null, { @@ -134,7 +247,7 @@ exports.getUser = (req, res) => { }); }; -exports.sendNotification = async (req, res) => { +const sendNotification = async (req, res) => { setTimeout(() => { // Send a message to the device corresponding to the provided // registration token. @@ -167,7 +280,7 @@ exports.sendNotification = async (req, res) => { }, 500); }; -exports.subscribe = async (req, res) => { +const subscribe = async (req, res) => { const result = await admin .messaging() .subscribeToTopic(req.body.fcm_tokens, `${req.body.imexshopid}-${req.body.type}`); @@ -175,7 +288,7 @@ exports.subscribe = async (req, res) => { res.json(result); }; -exports.unsubscribe = async (req, res) => { +const unsubscribe = async (req, res) => { try { const result = await admin .messaging() @@ -187,6 +300,17 @@ exports.unsubscribe = async (req, res) => { } }; +module.exports = { + admin, + createUser, + updateUser, + getUser, + sendPromanagerWelcomeEmail, + sendNotification, + subscribe, + unsubscribe +}; + //Admin claims code. // const uid = "JEqqYlsadwPEXIiyRBR55fflfko1"; diff --git a/server/routes/adminRoutes.js b/server/routes/adminRoutes.js index c1d3fe85a..ac0ebb6fb 100644 --- a/server/routes/adminRoutes.js +++ b/server/routes/adminRoutes.js @@ -1,18 +1,20 @@ const express = require("express"); const router = express.Router(); -const fb = require("../firebase/firebase-handler"); const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware"); const { createAssociation, createShop, updateShop, updateCounter } = require("../admin/adminops"); +const { updateUser, getUser, createUser, sendPromanagerWelcomeEmail } = require("../firebase/firebase-handler"); const validateAdminMiddleware = require("../middleware/validateAdminMiddleware"); router.use(validateFirebaseIdTokenMiddleware); +router.use(validateAdminMiddleware); -router.post("/createassociation", validateAdminMiddleware, createAssociation); -router.post("/createshop", validateAdminMiddleware, createShop); -router.post("/updateshop", validateAdminMiddleware, updateShop); -router.post("/updatecounter", validateAdminMiddleware, updateCounter); -router.post("/updateuser", fb.updateUser); -router.post("/getuser", fb.getUser); -router.post("/createuser", fb.createUser); +router.post("/createassociation", createAssociation); +router.post("/createshop", createShop); +router.post("/updateshop", updateShop); +router.post("/updatecounter", updateCounter); +router.post("/updateuser", updateUser); +router.post("/getuser", getUser); +router.post("/createuser", createUser); +router.post("/promanagerwelcome", sendPromanagerWelcomeEmail); module.exports = router;