This commit is contained in:
Dave Richer
2023-11-20 14:46:11 -05:00
parent c0d756fa38
commit 54af163ddf
7 changed files with 7475 additions and 5718 deletions

7191
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -17,24 +17,24 @@
"start": "node server.js" "start": "node server.js"
}, },
"dependencies": { "dependencies": {
"@aws-sdk/client-secrets-manager": "^3.388.0", "@aws-sdk/client-secrets-manager": "^3.454.0",
"@aws-sdk/credential-provider-node": "^3.319.0", "@aws-sdk/client-ses": "^3.454.0",
"@opensearch-project/opensearch": "^2.2.1", "@aws-sdk/credential-provider-node": "^3.451.0",
"aws-sdk": "^2.1326.0", "@opensearch-project/opensearch": "^2.4.0",
"aws4": "^1.12.0", "aws4": "^1.12.0",
"axios": "^0.27.2", "axios": "^0.27.2",
"bluebird": "^3.7.2", "bluebird": "^3.7.2",
"body-parser": "^1.20.2", "body-parser": "^1.20.2",
"cloudinary": "^1.34.0", "cloudinary": "^1.41.0",
"compression": "^1.7.4", "compression": "^1.7.4",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"cors": "2.8.5", "cors": "2.8.5",
"csrf": "^3.1.0", "csrf": "^3.1.0",
"dinero.js": "^1.9.1", "dinero.js": "^1.9.1",
"dotenv": "16.0.3", "dotenv": "^16.3.1",
"express": "^4.18.2", "express": "^4.18.2",
"firebase-admin": "^11.5.0", "firebase-admin": "^11.11.0",
"graphql": "^16.6.0", "graphql": "^16.8.1",
"graphql-request": "^4.2.0", "graphql-request": "^4.2.0",
"graylog2": "^0.2.1", "graylog2": "^0.2.1",
"inline-css": "^4.0.2", "inline-css": "^4.0.2",
@@ -44,20 +44,20 @@
"moment": "^2.29.4", "moment": "^2.29.4",
"moment-timezone": "^0.5.41", "moment-timezone": "^0.5.41",
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"node-mailjet": "^6.0.2", "node-mailjet": "^6.0.4",
"node-persist": "^3.1.3", "node-persist": "^3.1.3",
"node-quickbooks": "^2.0.41", "node-quickbooks": "^2.0.43",
"nodemailer": "^6.9.1", "nodemailer": "^6.9.7",
"phone": "^3.1.35", "phone": "^3.1.41",
"query-string": "^7.1.1", "query-string": "^7.1.1",
"soap": "^1.0.0", "soap": "^1.0.0",
"socket.io": "^4.6.1", "socket.io": "^4.7.2",
"ssh2-sftp-client": "^9.0.4", "ssh2-sftp-client": "^9.1.0",
"stripe": "^9.15.0", "stripe": "^9.15.0",
"twilio": "^4.8.0", "twilio": "^4.19.0",
"uuid": "^9.0.0", "uuid": "^9.0.1",
"xml2js": "^0.4.23", "xml2js": "^0.6.2",
"xmlbuilder2": "^3.0.2" "xmlbuilder2": "^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"concurrently": "^7.3.0", "concurrently": "^7.3.0",

View File

@@ -5,8 +5,8 @@ const path = require("path");
const compression = require("compression"); const compression = require("compression");
const twilio = require("twilio"); const twilio = require("twilio");
const logger = require("./server/utils/logger"); const logger = require("./server/utils/logger");
var fb = require("./server/firebase/firebase-handler"); const fb = require("./server/firebase/firebase-handler");
var cookieParser = require("cookie-parser"); const cookieParser = require("cookie-parser");
const multer = require("multer"); const multer = require("multer");
const upload = multer(); const upload = multer();
//var enforce = require("express-sslify"); //var enforce = require("express-sslify");

View File

@@ -7,15 +7,19 @@ require("dotenv").config({
}); });
const axios = require("axios"); const axios = require("axios");
let nodemailer = require("nodemailer"); let nodemailer = require("nodemailer");
let aws = require("aws-sdk"); let aws = require("@aws-sdk/client-ses");
let { defaultProvider } = require("@aws-sdk/credential-provider-node");
const logger = require("../utils/logger"); const logger = require("../utils/logger");
const client = require("../graphql-client/graphql-client").client; const client = require("../graphql-client/graphql-client").client;
const queries = require("../graphql-client/queries"); const queries = require("../graphql-client/queries");
const ses = new aws.SES({ const ses = new aws.SES({
// The key apiVersion is no longer supported in v3, and can be removed.
// @deprecated The client uses the "latest" apiVersion.
apiVersion: "latest", apiVersion: "latest",
region: "ca-central-1", region: "ca-central-1",
defaultProvider
}); });
let transporter = nodemailer.createTransport({ let transporter = nodemailer.createTransport({
@@ -48,7 +52,6 @@ exports.sendServerEmail = async function ({ subject, text }) {
} catch (error) { } catch (error) {
console.log(error); console.log(error);
logger.log("server-email-failure", "error", null, null, error); logger.log("server-email-failure", "error", null, null, error);
res.status(500).json(error);
} }
}; };
exports.sendTaskEmail = async function ({ to, subject, text, attachments }) { exports.sendTaskEmail = async function ({ to, subject, text, attachments }) {

View File

@@ -1,6 +1,6 @@
"use strict"; "use strict";
const AWS = require("aws-sdk"); const awsSecretManager = require("@aws-sdk/client-secrets-manager");
class SecretsManager { class SecretsManager {
/** /**
@@ -8,11 +8,10 @@ class SecretsManager {
*/ */
static async getSecret(secretName, region) { static async getSecret(secretName, region) {
const config = { region: region }; const config = { region: region };
let secretsManager = new AWS.SecretsManager(config); let secretsManager = new awsSecretManager.SecretsManager(config);
try { try {
let secretValue = await secretsManager let secretValue = await secretsManager
.getSecretValue({ SecretId: secretName }) .getSecretValue({ SecretId: secretName });
.promise();
if ("SecretString" in secretValue) { if ("SecretString" in secretValue) {
return secretValue.SecretString; return secretValue.SecretString;
} else { } else {

View File

@@ -1,122 +1,122 @@
const Dinero = require("dinero.js");
const queries = require("../graphql-client/queries"); const queries = require("../graphql-client/queries");
//const client = require("../graphql-client/graphql-client").client; const {pick} = require("lodash");
const _ = require("lodash");
const GraphQLClient = require("graphql-request").GraphQLClient; const GraphQLClient = require("graphql-request").GraphQLClient;
const logger = require("../utils/logger"); const logger = require("../utils/logger");
//const client = require("../graphql-client/graphql-client").client;
const path = require("path"); const path = require("path");
const client = require("../graphql-client/graphql-client").client; const client = require("../graphql-client/graphql-client").client;
require("dotenv").config({ require("dotenv").config({
path: path.resolve( path: path.resolve(
process.cwd(), process.cwd(),
`.env.${process.env.NODE_ENV || "development"}` `.env.${process.env.NODE_ENV || "development"}`
), ),
}); });
const { Client, Connection } = require("@opensearch-project/opensearch"); const {Client, Connection} = require("@opensearch-project/opensearch");
const { defaultProvider } = require("@aws-sdk/credential-provider-node"); const {defaultProvider} = require("@aws-sdk/credential-provider-node");
const aws4 = require("aws4"); const aws4 = require("aws4");
const { gql } = require("graphql-request"); const {gql} = require("graphql-request");
var host = process.env.OPEN_SEARCH_HOST; var host = process.env.OPEN_SEARCH_HOST;
const createAwsConnector = (credentials, region) => { const createAwsConnector = (credentials, region) => {
class AmazonConnection extends Connection { class AmazonConnection extends Connection {
buildRequestObject(params) { buildRequestObject(params) {
const request = super.buildRequestObject(params); const request = super.buildRequestObject(params);
request.service = "es"; request.service = "es";
request.region = region; request.region = region;
request.headers = request.headers || {}; request.headers = request.headers || {};
request.headers["host"] = request.hostname; request.headers["host"] = request.hostname;
return aws4.sign(request, credentials); return aws4.sign(request, credentials);
}
} }
}
return { return {
Connection: AmazonConnection, Connection: AmazonConnection,
}; };
}; };
const getClient = async () => { const getClient = async () => {
const credentials = await defaultProvider()(); const credentials = await defaultProvider()();
return new Client({ return new Client({
...createAwsConnector(credentials, "ca-central-1"), ...createAwsConnector(credentials, "ca-central-1"),
node: host, node: host,
}); });
}; };
async function OpenSearchUpdateHandler(req, res) { async function OpenSearchUpdateHandler(req, res) {
if (req.headers["event-secret"] !== process.env.EVENT_SECRET) { if (req.headers["event-secret"] !== process.env.EVENT_SECRET) {
res.status(401).send("Unauthorized"); res.status(401).send("Unauthorized");
return; return;
} }
try { try {
var osClient = await getClient(); var osClient = await getClient();
// const osClient = new Client({ // const osClient = new Client({
// node: `https://imex:<password>@search-imexonline-search-ixp2stfvwp6qocjsowzjzyreoy.ca-central-1.es.amazonaws.com/`, // node: `https://imex:<password>@search-imexonline-search-ixp2stfvwp6qocjsowzjzyreoy.ca-central-1.es.amazonaws.com/`,
// }); // });
if (req.body.event.op === "DELETE") { if (req.body.event.op === "DELETE") {
let response; let response;
response = await osClient.delete({ response = await osClient.delete({
id: req.body.event.data.old.id, id: req.body.event.data.old.id,
index: req.body.table.name, index: req.body.table.name,
}); });
res.status(200).json(response.body); res.status(200).json(response.body);
} else { } else {
let document; let document;
switch (req.body.table.name) { switch (req.body.table.name) {
case "jobs": case "jobs":
document = _.pick(req.body.event.data.new, [ document = pick(req.body.event.data.new, [
"id", "id",
"bodyshopid", "bodyshopid",
"clm_no", "clm_no",
"clm_total", "clm_total",
"comment", "comment",
"ins_co_nm", "ins_co_nm",
"owner_owing", "owner_owing",
"ownr_co_nm", "ownr_co_nm",
"ownr_fn", "ownr_fn",
"ownr_ln", "ownr_ln",
"ownr_ph1", "ownr_ph1",
"ownr_ph2", "ownr_ph2",
"plate_no", "plate_no",
"ro_number", "ro_number",
"status", "status",
"v_model_yr", "v_model_yr",
"v_make_desc", "v_make_desc",
"v_model_desc", "v_model_desc",
"v_vin", "v_vin",
]); ]);
document.bodyshopid = req.body.event.data.new.shopid; document.bodyshopid = req.body.event.data.new.shopid;
break; break;
case "vehicles": case "vehicles":
document = _.pick(req.body.event.data.new, [ document = pick(req.body.event.data.new, [
"id", "id",
"v_model_yr", "v_model_yr",
"v_model_desc", "v_model_desc",
"v_make_desc", "v_make_desc",
"v_color", "v_color",
"v_vin", "v_vin",
"plate_no", "plate_no",
]); ]);
document.bodyshopid = req.body.event.data.new.shopid; document.bodyshopid = req.body.event.data.new.shopid;
break; break;
case "owners": case "owners":
document = _.pick(req.body.event.data.new, [ document = pick(req.body.event.data.new, [
"id", "id",
"ownr_fn", "ownr_fn",
"ownr_ln", "ownr_ln",
"ownr_co_nm", "ownr_co_nm",
"ownr_ph1", "ownr_ph1",
"ownr_ph2", "ownr_ph2",
]); ]);
document.bodyshopid = req.body.event.data.new.shopid; document.bodyshopid = req.body.event.data.new.shopid;
break; break;
case "bills": case "bills":
const bill = await client.request( const bill = await client.request(
`query ADMIN_GET_BILL_BY_ID($billId: uuid!) { `query ADMIN_GET_BILL_BY_ID($billId: uuid!) {
bills_by_pk(id: $billId) { bills_by_pk(id: $billId) {
id id
job { job {
@@ -131,26 +131,26 @@ async function OpenSearchUpdateHandler(req, res) {
} }
} }
`, `,
{ billId: req.body.event.data.new.id } {billId: req.body.event.data.new.id}
); );
document = { document = {
..._.pick(req.body.event.data.new, [ ...pick(req.body.event.data.new, [
"id", "id",
"date", "date",
"exported", "exported",
"exported_at", "exported_at",
"invoice_number", "invoice_number",
"is_credit_memo", "is_credit_memo",
"total", "total",
]), ]),
...bill.bills_by_pk, ...bill.bills_by_pk,
bodyshopid: bill.bills_by_pk.job.shopid, bodyshopid: bill.bills_by_pk.job.shopid,
}; };
break; break;
case "payments": case "payments":
//Query to get the job and RO number //Query to get the job and RO number
const payment = await client.request( const payment = await client.request(
`query ADMIN_GET_PAYMENT_BY_ID($paymentId: uuid!) { `query ADMIN_GET_PAYMENT_BY_ID($paymentId: uuid!) {
payments_by_pk(id: $paymentId) { payments_by_pk(id: $paymentId) {
id id
job { job {
@@ -171,155 +171,155 @@ async function OpenSearchUpdateHandler(req, res) {
} }
} }
`, `,
{ paymentId: req.body.event.data.new.id } {paymentId: req.body.event.data.new.id}
); );
document = { document = {
..._.pick(req.body.event.data.new, [ ...pick(req.body.event.data.new, [
"id", "id",
"amount", "amount",
"created_at", "created_at",
"date", "date",
"exportedat", "exportedat",
"memo", "memo",
"payer", "payer",
"paymentnum", "paymentnum",
"transactionid", "transactionid",
"type", "type",
]), ]),
...payment.payments_by_pk, ...payment.payments_by_pk,
bodyshopid: payment.payments_by_pk.job.shopid, bodyshopid: payment.payments_by_pk.job.shopid,
}; };
break; break;
} }
const payload = { const payload = {
id: req.body.event.data.new.id, id: req.body.event.data.new.id,
index: req.body.table.name, index: req.body.table.name,
body: document, body: document,
}; };
let response; let response;
response = await osClient.index(payload); response = await osClient.index(payload);
console.log(response.body); console.log(response.body);
res.status(200).json(response.body); res.status(200).json(response.body);
}
} catch (error) {
res.status(400).json(JSON.stringify(error));
} finally {
} }
} catch (error) {
res.status(400).json(JSON.stringify(error));
} finally {
}
} }
async function OpenSearchSearchHandler(req, res) { async function OpenSearchSearchHandler(req, res) {
try { try {
const { search, bodyshopid, index } = req.body; const {search, bodyshopid, index} = req.body;
if (!req.user) { if (!req.user) {
res.sendStatus(401); res.sendStatus(401);
return; return;
} }
logger.log("os-search", "DEBUG", req.user.email, null, { logger.log("os-search", "DEBUG", req.user.email, null, {
search, search,
}); });
const BearerToken = req.headers.authorization; const BearerToken = req.headers.authorization;
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, { const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
headers: { headers: {
Authorization: BearerToken, Authorization: BearerToken,
},
});
const assocs = await client
.setHeaders({ Authorization: BearerToken })
.request(queries.ACTIVE_SHOP_BY_USER, {
user: req.user.email,
});
if (assocs.length === 0) {
res.sendStatus(401);
}
var osClient = await getClient();
const { body } = await osClient.search({
...(index ? { index } : {}),
body: {
size: 100,
query: {
bool: {
must: [
{
match: {
bodyshopid: assocs.associations[0].shopid,
},
},
{
bool: {
should: [
{
multi_match: {
query: search,
type: "cross_fields",
fields: ["*ownr_fn", "*ownr_ln"],
},
},
{
multi_match: {
query: search,
type: "most_fields",
fields: [
"*v_model_yr",
"*v_make_desc^2",
"*v_model_desc^3",
],
},
},
{
query_string: {
query: `*${search}*`,
// Weighted Fields
fields: [
"*ro_number^20",
"*clm_no^14",
"*v_vin^12",
"*plate_no^12",
"*ownr_ln^10",
"transactionid^10",
"paymentnum^10",
"invoice_number^10",
"*ownr_fn^8",
"*ownr_co_nm^8",
"*ownr_ph1^8",
"*ownr_ph2^8",
"*",
],
},
},
],
minimum_should_match: 1,
},
},
],
},
},
sort: [
{
_score: {
order: "desc",
}, },
}, });
],
},
});
res.json(body); const assocs = await client
} catch (error) { .setHeaders({Authorization: BearerToken})
console.log(error); .request(queries.ACTIVE_SHOP_BY_USER, {
logger.log("os-search-error", "ERROR", req.user.email, null, { user: req.user.email,
error: JSON.stringify(error), });
});
res.status(400).json(error); if (assocs.length === 0) {
} finally { res.sendStatus(401);
} }
const osClient = await getClient();
const {body} = await osClient.search({
...(index ? {index} : {}),
body: {
size: 100,
query: {
bool: {
must: [
{
match: {
bodyshopid: assocs.associations[0].shopid,
},
},
{
bool: {
should: [
{
multi_match: {
query: search,
type: "cross_fields",
fields: ["*ownr_fn", "*ownr_ln"],
},
},
{
multi_match: {
query: search,
type: "most_fields",
fields: [
"*v_model_yr",
"*v_make_desc^2",
"*v_model_desc^3",
],
},
},
{
query_string: {
query: `*${search}*`,
// Weighted Fields
fields: [
"*ro_number^20",
"*clm_no^14",
"*v_vin^12",
"*plate_no^12",
"*ownr_ln^10",
"transactionid^10",
"paymentnum^10",
"invoice_number^10",
"*ownr_fn^8",
"*ownr_co_nm^8",
"*ownr_ph1^8",
"*ownr_ph2^8",
"*",
],
},
},
],
minimum_should_match: 1,
},
},
],
},
},
sort: [
{
_score: {
order: "desc",
},
},
],
},
});
res.json(body);
} catch (error) {
console.log(error);
logger.log("os-search-error", "ERROR", req.user.email, null, {
error: JSON.stringify(error),
});
res.status(400).json(error);
} finally {
}
} }
exports.handler = OpenSearchUpdateHandler; exports.handler = OpenSearchUpdateHandler;

5436
yarn.lock

File diff suppressed because it is too large Load Diff