const express = require("express"); const app = express(); const fs = require("fs"); const tesseReader = require("./tesseReaderService/tesseReader.js"); const cors = require("cors"); const multer = require("multer"); const logger = require("./logger/logger.js"); const modelController = require("./agent/ModelController.js"); const tesseController = require("./tesseReaderService/tesseController.js"); const stripeController = require("./paymentService/stripeController.js"); const { db } = require("./firebase/firebase.js"); const trialUsers = require("./Constants/trialSignupData.js"); const crypto = require("crypto"); const { storeEditedCompletions, storeDataForGenServices, } = require("./storageService/storeEditedCompletion.js"); const { deleteDocument, deleteFolderAndContents, cleanupGenFolderAndContents, } = require("./storageService/deleteDirOrDoc.js"); const { handlePaymentFailure, handleSubscriptionDeletion, } = require("./paymentService/stripe.js"); const { collection, query, where, getDocs } = require("firebase/firestore"); const generatePassword = ( length = 20, characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$" ) => Array.from(crypto.randomFillSync(new Uint32Array(length))) .map((x) => characters[x % characters.length]) .join(""); //*** STRIPE ***/ const Stripe = require("stripe"); const { stripeAPIKey, stripeWebhooksKey } = require("./firebase/secrets.js"); const stripe = Stripe(stripeAPIKey); // Secret for Stripe webhooks const endpointSecret = stripeWebhooksKey; //** NODE HTTP-PROXY ***/ const httpProxy = require("http-proxy"); const targetUrl = "http://127.0.0.1:8081"; const proxy = httpProxy.createProxy({ changeOrigin: true, target: targetUrl, }); //** NODE HTTP-PROXY ***/ const httpProxy2 = require("http-proxy"); const targetAdd = "http://127.0.0.1:8087"; const proxyTwo = httpProxy.createProxy({ changeOrigin: true, target: targetAdd, }); //*** MULTER ***/ const storage = multer.diskStorage({ destination: "./Documents/Uploads", filename: function (req, file, callback) { callback(null, file.originalname); }, }); const altStorage = multer.diskStorage({ destination: "./Documents/Complaints", filename: function (req, file, callback) { callback(null, file.originalname); }, }); const upload = multer({ storage: storage }); const uploadComp = multer({ storage: altStorage }); //POST NEW COMPLAINT DOC -> py docConvert pdf-png app.post( "/v1/parse-new-compdoc", uploadComp.single("file"), function (req, res) { const id = req.file.originalname.split(".")[0]; const isComplaint = true; const clientPosition = "plaintiff"; try { req.url = req.url.replace( "/v1/parse-new-compdoc", `/parse-new-complaint/${id}` ); proxy.web(req, res, { function(err) { console.log("Proxy error:", err); }, }); } catch (err) { logger.error({ level: "error", message: "err", err }); console.log("Error at /v1/gen-disc-request", err); res.send(err); } res.sendStatus(200); } ); /* * POST new discv request => docConvert - for pdf to png */ app.post("/v1/parse-new-req-doc", upload.single("file"), function (req, res) { const id = req.file.originalname.split(".")[0]; try { req.url = req.url.replace( "/v1/parse-new-req-doc", `/parse-new-disc-req/${id}` ); proxy.web(req, res, { function(err) { console.log("Proxy error:", err); }, }); } catch (err) { logger.error({ level: "error", message: "err", err }); console.log("Error at /v1/gen-disc-request", err); res.send(err); } res.sendStatus(200); }); //Make outgoing requests from complaint app.post( "/v1/generate-outgoing-disc-req/:docId/:clientPosition", async (req, res) => { const { docId, clientPosition } = req.params; const isComplaint = true; try { const res = await tesseController.executeReadWriteActions( docId, isComplaint, clientPosition ); //return res; } catch (err) { console.log("err in make-outgoing-requests", err); } res.sendStatus(200); } ); //make resp to incoming requests from req doc app.post( "/v1/generate-disc-responses/:docId/:clientPosition", async (req, res) => { const { docId, clientPosition } = req.params; const isComplaint = false; try { const res = await tesseController.executeReadWriteActions( docId, isComplaint, clientPosition ); return res; } catch (err) { console.log("err in make-outgoing-requests", err); } res.sendStatus(200); } ); /* * POST to Generate Docx */ app.post("/v1/generate-request-docx/:docId", async function (req, res) { const { docId } = req.params; const data = req.body; try { req.url = req.url.replace("/v1/generate-request-docx", `/gen-req-docx`); proxyTwo.web(req, res, { function(err) { console.log("Proxy error:", err); }, }); } catch (err) { console.log("generate-request-docx error", err); } }); const rootDir = process.env.NODE_ENV === "development" ? "/Users/kjannette/workspace/ax3" : "/var/www"; //*** EXPRESS ***/ const port = 3001; var corsOptions = { AccessControlAllowOrigin: "*", origin: "*", methods: "GET,HEAD,PUT,PATCH,POST,DELETE", optionsSuccessStatus: 200, }; app.use(cors(corsOptions)); app.use(express.urlencoded({ extended: false })); app.use(express.json()); /* * Client POST create stripe subscription, make payment */ app.post("/create-subscription", async (req, res) => { const { planType, additionalAccounts, isAnnual, customerData, token } = req.body; try { const sub = await stripeController.createNewSubscription( planType, additionalAccounts, isAnnual, customerData, token ); const subscriptionCreated = sub.subscription.created; const subscriptionPeriodStart = sub.subscription.current_period_start; const subscriptionPeriodEnd = sub.subscription.current_period_end; const subscriptionId = sub.subscription.id; const customerId = sub.customer.customerId; res.send({ subscriptionCreated, subscriptionPeriodStart, subscriptionPeriodEnd, subscriptionId, customerId, }); } catch (error) { console.log("Error in create-subscription", error); res.status(400).send({ error: { message: error.message } }); } }); /* * Client POST create stripe subscription, make payment */ console.log("process.env.NODE_ENV", process.env.NODE_ENV); app.post("/new-payment-intent", async (req, res) => { const { planType, additionalAccounts, isAnnual, customerData, token } = req.body; const userAgent = req.headers["user-agent"]; try { const payIntent = await stripeController.createNewPaymentIntent( customerData, token, userAgent ); res.send({ payIntent, }); } catch (error) { console.log(error); res.status(400).send({ error: { message: error.message } }); } }); /* * Client POST for cancelling a subscription */ app.post("/cancel-subscription", async (req, res) => { const { appUserId } = req.body; try { const usersRef = collection(db, "users"); const q = query(usersRef, where("appUserId", "==", appUserId)); const querySnapshot = await getDocs(q); if (querySnapshot.empty) { console.log("No user found with the email:", appUserId); return; } const userDoc = querySnapshot.docs[0]; //get the user's subscription ID and customer ID const subscriptionId = userDoc.data().subscriptionId; const deletedSubscription = await stripe.subscriptions.update( subscriptionId, { cancel_at_period_end: true, } ); res.status(200).send(); } catch (error) { console.log(error); res.status(500).send({ error: { message: error.message } }); } }); /* * Client POST - Stripe webhook(s) */ app.post( "/stripe-webhook", express.raw({ type: "application/json" }), async (request, response) => { const { type } = request.body.type; switch (request.body.type) { case "customer.subscription.deleted": const subscription = request.body.data.object; //get stripe customer const stripeCustomer = await stripe.customers.retrieve( subscription.customer ); await handleSubscriptionDeletion(stripeCustomer, subscription, stripe); break; x; case "invoice.payment_failed": const paymentIntent = request.body.data.object; await handlePaymentFailure(paymentIntent); break; default: console.log(`Unhandled event type`); } response.status(200).send(); } ); /* * Generate responses to irregular types * combined-numbered */ app.get( "/v1/generate-disc-responses-irreg/:docId/:docType/:isRequests", async (req, res) => { const { docId, docType } = req.params; const isRequests = false; try { const data = await modelController.arrayGenAnswers( docId, docType, isRequests ); res.send(data); } catch (error) { console.log(error); } } ); /* * * GET .docx discovery response * */ app.get("/v1/get-docx/:docId/:reqType", (req, res) => { const { docId } = req.params; res.sendFile(`${docId}.docx`, { root: `${rootDir}/ax3Services/Docxfinal/`, }); }); /* * Cleanup docx working files (temp workaround) */ app.get("/cleanUpDocx/:docId/:reqType", (req, res) => { const { docId, reqType } = req.params; try { cleanupGenFolderAndContents(docId, reqType); res.end("doc cleanup complete"); } catch (err) { console.log(err); } }); /* * POST store user-edited completions */ app.post("/v1/store-edited-completions", function (req, res) { const data = req.body; try { storeEditedCompletions(data); } catch (err) { console.log("Error at /v1/store-edited-completions:", err); } res.end(); }); /* * POST store docx data for gen service */ app.post("/v1/store-docx-data/:docId", function (req, res) { const { docId } = req.params; const data = req.body; console.log("data", data); try { storeDataForGenServices(docId, data); } catch (err) { console.log("Error at /v1/store-edited-completions:", err); } res.end(); }); /* * * Client GET parsed requests array */ app.get("/v1/get-parsed-requests/:docId/:docType", (req, res) => { const { docId, docType } = req.params; try { res.sendFile(`${docId}-jbk-parsedRequests.json`, { root: `${rootDir}/ax3Services/Documents/Requests/${docType}/${docId}/`, }); } catch (err) { console.log("err", err); } }); /* * * Client GET focus user data */ app.get("/v1/get-focused-data/:code", (req, res) => { const { code } = req.params; try { const match = trialUsers.trialUsers.filter( (user) => user.signupCode === code ); if (match.length > 0) { const mspall = generatePassword(); match[0]["mspall"] = mspall; res.send(match); } } catch (err) { console.log("err", err); } }); /* * Client GET completions - (responses to) incoming requests */ app.get("/v1/get-completions/:docId/:docType", (req, res) => { const { docId, docType } = req.params; try { res.sendFile(`${docId}-jbk-responses.json`, { root: `./Documents/Responses/${docType}/${docId}/`, }); } catch (err) { console.log("err", err); } }); /* * Client GET completions - requests outgoing */ app.get("/v1/get-outgoing-requests/:docId/:docType", (req, res) => { const { docId, docType } = req.params; try { res.sendFile(`${docId}-jbk-requests-out.json`, { root: `./Documents/RequestsOut/${docId}/`, }); } catch (err) { console.log("err", err); } }); /* * Client POST to delete a request or response document */ app.post("/deleteDoc/:docId/:docType/:respGens", (req, res) => { const { docId, docType, respGens } = req.params; try { deleteFolderAndContents(docId, docType, respGens); } catch (err) { console.log("err", err); } }); console.log("app running on port", port); console.log("rootDir", rootDir); app.listen(port);