Merged in release/2024-09-20 (pull request #1741)
Release/2024 09 20 IO-2934 IO-2920 IO-2936 IO-2920 IO-2933 IO-2921 IO-2939 IO-2932 IO-2782 IO-2948
This commit is contained in:
@@ -298,6 +298,16 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme
|
|||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: (a, b) => statusSort(a.status, b.status, activeStatuses),
|
sorter: (a, b) => statusSort(a.status, b.status, activeStatuses),
|
||||||
sortOrder: state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
sortOrder: state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
||||||
|
filters:
|
||||||
|
activeStatuses
|
||||||
|
?.map((s) => {
|
||||||
|
return {
|
||||||
|
text: s || "No Status*",
|
||||||
|
value: [s]
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.sort((a, b) => statusSort(a.text, b.text, activeStatuses)) || [],
|
||||||
|
onFilter: (value, record) => value.includes(record.status),
|
||||||
render: (text, record) => <ProductionListColumnStatus record={record} />
|
render: (text, record) => <ProductionListColumnStatus record={record} />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -96,6 +96,20 @@ const sendServerEmail = async ({ subject, text }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const sendProManagerWelcomeEmail = async (to, subject, html) => {
|
||||||
|
try {
|
||||||
|
await transporter.sendMail({
|
||||||
|
from: `ProManager <noreply@promanager.web-est.com>`,
|
||||||
|
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 }) => {
|
const sendTaskEmail = async ({ to, subject, type = "text", html, text, attachments }) => {
|
||||||
try {
|
try {
|
||||||
transporter.sendMail(
|
transporter.sendMail(
|
||||||
@@ -309,5 +323,6 @@ module.exports = {
|
|||||||
sendEmail,
|
sendEmail,
|
||||||
sendServerEmail,
|
sendServerEmail,
|
||||||
sendTaskEmail,
|
sendTaskEmail,
|
||||||
|
sendProManagerWelcomeEmail,
|
||||||
emailBounce
|
emailBounce
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,30 +1,28 @@
|
|||||||
const admin = require("firebase-admin");
|
|
||||||
const logger = require("../utils/logger");
|
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const { auth } = require("firebase-admin");
|
|
||||||
|
|
||||||
require("dotenv").config({
|
require("dotenv").config({
|
||||||
path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
|
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 serviceAccount = require(process.env.FIREBASE_ADMINSDK_JSON);
|
||||||
const adminEmail = require("../utils/adminEmail");
|
const generateEmailTemplate = require("../email/generateTemplate");
|
||||||
|
|
||||||
admin.initializeApp({
|
admin.initializeApp({
|
||||||
credential: admin.credential.cert(serviceAccount),
|
credential: admin.credential.cert(serviceAccount),
|
||||||
databaseURL: process.env.FIREBASE_DATABASE_URL
|
databaseURL: process.env.FIREBASE_DATABASE_URL
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.admin = admin;
|
const createUser = async (req, res) => {
|
||||||
|
|
||||||
exports.createUser = async (req, res) => {
|
|
||||||
logger.log("admin-create-user", "ADMIN", req.user.email, null, {
|
logger.log("admin-create-user", "ADMIN", req.user.email, null, {
|
||||||
request: req.body,
|
request: req.body,
|
||||||
ioadmin: true
|
ioadmin: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const { email, displayName, password, shopid, authlevel } = req.body;
|
const { email, displayName, password, shopid, authlevel, validemail } = req.body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const userRecord = await admin.auth().createUser({ email, displayName, password });
|
const userRecord = await admin.auth().createUser({ email, displayName, password });
|
||||||
|
|
||||||
@@ -42,6 +40,7 @@ exports.createUser = async (req, res) => {
|
|||||||
user: {
|
user: {
|
||||||
email: email.toLowerCase(),
|
email: email.toLowerCase(),
|
||||||
authid: userRecord.uid,
|
authid: userRecord.uid,
|
||||||
|
validemail,
|
||||||
associations: {
|
associations: {
|
||||||
data: [{ shopid, authlevel, active: true }]
|
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: `
|
||||||
|
<p>Welcome to the ProManager platform. Please click the link below to reset your password:</p>
|
||||||
|
<p><a href="${resetLink}">Reset your password</a></p>
|
||||||
|
<p>User Details:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Email: ${dbUser.email}</li>
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.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, {
|
logger.log("admin-update-user", "ADMIN", req.user.email, null, {
|
||||||
request: req.body,
|
request: req.body,
|
||||||
ioadmin: true
|
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
|
admin
|
||||||
.auth()
|
.auth()
|
||||||
.updateUser(
|
.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, {
|
logger.log("admin-get-user", "ADMIN", req.user.email, null, {
|
||||||
request: req.body,
|
request: req.body,
|
||||||
ioadmin: true
|
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
|
admin
|
||||||
.auth()
|
.auth()
|
||||||
.getUser(req.body.uid)
|
.getUser(req.body.uid)
|
||||||
.then((userRecord) => {
|
.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) => {
|
.catch((error) => {
|
||||||
logger.log("admin-get-user-error", "ERROR", req.user.email, null, {
|
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(() => {
|
setTimeout(() => {
|
||||||
// Send a message to the device corresponding to the provided
|
// Send a message to the device corresponding to the provided
|
||||||
// registration token.
|
// registration token.
|
||||||
@@ -167,7 +280,7 @@ exports.sendNotification = async (req, res) => {
|
|||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.subscribe = async (req, res) => {
|
const subscribe = async (req, res) => {
|
||||||
const result = await admin
|
const result = await admin
|
||||||
.messaging()
|
.messaging()
|
||||||
.subscribeToTopic(req.body.fcm_tokens, `${req.body.imexshopid}-${req.body.type}`);
|
.subscribeToTopic(req.body.fcm_tokens, `${req.body.imexshopid}-${req.body.type}`);
|
||||||
@@ -175,7 +288,7 @@ exports.subscribe = async (req, res) => {
|
|||||||
res.json(result);
|
res.json(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.unsubscribe = async (req, res) => {
|
const unsubscribe = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const result = await admin
|
const result = await admin
|
||||||
.messaging()
|
.messaging()
|
||||||
@@ -187,6 +300,17 @@ exports.unsubscribe = async (req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
admin,
|
||||||
|
createUser,
|
||||||
|
updateUser,
|
||||||
|
getUser,
|
||||||
|
sendPromanagerWelcomeEmail,
|
||||||
|
sendNotification,
|
||||||
|
subscribe,
|
||||||
|
unsubscribe
|
||||||
|
};
|
||||||
|
|
||||||
//Admin claims code.
|
//Admin claims code.
|
||||||
// const uid = "JEqqYlsadwPEXIiyRBR55fflfko1";
|
// const uid = "JEqqYlsadwPEXIiyRBR55fflfko1";
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
const express = require("express");
|
const express = require("express");
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const fb = require("../firebase/firebase-handler");
|
|
||||||
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
|
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
|
||||||
const { createAssociation, createShop, updateShop, updateCounter } = require("../admin/adminops");
|
const { createAssociation, createShop, updateShop, updateCounter } = require("../admin/adminops");
|
||||||
|
const { updateUser, getUser, createUser, sendPromanagerWelcomeEmail } = require("../firebase/firebase-handler");
|
||||||
const validateAdminMiddleware = require("../middleware/validateAdminMiddleware");
|
const validateAdminMiddleware = require("../middleware/validateAdminMiddleware");
|
||||||
|
|
||||||
router.use(validateFirebaseIdTokenMiddleware);
|
router.use(validateFirebaseIdTokenMiddleware);
|
||||||
|
router.use(validateAdminMiddleware);
|
||||||
|
|
||||||
router.post("/createassociation", validateAdminMiddleware, createAssociation);
|
router.post("/createassociation", createAssociation);
|
||||||
router.post("/createshop", validateAdminMiddleware, createShop);
|
router.post("/createshop", createShop);
|
||||||
router.post("/updateshop", validateAdminMiddleware, updateShop);
|
router.post("/updateshop", updateShop);
|
||||||
router.post("/updatecounter", validateAdminMiddleware, updateCounter);
|
router.post("/updatecounter", updateCounter);
|
||||||
router.post("/updateuser", fb.updateUser);
|
router.post("/updateuser", updateUser);
|
||||||
router.post("/getuser", fb.getUser);
|
router.post("/getuser", getUser);
|
||||||
router.post("/createuser", fb.createUser);
|
router.post("/createuser", createUser);
|
||||||
|
router.post("/promanagerwelcome", sendPromanagerWelcomeEmail);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
Reference in New Issue
Block a user