diff --git a/apps/OpenSign/src/pages/Form.js b/apps/OpenSign/src/pages/Form.js index 3dfee1aa9..6af4107ac 100644 --- a/apps/OpenSign/src/pages/Form.js +++ b/apps/OpenSign/src/pages/Form.js @@ -11,8 +11,10 @@ import SignersInput from "../components/shared/fields/SignersInput"; import Title from "../components/Title"; import PageNotFound from "./PageNotFound"; import { SaveFileSize } from "../constant/saveFileSize"; -import { getFileName } from "../constant/Utils"; +import { getFileName, toDataUrl } from "../constant/Utils"; import { PDFDocument } from "pdf-lib"; +import axios from "axios"; +import { isEnableSubscription } from "../constant/const"; // `Form` render all type of Form on this basis of their provided in path function Form() { @@ -32,6 +34,7 @@ function Form() { const Forms = (props) => { const maxFileSize = 20; + const abortController = new AbortController(); const navigate = useNavigate(); const [signers, setSigners] = useState([]); const [folder, setFolder] = useState({ ObjectId: "", Name: "" }); @@ -54,6 +57,7 @@ const Forms = (props) => { }; useEffect(() => { handleReset(); + return () => abortController.abort(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.title]); @@ -86,16 +90,113 @@ const Forms = (props) => { e.target.value = ""; return; } else { - try { - const res = await getFileAsArrayBuffer(files[0]); - const pdfBytes = await PDFDocument.load(res); - console.log("pdfbytes ", pdfBytes); - handleFileUpload(files[0]); - } catch (err) { - alert(`Currently encrypted pdf files are not supported.`); - setFileUpload(""); - e.target.value = ""; - console.log("err ", err); + if (files?.[0]?.type === "application/pdf") { + try { + const res = await getFileAsArrayBuffer(files[0]); + await PDFDocument.load(res); + handleFileUpload(files[0]); + } catch (err) { + alert(`Currently encrypted pdf files are not supported.`); + setFileUpload(""); + e.target.value = ""; + console.log("err ", err); + try { + await Parse.Cloud.run("encryptedpdf", { + email: Parse.User.current().getEmail() + }); + } catch (err) { + console.log("err in sending posthog encryptedpdf", err); + } + } + } else { + if (isEnableSubscription) { + const isImage = files?.[0]?.type.includes("image/"); + if (isImage) { + const image = await toDataUrl(files[0]); + const pdfDoc = await PDFDocument.create(); + let embedImg; + if (files?.[0]?.type === "image/png") { + embedImg = await pdfDoc.embedPng(image); + } else { + embedImg = await pdfDoc.embedJpg(image); + } + + // Get image dimensions + const imageWidth = embedImg.width; + const imageHeight = embedImg.height; + const page = pdfDoc.addPage([imageWidth, imageHeight]); + page.drawImage(embedImg, { + x: 0, + y: 0, + width: imageWidth, + height: imageHeight + }); + const getFile = await pdfDoc.save({ + useObjectStreams: false + }); + setfileload(true); + const fileName = files[0].name; + const size = files[0].size; + const name = sanitizeFileName(fileName); + const pdfName = `${name?.split(".")[0]}.pdf`; + const parseFile = new Parse.File( + pdfName, + [...getFile], + "application/pdf" + ); + + try { + const response = await parseFile.save({ + progress: (progressValue, loaded, total, { type }) => { + if (type === "upload" && progressValue !== null) { + const percentCompleted = Math.round( + (loaded * 100) / total + ); + setpercentage(percentCompleted); + } + } + }); + // The response object will contain information about the uploaded file + // You can access the URL of the uploaded file using response.url() + setFileUpload(response.url()); + setfileload(false); + if (response.url()) { + const tenantId = localStorage.getItem("TenantId"); + SaveFileSize(size, response.url(), tenantId); + return response.url(); + } + } catch (error) { + e.target.value = ""; + setfileload(false); + setpercentage(0); + console.error("Error uploading file:", error); + } + } else { + try { + setfileload(true); + const url = "http://tools.opensignlabs.com/docxtopdf"; + let formData = new FormData(); + formData.append("file", files[0]); + const config = { + headers: { + "content-type": "multipart/form-data", + sessiontoken: Parse.User.current().getSessionToken() + }, + signal: abortController.signal + }; + const res = await axios.post(url, formData, config); + if (res.data) { + setFileUpload(res.data.url); + setfileload(false); + } + } catch (err) { + e.target.value = ""; + setfileload(false); + setpercentage(0); + console.log("err in libreconverter ", err); + } + } + } } } } else { @@ -353,7 +454,12 @@ const Forms = (props) => { type="file" className="bg-white px-2 py-1.5 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" onChange={(e) => handleFileInput(e)} - accept="application/pdf" + // accept="application/pdf" + accept={ + isEnableSubscription + ? "application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,image/png,image/jpeg" + : "application/pdf" + } required /> {process.env.REACT_APP_DROPBOX_API_KEY && ( diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js index fa6ebeb04..94977c454 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.js +++ b/apps/OpenSign/src/pages/PdfRequestFiles.js @@ -571,192 +571,200 @@ function PdfRequestFiles() { const pngUrl = checkUser[0].placeHolder; // Load a PDFDocument from the existing PDF bytes const existingPdfBytes = pdfArrayBuffer; - const pdfDoc = await PDFDocument.load(existingPdfBytes, { - ignoreEncryption: true - }); - const isSignYourSelfFlow = false; - const extUserPtr = pdfDetails[0].ExtUserPtr; - const HeaderDocId = extUserPtr?.HeaderDocId; - //embed document's object id to all pages in pdf document - if (!HeaderDocId) { - if (!isDocId) { - await embedDocId(pdfDoc, documentId, allPages); - } - } - //embed multi signature in pdf - const pdfBytes = await multiSignEmbed( - pngUrl, - pdfDoc, - pdfOriginalWidth, - isSignYourSelfFlow, - containerWH - ); - //get ExistUserPtr object id of user class to get tenantDetails - const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId; - //get ExistUserPtr email to get userDetails - const currentUserEmail = pdfDetails?.[0]?.ExtUserPtr?.Email; - const res = await contractUsers(currentUserEmail); - let activeMailAdapter = ""; - if (res === "Error: Something went wrong!") { - setHandleError("Error: Something went wrong!"); - setIsLoading({ - isLoad: false - }); - } else if (!res || res?.length === 0) { - activeMailAdapter = ""; - } else if (res[0] && res.length) { - activeMailAdapter = res[0]?.active_mail_adapter; - } - //function for call to embed signature in pdf and get digital signature pdf try { - const res = await signPdfFun( - pdfBytes, - documentId, - signerObjectId, - setIsAlert, - objectId, - isSubscribed, - activeMailAdapter - ); - if (res && res.status === "success") { - setPdfUrl(res.data); - setIsSigned(true); - setSignedSigners([]); - setUnSignedSigners([]); - getDocumentDetails(); - const index = pdfDetails?.[0].Signers.findIndex( - (x) => x.Email === jsonSender.email - ); - const newIndex = index + 1; - const user = pdfDetails?.[0].Signers[newIndex]; - if (user) { - setIsCompleted({ - isModal: true, - message: - "You have successfully signed the document. You can download or print a copy of the partially signed document. A copy of the digitally signed document will be sent to the owner over email once it is signed by all signers." - }); + const pdfDoc = await PDFDocument.load(existingPdfBytes); + + const isSignYourSelfFlow = false; + const extUserPtr = pdfDetails[0].ExtUserPtr; + const HeaderDocId = extUserPtr?.HeaderDocId; + //embed document's object id to all pages in pdf document + if (!HeaderDocId) { + if (!isDocId) { + await embedDocId(pdfDoc, documentId, allPages); } - if (sendInOrder) { - const requestBody = pdfDetails?.[0]?.RequestBody; - const requestSubject = pdfDetails?.[0]?.RequestSubject; + } + //embed multi signature in pdf + const pdfBytes = await multiSignEmbed( + pngUrl, + pdfDoc, + pdfOriginalWidth, + isSignYourSelfFlow, + containerWH + ); + //get ExistUserPtr object id of user class to get tenantDetails + const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId; + //get ExistUserPtr email to get userDetails + const currentUserEmail = pdfDetails?.[0]?.ExtUserPtr?.Email; + const res = await contractUsers(currentUserEmail); + let activeMailAdapter = ""; + if (res === "Error: Something went wrong!") { + setHandleError("Error: Something went wrong!"); + setIsLoading({ + isLoad: false + }); + } else if (!res || res?.length === 0) { + activeMailAdapter = ""; + } else if (res[0] && res.length) { + activeMailAdapter = res[0]?.active_mail_adapter; + } + //function for call to embed signature in pdf and get digital signature pdf + try { + const res = await signPdfFun( + pdfBytes, + documentId, + signerObjectId, + setIsAlert, + objectId, + isSubscribed, + activeMailAdapter + ); + if (res && res.status === "success") { + setPdfUrl(res.data); + setIsSigned(true); + setSignedSigners([]); + setUnSignedSigners([]); + getDocumentDetails(); + const index = pdfDetails?.[0].Signers.findIndex( + (x) => x.Email === jsonSender.email + ); + const newIndex = index + 1; + const user = pdfDetails?.[0].Signers[newIndex]; if (user) { - const expireDate = pdfDetails?.[0].ExpiryDate.iso; - const newDate = new Date(expireDate); - const localExpireDate = newDate.toLocaleDateString("en-US", { - day: "numeric", - month: "long", - year: "numeric" + setIsCompleted({ + isModal: true, + message: + "You have successfully signed the document. You can download or print a copy of the partially signed document. A copy of the digitally signed document will be sent to the owner over email once it is signed by all signers." }); - let senderEmail = pdfDetails?.[0].ExtUserPtr.Email; - let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone; - const senderName = `${pdfDetails?.[0].ExtUserPtr.Name}`; - - try { - const imgPng = - "https://qikinnovation.ams3.digitaloceanspaces.com/logo.png"; - let url = `${localStorage.getItem( - "baseUrl" - )}functions/sendmailv3/`; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": - localStorage.getItem("parseAppId"), - sessionToken: localStorage.getItem("accesstoken") - }; - const serverUrl = localStorage.getItem("baseUrl"); - const newServer = serverUrl.replaceAll("/", "%2F"); - const objectId = user.objectId; - const serverParams = `${newServer}&${localStorage.getItem( - "parseAppId" - )}&${localStorage.getItem("_appName")}`; - const hostUrl = window.location.origin; - let signPdf = `${hostUrl}/login/${pdfDetails?.[0].objectId}/${user.Email}/${objectId}/${serverParams}`; - const openSignUrl = "https://www.opensignlabs.com/contact-us"; - const orgName = pdfDetails[0]?.ExtUserPtr.Company - ? pdfDetails[0].ExtUserPtr.Company - : ""; - const themeBGcolor = themeColor; - let replaceVar; - if ( - requestBody && - requestSubject && - (!isEnableSubscription || isSubscribed) - ) { - const replacedRequestBody = requestBody.replace(/"/g, "'"); - const htmlReqBody = - "" + - replacedRequestBody + - " "; - - const variables = { - document_title: pdfDetails?.[0].Name, - sender_name: senderName, - sender_mail: senderEmail, - sender_phone: senderPhone, - receiver_name: user.Name, - receiver_email: user.Email, - receiver_phone: user.Phone, - expiry_date: localExpireDate, - company_name: orgName, - signing_url: `Sign here` - }; - replaceVar = replaceMailVaribles( - requestSubject, - htmlReqBody, - variables - ); - } - - let params = { - mailProvider: activeMailAdapter, - extUserId: extUserId, - recipient: user.Email, - subject: requestSubject - ? replaceVar?.subject - : `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`, - from: senderEmail, - html: requestBody - ? replaceVar?.body - : "

