From 5a68e18c48524e856c87d03c6d3b049ee16f8c69 Mon Sep 17 00:00:00 2001 From: prafull-opensignlabs Date: Mon, 6 May 2024 18:46:12 +0530 Subject: [PATCH] fix: pdf url are not downloadable after some time --- apps/OpenSign/src/components/pdf/PdfHeader.js | 249 +++++++++--------- .../src/primitives/GetReportDisplay.js | 29 +- apps/OpenSignServer/cloud/main.js | 4 +- .../cloud/parsefunction/getSignedUrl.js | 23 ++ 4 files changed, 165 insertions(+), 140 deletions(-) diff --git a/apps/OpenSign/src/components/pdf/PdfHeader.js b/apps/OpenSign/src/components/pdf/PdfHeader.js index 896072f8e..eeac61ee3 100644 --- a/apps/OpenSign/src/components/pdf/PdfHeader.js +++ b/apps/OpenSign/src/components/pdf/PdfHeader.js @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState } from "react"; import PrevNext from "./PrevNext"; import printModule from "print-js"; import { getBase64FromUrl } from "../../constant/Utils"; @@ -7,8 +7,9 @@ import "../../styles/signature.css"; import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; import { useNavigate } from "react-router-dom"; import { themeColor } from "../../constant/const"; -import Certificate from "./Certificate"; -import { PDFDownloadLink } from "@react-pdf/renderer"; +import axios from "axios"; +import ModalUi from "../../primitives/ModalUi"; +import Parse from "parse"; function Header({ isPdfRequestFiles, @@ -39,6 +40,7 @@ function Header({ signerPos && signerPos?.filter((data) => data.Role !== "prefill"); const isMobile = window.innerWidth < 767; const navigate = useNavigate(); + const [isCertificate, setIsCertificate] = useState(false); const isGuestSigner = localStorage.getItem("isGuestSigner"); //for go to previous page function previousPage() { @@ -61,30 +63,43 @@ function Header({ const handleToPrint = async (event) => { event.preventDefault(); - const pdf = await getBase64FromUrl(pdfUrl); - const isAndroidDevice = navigator.userAgent.match(/Android/i); - const isAppleDevice = - (/iPad|iPhone|iPod/.test(navigator.platform) || - (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)) && - !window.MSStream; - if (isAndroidDevice || isAppleDevice) { - const byteArray = Uint8Array.from( - atob(pdf) - .split("") - .map((char) => char.charCodeAt(0)) - ); - const blob = new Blob([byteArray], { type: "application/pdf" }); - const blobUrl = URL.createObjectURL(blob); - window.open(blobUrl, "_blank"); - } else { - printModule({ printable: pdf, type: "pdf", base64: true }); + try { + const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl }); + const pdf = await getBase64FromUrl(url); + const isAndroidDevice = navigator.userAgent.match(/Android/i); + const isAppleDevice = + (/iPad|iPhone|iPod/.test(navigator.platform) || + (navigator.platform === "MacIntel" && + navigator.maxTouchPoints > 1)) && + !window.MSStream; + if (isAndroidDevice || isAppleDevice) { + const byteArray = Uint8Array.from( + atob(pdf) + .split("") + .map((char) => char.charCodeAt(0)) + ); + const blob = new Blob([byteArray], { type: "application/pdf" }); + const blobUrl = URL.createObjectURL(blob); + window.open(blobUrl, "_blank"); + } else { + printModule({ printable: pdf, type: "pdf", base64: true }); + } + } catch (err) { + console.log("err in getsignedurl", err); + alert("something went wrong, please try again later."); } }; //handle download signed pdf - const handleDownloadPdf = () => { + const handleDownloadPdf = async () => { const pdfName = pdfDetails[0] && pdfDetails[0].Name; - saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`); + try { + const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl }); + saveAs(url, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`); + } catch (err) { + console.log("err in getsignedurl", err); + alert("something went wrong, please try again later."); + } }; const sanitizeFileName = (pdfName) => { @@ -102,55 +117,41 @@ function Header({ } catch (err) { console.log("err in download in certificate", err); } + } else { + setIsCertificate(true); + try { + const data = { + docId: pdfDetails[0]?.objectId + }; + const docDetails = await axios.post( + `${localStorage.getItem("baseUrl")}functions/getDocument`, + data, + { + headers: { + "Content-Type": "application/json", + "X-Parse-Application-Id": localStorage.getItem("parseAppId"), + sessionToken: localStorage.getItem("accesstoken") + } + } + ); + if (docDetails.data && docDetails.data.result) { + const doc = docDetails.data.result; + if (doc?.CertificateUrl) { + await fetch(doc?.CertificateUrl); + const certificateUrl = doc?.CertificateUrl; + saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`); + setIsCertificate(false); + } else { + setIsCertificate(true); + } + } + } catch (err) { + console.log("err in download in certificate", err); + alert("something went wrong, please try again later."); + } } }; - const GenerateCertificate = () => { - //after generate download certifcate pdf - const handleDownload = (pdfBlob, fileName) => { - if (pdfBlob) { - const url = window.URL.createObjectURL(pdfBlob); - // Create a temporary anchor element - const link = document.createElement("a"); - link.href = url; - link.download = fileName; - // Append the anchor to the body - document.body.appendChild(link); - // Programmatically click the anchor to trigger the download - link.click(); - // Remove the anchor from the body - document.body.removeChild(link); - // Release the object URL to free up resources - window.URL.revokeObjectURL(url); - } - }; - - return ( - e.preventDefault()} - style={{ textDecoration: "none", zIndex: "35" }} - document={} - > - {({ blob, loading }) => ( - - )} - - ); - }; return (
{isMobile && isShowHeader ? ( @@ -240,32 +241,24 @@ function Header({
{isCompleted && ( - <> - {pdfDetails[0] && pdfDetails[0]?.CertificateUrl ? ( - handleDownloadCertificate()} - > -
- - Certificate -
-
- ) : ( - - - - )} - + handleDownloadCertificate()} + > +
+ + Certificate +
+
)} {isSignYourself && ( {isCompleted && ( - <> - {pdfDetails[0] && pdfDetails[0]?.CertificateUrl ? ( - - ) : ( - - )} - + )} - ) : ( - - )} - + )} - {formatRow(item?.ExtUserPtr)} diff --git a/apps/OpenSignServer/cloud/main.js b/apps/OpenSignServer/cloud/main.js index 652e69e53..bc6cb66a2 100644 --- a/apps/OpenSignServer/cloud/main.js +++ b/apps/OpenSignServer/cloud/main.js @@ -36,6 +36,7 @@ import TenantAterFind from './parsefunction/TenantAfterFind.js'; import saveSubscription from './parsefunction/saveSubscription.js'; import VerifyEmail from './parsefunction/VerifyEmail.js'; import encryptedpdf from './parsefunction/encryptedPdf.js'; +import { getSignedUrl } from './parsefunction/getSignedUrl.js'; Parse.Cloud.define('AddUserToRole', addUserToGroups); Parse.Cloud.define('UserGroups', getUserGroups); @@ -74,4 +75,5 @@ 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) +Parse.Cloud.define('encryptedpdf', encryptedpdf); +Parse.Cloud.define('getsignedurl', getSignedUrl); diff --git a/apps/OpenSignServer/cloud/parsefunction/getSignedUrl.js b/apps/OpenSignServer/cloud/parsefunction/getSignedUrl.js index d2869b549..642b41fdd 100644 --- a/apps/OpenSignServer/cloud/parsefunction/getSignedUrl.js +++ b/apps/OpenSignServer/cloud/parsefunction/getSignedUrl.js @@ -1,4 +1,5 @@ import AWS from 'aws-sdk'; +import { useLocal } from '../../Utils.js'; const credentials = { accessKeyId: process.env.DO_ACCESS_KEY_ID, secretAccessKey: process.env.DO_SECRET_ACCESS_KEY, @@ -24,3 +25,25 @@ export default function getPresignedUrl(url) { }); return presignedGETURL; } + +export async function getSignedUrl(request) { + try { + const url = request.params.url; + if (!request?.user) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.'); + } else { + if (useLocal !== 'true') { + const presignedUrl = getPresignedUrl(url); + return presignedUrl; + } else { + return url; + } + } + } catch (err) { + console.log('error in getsignedurl', err); + const code = err.code || 400; + const msg = err.message; + const error = new Parse.Error(code, msg); + throw error; + } +}