const path = require("path"); const queries = require("../graphql-client/queries"); const moment = require("moment-timezone"); const converter = require("json-2-csv"); const _ = require("lodash"); const logger = require("../utils/logger"); const fs = require("fs"); const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager"); require("dotenv").config({ path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`) }); let Client = require("ssh2-sftp-client"); const client = require("../graphql-client/graphql-client").client; const { sendServerEmail } = require("../email/sendemail"); const ftpSetup = { host: process.env.CHATTER_HOST, port: process.env.CHATTER_PORT, username: process.env.CHATTER_USER, privateKey: null, debug: (message, ...data) => logger.log(message, "DEBUG", "api", null, data), algorithms: { serverHostKey: ["ssh-rsa", "ssh-dss", "rsa-sha2-256", "rsa-sha2-512", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384"] } }; exports.default = async (req, res) => { // Only process if in production environment. if (process.env.NODE_ENV !== "production") { res.sendStatus(403); return; } if (req.headers["x-imex-auth"] !== process.env.AUTOHOUSE_AUTH_TOKEN) { res.sendStatus(401); return; } //Query for the List of Bodyshop Clients. logger.log("chatter-start", "DEBUG", "api", null, null); const { bodyshops } = await client.request(queries.GET_CHATTER_SHOPS); const specificShopIds = req.body.bodyshopIds; // ['uuid] const { start, end, skipUpload } = req.body; //YYYY-MM-DD const allcsvsToUpload = []; const allErrors = []; try { for (const bodyshop of specificShopIds ? bodyshops.filter((b) => specificShopIds.includes(b.id)) : bodyshops) { logger.log("chatter-start-shop-extract", "DEBUG", "api", bodyshop.id, { shopname: bodyshop.shopname }); try { const { jobs, bodyshops_by_pk } = await client.request(queries.CHATTER_QUERY, { bodyshopid: bodyshop.id, start: start ? moment(start).startOf("day") : moment().subtract(1, "days").startOf("day"), ...(end && { end: moment(end).endOf("day") }) }); const chatterObject = jobs.map((j) => { return { poc_trigger_code: bodyshops_by_pk.chatterid, firstname: j.ownr_co_nm ? null : j.ownr_fn, lastname: j.ownr_co_nm ? j.ownr_co_nm : j.ownr_ln, transaction_id: j.ro_number, email: j.ownr_ea, phone_number: j.ownr_ph1 }; }); const ret = converter.json2csv(chatterObject, { emptyFieldValue: "" }); allcsvsToUpload.push({ count: chatterObject.length, csv: ret, filename: `${bodyshop.shopname}_solicitation_${moment().format("YYYYMMDD")}.csv` }); logger.log("chatter-end-shop-extract", "DEBUG", "api", bodyshop.id, { shopname: bodyshop.shopname }); } catch (error) { //Error at the shop level. logger.log("chatter-error-shop", "ERROR", "api", bodyshop.id, { ...error }); allErrors.push({ bodyshopid: bodyshop.id, imexshopid: bodyshop.imexshopid, shopname: bodyshop.shopname, fatal: true, errors: [error.toString()] }); } finally { allErrors.push({ bodyshopid: bodyshop.id, imexshopid: bodyshop.imexshopid, shopname: bodyshop.shopname }); } } if (skipUpload) { for (const csvObj of allcsvsToUpload) { fs.writeFile(`./logs/${csvObj.filename}`, csvObj.csv); } sendServerEmail({ subject: `Chatter Report ${moment().format("MM-DD-YY")}`, text: `Errors: ${allErrors.map((e) => JSON.stringify(e, null, 2))} Uploaded: ${JSON.stringify( allcsvsToUpload.map((x) => ({ filename: x.filename, count: x.count })), null, 2 )} ` }); res.json(allcsvsToUpload); return; } const sftp = new Client(); sftp.on("error", (errors) => logger.log("chatter-sftp-error", "ERROR", "api", null, { ...errors })); try { //Get the private key from AWS Secrets Manager. ftpSetup.privateKey = await getPrivateKey(); //Connect to the FTP and upload all. await sftp.connect(ftpSetup); for (const csvObj of allcsvsToUpload) { logger.log("chatter-sftp-upload", "DEBUG", "api", null, { filename: csvObj.filename }); const uploadResult = await sftp.put(Buffer.from(csvObj.xml), `/${csvObj.filename}`); logger.log("chatter-sftp-upload-result", "DEBUG", "api", null, { uploadResult }); } } catch (error) { logger.log("chatter-sftp-error", "ERROR", "api", null, { ...error }); } finally { sftp.end(); } sendServerEmail({ subject: `Chatter Report ${moment().format("MM-DD-YY")}`, text: `Errors: ${allErrors.map((e) => JSON.stringify(e, null, 2))} Uploaded: ${JSON.stringify( allcsvsToUpload.map((x) => ({ filename: x.filename, count: x.count })), null, 2 )}` }); res.sendStatus(200); } catch (error) { res.status(200).json(error); } }; async function getPrivateKey() { // Connect to AWS Secrets Manager const client = new SecretsManagerClient({ region: "ca-central-1" }); const command = new GetSecretValueCommand({ SecretId: "CHATTER_PRIVATE_KEY" }); logger.log("chatter-get-private-key", "DEBUG", "api", null, null); try { const { SecretString, SecretBinary } = await client.send(command); if (SecretString || SecretBinary) logger.log("chatter-retrieved-private-key", "DEBUG", "api", null, null); const chatterPrivateKey = SecretString ? JSON.parse(SecretString) : JSON.parse(Buffer.from(SecretBinary, "base64").toString("ascii")); return chatterPrivateKey.private_key; } catch (error) { logger.log("chatter-get-private-key", "ERROR", "api", null, error); throw err; } }