Digital Signature Request

" + - pdfDetails?.[0].ExtUserPtr.Name + - " has requested you to review and sign " + - pdfDetails?.[0].Name + - ".

Sender " + - senderEmail + - "
Organization " + - orgName + - "
Expires on " + - localExpireDate + - "

This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " + - senderEmail + - " directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ here.

" - }; - await axios.post(url, params, { - headers: headers + } + if (sendInOrder) { + const requestBody = pdfDetails?.[0]?.RequestBody; + const requestSubject = pdfDetails?.[0]?.RequestSubject; + if (user) { + const expireDate = pdfDetails?.[0].ExpiryDate.iso; + const newDate = new Date(expireDate); + const localExpireDate = newDate.toLocaleDateString("en-US", { + day: "numeric", + month: "long", + year: "numeric" }); - } catch (error) { - console.log("error", error); + let senderEmail = pdfDetails?.[0].ExtUserPtr.Email; + let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone; + const senderName = `${pdfDetails?.[0].ExtUserPtr.Name}`; + + try { + const imgPng = + "https://qikinnovation.ams3.digitaloceanspaces.com/logo.png"; + let url = `${localStorage.getItem( + "baseUrl" + )}functions/sendmailv3/`; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": + localStorage.getItem("parseAppId"), + sessionToken: localStorage.getItem("accesstoken") + }; + const serverUrl = localStorage.getItem("baseUrl"); + const newServer = serverUrl.replaceAll("/", "%2F"); + const objectId = user.objectId; + const serverParams = `${newServer}&${localStorage.getItem( + "parseAppId" + )}&${localStorage.getItem("_appName")}`; + const hostUrl = window.location.origin; + let signPdf = `${hostUrl}/login/${pdfDetails?.[0].objectId}/${user.Email}/${objectId}/${serverParams}`; + const openSignUrl = + "https://www.opensignlabs.com/contact-us"; + const orgName = pdfDetails[0]?.ExtUserPtr.Company + ? pdfDetails[0].ExtUserPtr.Company + : ""; + const themeBGcolor = themeColor; + let replaceVar; + if ( + requestBody && + requestSubject && + (!isEnableSubscription || isSubscribed) + ) { + const replacedRequestBody = requestBody.replace(/"/g, "'"); + const htmlReqBody = + "" + + replacedRequestBody + + " "; + + const variables = { + document_title: pdfDetails?.[0].Name, + sender_name: senderName, + sender_mail: senderEmail, + sender_phone: senderPhone, + receiver_name: user.Name, + receiver_email: user.Email, + receiver_phone: user.Phone, + expiry_date: localExpireDate, + company_name: orgName, + signing_url: `Sign here` + }; + replaceVar = replaceMailVaribles( + requestSubject, + htmlReqBody, + variables + ); + } + + let params = { + mailProvider: activeMailAdapter, + extUserId: extUserId, + recipient: user.Email, + subject: requestSubject + ? replaceVar?.subject + : `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`, + from: senderEmail, + html: requestBody + ? replaceVar?.body + : "

Digital Signature Request

" + + pdfDetails?.[0].ExtUserPtr.Name + + " has requested you to review and sign " + + pdfDetails?.[0].Name + + ".

Sender " + + senderEmail + + "
Organization " + + orgName + + "
Expires on " + + localExpireDate + + "

This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " + + senderEmail + + " directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ here.

" + }; + await axios.post(url, params, { + headers: headers + }); + } catch (error) { + console.log("error", error); + } } } + } else { + setIsAlert({ + isShow: true, + alertMessage: "something went wrong" + }); } - } else { + } catch (err) { setIsAlert({ isShow: true, alertMessage: "something went wrong" }); } } catch (err) { + setIsUiLoading(false); setIsAlert({ isShow: true, - alertMessage: "something went wrong" + alertMessage: `Currently encrypted pdf files are not supported.` }); } } diff --git a/apps/OpenSign/src/pages/SignyourselfPdf.js b/apps/OpenSign/src/pages/SignyourselfPdf.js index 13f785405..74772ce70 100644 --- a/apps/OpenSign/src/pages/SignyourselfPdf.js +++ b/apps/OpenSign/src/pages/SignyourselfPdf.js @@ -574,30 +574,38 @@ function SignYourSelf() { setIsUiLoading(true); const existingPdfBytes = pdfArrayBuffer; // Load a PDFDocument from the existing PDF bytes - const pdfDoc = await PDFDocument.load(existingPdfBytes, { - ignoreEncryption: true - }); - const isSignYourSelfFlow = true; - const extUserPtr = pdfDetails[0].ExtUserPtr; - const HeaderDocId = extUserPtr?.HeaderDocId; - //embed document's object id to all pages in pdf document - if (!HeaderDocId) { - await embedDocId(pdfDoc, documentId, allPages); + try { + const pdfDoc = await PDFDocument.load(existingPdfBytes, { + ignoreEncryption: true + }); + const isSignYourSelfFlow = true; + const extUserPtr = pdfDetails[0].ExtUserPtr; + const HeaderDocId = extUserPtr?.HeaderDocId; + //embed document's object id to all pages in pdf document + if (!HeaderDocId) { + await embedDocId(pdfDoc, documentId, allPages); + } + //embed multi signature in pdf + const pdfBytes = await multiSignEmbed( + xyPostion, + pdfDoc, + pdfOriginalWidth, + isSignYourSelfFlow, + containerWH + ); + // console.log("pdf", pdfBytes); + //function for call to embed signature in pdf and get digital signature pdf + await signPdfFun(pdfBytes, documentId); + } catch (err) { + setIsUiLoading(false); + setIsAlert({ + isShow: true, + alertMessage: `Currently encrypted pdf files are not supported.` + }); } - //embed multi signature in pdf - const pdfBytes = await multiSignEmbed( - xyPostion, - pdfDoc, - pdfOriginalWidth, - isSignYourSelfFlow, - containerWH - ); - // console.log("pdf", pdfBytes); - //function for call to embed signature in pdf and get digital signature pdf - await signPdfFun(pdfBytes, documentId); } } catch (err) { - console.log("err in embedselfsign ", err ); + console.log("err in embedselfsign ", err); setIsUiLoading(false); setIsAlert({ isShow: true, diff --git a/apps/OpenSign/src/pages/UserProfile.js b/apps/OpenSign/src/pages/UserProfile.js index b95d60312..69b491468 100644 --- a/apps/OpenSign/src/pages/UserProfile.js +++ b/apps/OpenSign/src/pages/UserProfile.js @@ -194,7 +194,7 @@ function UserProfile() { }; const handleSendOTP = async () => { try { - let url = `${parseBaseUrl}functions/SendOTPMailV1/`; + let url = `${parseBaseUrl}functions/SendOTPMailV1`; const headers = { "Content-Type": "application/json", "X-Parse-Application-Id": parseAppId @@ -214,6 +214,12 @@ function UserProfile() { otp: otp, email: Parse.User.current().getEmail() }); + if (resEmail?.message === "Email is verified.") { + setIsEmailVerified(true); + } else if (resEmail?.message === "Email is already verified.") { + setIsEmailVerified(true); + } + setOtp(""); alert(resEmail.message); setIsVerifyModal(false); } catch (error) { diff --git a/apps/OpenSignServer/cloud/main.js b/apps/OpenSignServer/cloud/main.js index 230ee17c3..bfdcf3fbb 100644 --- a/apps/OpenSignServer/cloud/main.js +++ b/apps/OpenSignServer/cloud/main.js @@ -34,6 +34,7 @@ import getPayments from './parsefunction/getPayments.js'; import getSubscriptions from './parsefunction/getSubscriptions.js'; import TenantAterFind from './parsefunction/TenantAfterFind.js'; import saveSubscription from './parsefunction/saveSubscription.js'; +import encryptedpdf from './parsefunction/encryptedPdf.js'; import VerifyEmail from './parsefunction/VerifyEmail.js'; Parse.Cloud.define('AddUserToRole', addUserToGroups); @@ -73,3 +74,4 @@ Parse.Cloud.afterFind('contracts_Signature', SignatureAfterFind); Parse.Cloud.afterFind('partners_Tenant', TenantAterFind); Parse.Cloud.define('savesubscription', saveSubscription); Parse.Cloud.define('verifyemail', VerifyEmail); +Parse.Cloud.define('encryptedpdf', encryptedpdf) diff --git a/apps/OpenSignServer/cloud/parsefunction/encryptedPdf.js b/apps/OpenSignServer/cloud/parsefunction/encryptedPdf.js new file mode 100644 index 000000000..7fb6c58cf --- /dev/null +++ b/apps/OpenSignServer/cloud/parsefunction/encryptedPdf.js @@ -0,0 +1,14 @@ +import { PostHog } from 'posthog-node'; +const ph_project_api_key = process.env.PH_PROJECT_API_KEY; +const client = new PostHog(ph_project_api_key); +export default async function encryptedpdf(request) { + const email = request.params.email; + if (client) { + client?.capture({ + distinctId: email, + event: 'encrypted_pdf_error', + properties: { response_code: 200 }, + }); + } + return { message: 'success' }; +} diff --git a/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js b/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js index a84ceb9a4..fec7ab4ef 100644 --- a/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js +++ b/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js @@ -319,7 +319,7 @@ async function PDF(o) { } } } catch (e) { - throw (console.log('Err ', e), e); + throw (console.log('Err in signpdf', e), e); } } export default PDF;