diff --git a/apps/OpenSign/src/constant/Utils.js b/apps/OpenSign/src/constant/Utils.js
index 67b399d03..ab4f4e9a6 100644
--- a/apps/OpenSign/src/constant/Utils.js
+++ b/apps/OpenSign/src/constant/Utils.js
@@ -541,54 +541,88 @@ export const signPdfFun = async (
setIsAlert,
objectId,
isSubscribed,
- activeMailAdapter
+ activeMailAdapter,
+ xyPosition
) => {
let singleSign,
isCustomCompletionMail = false;
- //get tenant details
- const tenantDetails = await getTenantDetails(objectId);
- if (tenantDetails && tenantDetails === "user does not exist!") {
- alert("User does not exist");
- } else {
- if (
- tenantDetails?.CompletionBody &&
- tenantDetails?.CompletionSubject &&
- (!isEnableSubscription || isSubscribed)
- ) {
- isCustomCompletionMail = true;
- }
- }
-
- singleSign = {
- mailProvider: activeMailAdapter,
- pdfFile: base64Url,
- docId: documentId,
- userId: signerObjectId,
- isCustomCompletionMail: isCustomCompletionMail
- };
- const response = await axios
- .post(`${localStorage.getItem("baseUrl")}functions/signPdf`, singleSign, {
- headers: {
- "Content-Type": "application/json",
- "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
- sessionToken: localStorage.getItem("accesstoken")
+ try {
+ //get tenant details
+ const tenantDetails = await getTenantDetails(objectId);
+ if (tenantDetails && tenantDetails === "user does not exist!") {
+ alert("User does not exist");
+ } else {
+ if (
+ tenantDetails?.CompletionBody &&
+ tenantDetails?.CompletionSubject &&
+ (!isEnableSubscription || isSubscribed)
+ ) {
+ isCustomCompletionMail = true;
}
- })
- .then((Listdata) => {
- const json = Listdata.data;
- const res = json.result;
- return res;
- })
- .catch((err) => {
- console.log("Err ", err);
- setIsAlert({
- isShow: true,
- alertMessage: "something went wrong"
- });
- });
+ }
- return response;
+ let getSignature;
+ for (let item of xyPosition) {
+ const typeExist = item.pos.some((data) => data?.type);
+ if (typeExist) {
+ getSignature = item.pos.filter((data) => data?.type === "signature");
+ } else {
+ getSignature = item.pos.filter((data) => !data.isStamp);
+ }
+ }
+ let base64Sign = getSignature[0].SignUrl;
+ //check https type signature (default signature exist) then convert in base64
+ const isUrl = base64Sign.includes("https");
+ if (isUrl) {
+ try {
+ base64Sign = await fetchImageBase64(base64Sign);
+ } catch (e) {
+ console.log("error", e);
+ }
+ }
+ //change image width and height to 104/44 in png base64
+ const getNewse64 = await changeImageWH(base64Sign);
+ //remove suffiix of base64
+ const suffixbase64 = getNewse64 && getNewse64.split(",").pop();
+
+ singleSign = {
+ mailProvider: activeMailAdapter,
+ pdfFile: base64Url,
+ docId: documentId,
+ userId: signerObjectId,
+ isCustomCompletionMail: isCustomCompletionMail,
+ signature: suffixbase64
+ };
+ const response = await axios
+ .post(`${localStorage.getItem("baseUrl")}functions/signPdf`, singleSign, {
+ headers: {
+ "Content-Type": "application/json",
+ "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
+ // sessionToken: localStorage.getItem("accesstoken")
+ "X-Parse-Session-Token": localStorage.getItem("accesstoken")
+ }
+ })
+ .then((Listdata) => {
+ const json = Listdata.data;
+ const res = json.result;
+ return res;
+ })
+ .catch((err) => {
+ console.log("Err ", err);
+ setIsAlert({
+ isShow: true,
+ alertMessage: "something went wrong"
+ });
+ });
+
+ return response;
+ } catch (e) {
+ setIsAlert({
+ isShow: true,
+ alertMessage: "something went wrong"
+ });
+ }
};
export const randomId = () => {
@@ -1125,7 +1159,6 @@ export const onImageSelect = (event, setImgWH, setImage) => {
const imageType = event.target.files[0].type;
const reader = new FileReader();
reader.readAsDataURL(event.target.files[0]);
-
reader.onloadend = function (e) {
let width, height;
const image = new Image();
@@ -1153,6 +1186,50 @@ export const onImageSelect = (event, setImgWH, setImage) => {
};
};
+//convert https url to base64
+export const fetchImageBase64 = async (imageUrl) => {
+ try {
+ const response = await fetch(imageUrl);
+ const blob = await response.blob();
+
+ return new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.readAsDataURL(blob);
+ reader.onloadend = () => {
+ const base64data = reader.result;
+ resolve(base64data);
+ };
+ reader.onerror = (error) => {
+ reject(error);
+ };
+ });
+ } catch (error) {
+ throw new Error("Error converting URL to base64:", error);
+ }
+};
+//function for select image and upload image
+export const changeImageWH = async (base64Image) => {
+ const newWidth = 100;
+ const newHeight = 40;
+ return new Promise((resolve, reject) => {
+ const img = new Image();
+ img.src = base64Image;
+ img.onload = async () => {
+ const canvas = document.createElement("canvas");
+ const ctx = canvas.getContext("2d");
+ canvas.width = newWidth;
+ canvas.height = newHeight;
+ ctx.imageSmoothingEnabled = false;
+ ctx.drawImage(img, 0, 0, newWidth, newHeight);
+ const resizedBase64 = canvas.toDataURL("image/png", 1);
+ resolve(resizedBase64);
+ };
+ img.onerror = (error) => {
+ reject(error);
+ };
+ });
+};
+
//function for embed multiple signature using pdf-lib
export const multiSignEmbed = async (
pngUrl,
@@ -1267,8 +1344,8 @@ export const multiSignEmbed = async (
position.type === radioButtonWidget
? 10
: position.type === "checkbox"
- ? 10
- : newUpdateHeight;
+ ? 10
+ : newUpdateHeight;
const newHeight = ind ? (ind > 0 ? widgetHeight : 0) : widgetHeight;
if (signyourself) {
diff --git a/apps/OpenSign/src/pages/Form.js b/apps/OpenSign/src/pages/Form.js
index 1a53c6da7..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,22 +90,112 @@ 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 {
- await Parse.Cloud.run("encryptedpdf", {
- email: Parse.User.current().getEmail()
- });
+ const res = await getFileAsArrayBuffer(files[0]);
+ await PDFDocument.load(res);
+ handleFileUpload(files[0]);
} catch (err) {
- console.log("err in sending posthog encryptedpdf", 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);
+ }
+ }
}
}
}
@@ -360,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 c3ea8300c..50be8ced4 100644
--- a/apps/OpenSign/src/pages/PdfRequestFiles.js
+++ b/apps/OpenSign/src/pages/PdfRequestFiles.js
@@ -271,6 +271,7 @@ function PdfRequestFiles() {
) {
const params = {
event: "viewed",
+ contactId: currUserId,
body: {
objectId: documentData?.[0].objectId,
file: documentData?.[0]?.SignedUrl || documentData?.[0]?.URL,
@@ -471,7 +472,8 @@ function PdfRequestFiles() {
const maxCount =
requiredCheckbox[i].options?.validation?.maxRequiredCount;
const parseMax = maxCount && parseInt(maxCount);
- const response = requiredCheckbox[i].options?.response?.length;
+ const response =
+ requiredCheckbox[i].options?.response?.length;
const defaultValue =
requiredCheckbox[i].options?.defaultValue?.length;
if (parseMin === 0 && parseMax === 0) {
@@ -615,7 +617,8 @@ function PdfRequestFiles() {
setIsAlert,
objectId,
isSubscribed,
- activeMailAdapter
+ activeMailAdapter,
+ pngUrl
);
if (res && res.status === "success") {
setPdfUrl(res.data);
@@ -641,11 +644,14 @@ function PdfRequestFiles() {
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"
- });
+ const localExpireDate = newDate.toLocaleDateString(
+ "en-US",
+ {
+ day: "numeric",
+ month: "long",
+ year: "numeric"
+ }
+ );
let senderEmail = pdfDetails?.[0].ExtUserPtr.Email;
let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone;
const senderName = `${pdfDetails?.[0].ExtUserPtr.Name}`;
@@ -682,7 +688,10 @@ function PdfRequestFiles() {
requestSubject &&
(!isEnableSubscription || isSubscribed)
) {
- const replacedRequestBody = requestBody.replace(/"/g, "'");
+ const replacedRequestBody = requestBody.replace(
+ /"/g,
+ "'"
+ );
const htmlReqBody =
"
" +
replacedRequestBody +
@@ -1156,9 +1165,9 @@ function PdfRequestFiles() {
isDecline.currnt === "Sure"
? "Are you sure want to decline this document ?"
: isDecline.currnt === "YouDeclined"
- ? "You have declined this document!"
- : isDecline.currnt === "another" &&
- "You can not sign this document as it has been declined/revoked."
+ ? "You have declined this document!"
+ : isDecline.currnt === "another" &&
+ "You can not sign this document as it has been declined/revoked."
}
footerMessage={isDecline.currnt === "Sure"}
declineDoc={declineDoc}
diff --git a/apps/OpenSign/src/pages/SignyourselfPdf.js b/apps/OpenSign/src/pages/SignyourselfPdf.js
index 74772ce70..2b276d776 100644
--- a/apps/OpenSign/src/pages/SignyourselfPdf.js
+++ b/apps/OpenSign/src/pages/SignyourselfPdf.js
@@ -29,7 +29,9 @@ import {
textWidget,
getTenantDetails,
checkIsSubscribed,
- convertPdfArrayBuffer
+ convertPdfArrayBuffer,
+ fetchImageBase64,
+ changeImageWH
} from "../constant/Utils";
import { useParams } from "react-router-dom";
import Tour from "reactour";
@@ -194,13 +196,18 @@ function SignYourSelf() {
setPdfDetails(documentData);
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
const url = documentData[0] && documentData[0]?.URL;
- //convert document url in array buffer format to use embed widgets in pdf using pdf-lib
- const arrayBuffer = await convertPdfArrayBuffer(url);
- if (arrayBuffer === "Error") {
- setHandleError("Error: Something went wrong!");
+ if (url) {
+ //convert document url in array buffer format to use embed widgets in pdf using pdf-lib
+ const arrayBuffer = await convertPdfArrayBuffer(url);
+ if (arrayBuffer === "Error") {
+ setHandleError("Error: Something went wrong!");
+ } else {
+ setPdfArrayBuffer(arrayBuffer);
+ }
} else {
- setPdfArrayBuffer(arrayBuffer);
+ setHandleError("Error: Something went wrong!");
}
+
isCompleted = documentData[0].IsCompleted && documentData[0].IsCompleted;
if (isCompleted) {
setIsCompleted(true);
@@ -443,13 +450,13 @@ function SignYourSelf() {
Width: widgetTypeExist
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getWidth
: dragTypeValue === "initials"
- ? defaultWidthHeight(dragTypeValue).width
- : "",
+ ? defaultWidthHeight(dragTypeValue).width
+ : "",
Height: widgetTypeExist
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getHeight
: dragTypeValue === "initials"
- ? defaultWidthHeight(dragTypeValue).height
- : "",
+ ? defaultWidthHeight(dragTypeValue).height
+ : "",
options: addWidgetOptions(dragTypeValue)
};
@@ -526,7 +533,6 @@ function SignYourSelf() {
setSelectWidgetId(key);
setSignKey(key);
};
-
//function for send placeholder's co-ordinate(x,y) position embed signature url or stamp url
async function embedWidgetsData() {
let showAlert = false;
@@ -613,7 +619,6 @@ function SignYourSelf() {
});
}
}
- // console.log("signyourself", xyPostion);
//function for get digital signature
const signPdfFun = async (base64Url, documentId) => {
let isCustomCompletionMail = false;
@@ -630,12 +635,36 @@ function SignYourSelf() {
isCustomCompletionMail = true;
}
}
+ let getSignature;
+ for (let item of xyPostion) {
+ const typeExist = item.pos.some((data) => data?.type);
+ if (typeExist) {
+ getSignature = item.pos.filter((data) => data?.type === "signature");
+ } else {
+ getSignature = item.pos.filter((data) => !data.isStamp);
+ }
+ }
+ let base64Sign = getSignature[0].SignUrl;
+ //check https type signature (default signature exist) then convert in base64
+ const isUrl = base64Sign.includes("https");
+ if (isUrl) {
+ try {
+ base64Sign = await fetchImageBase64(base64Sign);
+ } catch (e) {
+ console.log("error", e);
+ }
+ }
+ //change image width and height to 104/44 in png base64
+ const getNewse64 = await changeImageWH(base64Sign);
+ //remove suffiix of base64
+ const suffixbase64 = getNewse64 && getNewse64.split(",").pop();
let singleSign = {
pdfFile: base64Url,
docId: documentId,
isCustomCompletionMail: isCustomCompletionMail,
- mailProvider: activeMailAdapter
+ mailProvider: activeMailAdapter,
+ signature: suffixbase64
};
await axios
diff --git a/apps/OpenSign/src/pages/UserProfile.js b/apps/OpenSign/src/pages/UserProfile.js
index eaeafffaa..69b491468 100644
--- a/apps/OpenSign/src/pages/UserProfile.js
+++ b/apps/OpenSign/src/pages/UserProfile.js
@@ -8,9 +8,10 @@ import sanitizeFileName from "../primitives/sanitizeFileName";
import axios from "axios";
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
import Tooltip from "../primitives/Tooltip";
-import { isEnableSubscription } from "../constant/const";
+import { isEnableSubscription, rejectBtn, submitBtn } from "../constant/const";
import { checkIsSubscribed } from "../constant/Utils";
import Upgrade from "../primitives/Upgrade";
+import ModalUi from "../primitives/ModalUi";
function UserProfile() {
const navigate = useNavigate();
@@ -32,12 +33,16 @@ function UserProfile() {
const [jobTitle, setJobTitle] = useState(
extendUser && extendUser?.[0]?.JobTitle
);
-
+ const [isVerifyModal, setIsVerifyModal] = useState(false);
+ const [otp, setOtp] = useState("");
+ const [otpLoader, setOtpLoader] = useState(false);
+ const [isEmailVerified, setIsEmailVerified] = useState(false);
useEffect(() => {
getUserDetail();
}, []);
const getUserDetail = async () => {
+ setIsLoader(true);
const extClass = localStorage.getItem("Extand_Class");
const jsonSender = JSON.parse(extClass);
const HeaderDocId = jsonSender[0]?.HeaderDocId;
@@ -48,6 +53,9 @@ function UserProfile() {
if (HeaderDocId) {
setIsDisableDocId(HeaderDocId);
}
+ const isEmailVerified = Parse.User.current()?.attributes?.emailVerified;
+ setIsEmailVerified(isEmailVerified);
+ setIsLoader(false);
};
const handleSubmit = async (e) => {
e.preventDefault();
@@ -177,6 +185,56 @@ function UserProfile() {
const handleDisableDocId = () => {
setIsDisableDocId((prevChecked) => !prevChecked);
};
+ const handleVerifyBtn = async () => {
+ setIsVerifyModal(true);
+ await handleSendOTP();
+ };
+ const handleCloseVerifyModal = async () => {
+ setIsVerifyModal(false);
+ };
+ const handleSendOTP = async () => {
+ try {
+ let url = `${parseBaseUrl}functions/SendOTPMailV1`;
+ const headers = {
+ "Content-Type": "application/json",
+ "X-Parse-Application-Id": parseAppId
+ };
+ const body = { email: Parse.User.current().getEmail() };
+ await axios.post(url, body, { headers: headers });
+ } catch (error) {
+ alert(error.message);
+ }
+ };
+
+ const handleVerifyEmail = async (e) => {
+ e.preventDefault();
+ setOtpLoader(true);
+ try {
+ const resEmail = await Parse.Cloud.run("verifyemail", {
+ 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) {
+ alert(error.message);
+ } finally {
+ setOtpLoader(false);
+ }
+ };
+ const handleReset = async (e) => {
+ e.preventDefault();
+ setOtpLoader(true);
+ await handleSendOTP();
+ setOtpLoader(false);
+ alert("OTP sent on you email");
+ };
return (
@@ -310,9 +368,20 @@ function UserProfile() {
Is Email verified:{" "}
- {UserProfile && UserProfile.emailVerified
- ? "Verified"
- : "Not verified"}
+ {isEmailVerified ? (
+ "Verified"
+ ) : (
+
+ Not verified(
+ handleVerifyBtn()}
+ className="hover:underline text-blue-600 cursor-pointer"
+ >
+ verify
+
+ )
+
+ )}
@@ -399,6 +468,59 @@ function UserProfile() {
+
+ {isVerifyModal && (
+
+ {otpLoader ? (
+
+ ) : (
+
+ )}
+
+ )}
)}
diff --git a/apps/OpenSignServer/cloud/main.js b/apps/OpenSignServer/cloud/main.js
index 47869fadc..652e69e53 100644
--- a/apps/OpenSignServer/cloud/main.js
+++ b/apps/OpenSignServer/cloud/main.js
@@ -33,7 +33,8 @@ import getInvoices from './parsefunction/getInvoices.js';
import getPayments from './parsefunction/getPayments.js';
import getSubscriptions from './parsefunction/getSubscriptions.js';
import TenantAterFind from './parsefunction/TenantAfterFind.js';
-import saveSubscriptio from './parsefunction/saveSubscription.js';
+import saveSubscription from './parsefunction/saveSubscription.js';
+import VerifyEmail from './parsefunction/VerifyEmail.js';
import encryptedpdf from './parsefunction/encryptedPdf.js';
Parse.Cloud.define('AddUserToRole', addUserToGroups);
@@ -71,5 +72,6 @@ Parse.Cloud.afterFind('contracts_Document', DocumentBeforeFind);
Parse.Cloud.afterFind('contracts_Template', TemplateAfterFind);
Parse.Cloud.afterFind('contracts_Signature', SignatureAfterFind);
Parse.Cloud.afterFind('partners_Tenant', TenantAterFind);
-Parse.Cloud.define('savesubscription', saveSubscriptio);
+Parse.Cloud.define('savesubscription', saveSubscription);
+Parse.Cloud.define('verifyemail', VerifyEmail);
Parse.Cloud.define('encryptedpdf', encryptedpdf)
diff --git a/apps/OpenSignServer/cloud/parsefunction/VerifyEmail.js b/apps/OpenSignServer/cloud/parsefunction/VerifyEmail.js
new file mode 100644
index 000000000..8c1f08d32
--- /dev/null
+++ b/apps/OpenSignServer/cloud/parsefunction/VerifyEmail.js
@@ -0,0 +1,49 @@
+export default async function VerifyEmail(request) {
+ try {
+ if (!request?.user) {
+ throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
+ } else {
+ let otpN = request.params.otp;
+ let otp = parseInt(otpN);
+ let email = request.params.email;
+
+ //checking otp is correct or not which already save in defaultdata_Otp class
+ const checkOtp = new Parse.Query('defaultdata_Otp');
+ checkOtp.equalTo('Email', email);
+ checkOtp.equalTo('OTP', otp);
+
+ const res = await checkOtp.first({ useMasterKey: true });
+ if (res) {
+ // Fetch the user by their objectId
+ const isEmailVerified = request?.user?.get('emailVerified');
+ if (isEmailVerified) {
+ return { message: 'Email is already verified.' };
+ } else {
+ const userQuery = new Parse.Query(Parse.User);
+ const user = await userQuery.get(request?.user.id, {
+ sessionToken: request?.user.getSessionToken(),
+ });
+
+ // Update the emailVerified field to true
+ user.set('emailVerified', true);
+ // Save the user object
+ const res = await user.save(null, { useMasterKey: true });
+ if (res) {
+ return { message: 'Email is verified.' };
+ } else {
+ const error = new Error('Something went wrong, please try again later!');
+ error.code = 400; // Set the error code (e.g., 400 for bad request)
+ throw error;
+ }
+ }
+ } else {
+ const error = new Error('OTP is invalid.');
+ error.code = 400; // Set the error code (e.g., 400 for bad request)
+ throw error;
+ }
+ }
+ } catch (err) {
+ console.log('err ', err.code + ' ' + err.message);
+ throw err;
+ }
+}
diff --git a/apps/OpenSignServer/cloud/parsefunction/callWebhook.js b/apps/OpenSignServer/cloud/parsefunction/callWebhook.js
index 7e2fa4056..a9d127c36 100644
--- a/apps/OpenSignServer/cloud/parsefunction/callWebhook.js
+++ b/apps/OpenSignServer/cloud/parsefunction/callWebhook.js
@@ -2,6 +2,8 @@ import axios from 'axios';
export default async function callWebhook(request) {
const event = request.params.event;
const body = request.params.body;
+ const docId = body.objectId;
+ const contactId = request.params.contactId;
const serverUrl = process.env.SERVER_URL;
const appId = process.env.APP_ID;
const userRes = await axios.get(serverUrl + '/users/me', {
@@ -13,6 +15,39 @@ export default async function callWebhook(request) {
const userId = userRes.data && userRes.data.objectId;
if (userId) {
+ if (event === 'viewed' && contactId) {
+ const docQuery = new Parse.Query('contracts_Document');
+ const res = await docQuery.get(docId, { useMasterKey: true });
+ if (res) {
+ const _res = res.toJSON();
+ const userPtr = {
+ __type: 'Pointer',
+ className: 'contracts_Contactbook',
+ objectId: contactId,
+ };
+ const date = new Date().toISOString();
+ const obj = {
+ UserPtr: userPtr,
+ SignedUrl: _res.SignedUrl,
+ Activity: 'Viewed',
+ ipAddress: request.headers['x-real-ip'],
+ ViewedOn: date,
+ };
+ const isUserExist = _res?.AuditTrail?.some(
+ x => x.UserPtr.objectId === contactId && x?.ViewedOn
+ );
+ if (!isUserExist) {
+ const updateDoc = new Parse.Object('contracts_Document');
+ updateDoc.id = res.id;
+ if (_res?.AuditTrail && _res?.AuditTrail?.length > 0) {
+ updateDoc.set('AuditTrail', [..._res?.AuditTrail, obj]);
+ } else {
+ updateDoc.set('AuditTrail', [obj]);
+ }
+ await updateDoc.save(null, { useMasterKey: true });
+ }
+ }
+ }
const extendcls = new Parse.Query('contracts_Users');
extendcls.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: userId });
const res = await extendcls.first({ useMasterKey: true });
@@ -39,11 +74,11 @@ export default async function callWebhook(request) {
});
webhook.save(null, { useMasterKey: true });
} catch (err) {
- console.log('err save in contracts_Webhook', err);
+ console.log('err save in contracts_Webhook', err.message);
}
})
.catch(err => {
- console.log('Err send data to webhook', err);
+ console.log('Err send data to webhook', err.message);
try {
const webhook = new Parse.Object('contracts_Webhook');
webhook.set('Log', err?.status);
@@ -54,7 +89,7 @@ export default async function callWebhook(request) {
});
webhook.save(null, { useMasterKey: true });
} catch (err) {
- console.log('err save in contracts_Webhook', err);
+ console.log('err save in contracts_Webhook', err.message);
}
});
}
diff --git a/apps/OpenSignServer/cloud/parsefunction/encryptedPdf.js b/apps/OpenSignServer/cloud/parsefunction/encryptedPdf.js
index 7fb6c58cf..315cf737b 100644
--- a/apps/OpenSignServer/cloud/parsefunction/encryptedPdf.js
+++ b/apps/OpenSignServer/cloud/parsefunction/encryptedPdf.js
@@ -1,6 +1,6 @@
import { PostHog } from 'posthog-node';
const ph_project_api_key = process.env.PH_PROJECT_API_KEY;
-const client = new PostHog(ph_project_api_key);
+const client = ph_project_api_key ? new PostHog(ph_project_api_key) : '';
export default async function encryptedpdf(request) {
const email = request.params.email;
if (client) {
diff --git a/apps/OpenSignServer/cloud/parsefunction/pdf/GenerateCertificate.js b/apps/OpenSignServer/cloud/parsefunction/pdf/GenerateCertificate.js
index 2b9b7625f..1d8fc2d15 100644
--- a/apps/OpenSignServer/cloud/parsefunction/pdf/GenerateCertificate.js
+++ b/apps/OpenSignServer/cloud/parsefunction/pdf/GenerateCertificate.js
@@ -17,21 +17,36 @@ export default async function GenerateCertificate(docDetails) {
const text = 14;
const textKeyColor = rgb(0.12, 0.12, 0.12);
const textValueColor = rgb(0.3, 0.3, 0.3);
- const completedAt = new Date(docDetails.updatedAt);
+ const completedAt = new Date();
const completedUTCtime = completedAt.toUTCString();
const signersCount = docDetails?.Signers?.length || 1;
- const createdAt = new Date();
- const createdUTCTime = createdAt.toUTCString();
- const createDate = 'Generated On ' + createdUTCTime;
+ const generateAt = new Date();
+ const generatedUTCTime = generateAt.toUTCString();
+ const generatedOn = 'Generated On ' + generatedUTCTime;
const company = docDetails?.ExtUserPtr?.Company || '';
const auditTrail =
docDetails.AuditTrail?.length > 1
? docDetails.AuditTrail.map(x => {
const data = docDetails.Signers.find(y => y.objectId === x.UserPtr.objectId);
- return { ...data, ipAddress: x.ipAddress };
+ return {
+ ...data,
+ ipAddress: x.ipAddress,
+ SignedOn: x?.SignedOn || generatedUTCTime,
+ ViewedOn: x?.ViewedOn || generatedUTCTime,
+ Signature: x?.Signature || '',
+ };
})
- : [{ ...docDetails.ExtUserPtr, ipAddress: docDetails?.AuditTrail[0].ipAddress }];
+ : [
+ {
+ ...docDetails.ExtUserPtr,
+ ipAddress: docDetails?.AuditTrail[0].ipAddress,
+ SignedOn: docDetails?.AuditTrail[0]?.SignedOn || generatedUTCTime,
+ ViewedOn: docDetails?.AuditTrail[0]?.ViewedOn || generatedUTCTime,
+ Signature: docDetails?.AuditTrail[0]?.Signature || '',
+ },
+ ];
+ const half = width / 2;
// Draw a border
page.drawRectangle({
x: startX,
@@ -48,7 +63,7 @@ export default async function GenerateCertificate(docDetails) {
height: 25,
});
- page.drawText(createDate, {
+ page.drawText(generatedOn, {
x: 320,
y: 810,
size: 12,
@@ -127,8 +142,7 @@ export default async function GenerateCertificate(docDetails) {
font: timesRomanFont,
color: textValueColor,
});
-
- page.drawText('Completed on :', {
+ page.drawText('Created on :', {
x: 30,
y: 625,
size: text,
@@ -136,15 +150,14 @@ export default async function GenerateCertificate(docDetails) {
color: textKeyColor,
});
- page.drawText(`${completedUTCtime}`, {
- x: 120,
+ page.drawText(`${new Date(docDetails.createdAt).toUTCString()}`, {
+ x: 105,
y: 625,
size: text,
font: timesRomanFont,
color: textValueColor,
});
-
- page.drawText('Signers :', {
+ page.drawText('Completed on :', {
x: 30,
y: 605,
size: text,
@@ -152,35 +165,102 @@ export default async function GenerateCertificate(docDetails) {
color: textKeyColor,
});
+ page.drawText(`${completedUTCtime}`, {
+ x: 125,
+ y: 605,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+ page.drawText('Signers :', {
+ x: 30,
+ y: 585,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+
page.drawText(`${signersCount}`, {
x: 80,
- y: 605,
+ y: 585,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+ page.drawText('Document originator', {
+ x: 30,
+ y: 565,
+ size: 17,
+ font: timesRomanFont,
+ color: titleColor,
+ });
+ page.drawText('Name :', {
+ x: 60,
+ y: 545,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+ page.drawText(`${docDetails.ExtUserPtr.Name}`, {
+ x: 105,
+ y: 545,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+ page.drawText('Email :', {
+ x: 60,
+ y: 525,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+ page.drawText(`${docDetails.ExtUserPtr.Email}`, {
+ x: 105,
+ y: 525,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+ page.drawText('IP address :', {
+ x: 60,
+ y: 505,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+ page.drawText(`152.58.21.622`, {
+ x: 130,
+ y: 505,
size: text,
font: timesRomanFont,
color: textValueColor,
});
page.drawLine({
- start: { x: 30, y: 565 },
- end: { x: width - 30, y: 565 },
+ start: { x: 30, y: 495 },
+ end: { x: width - 30, y: 495 },
color: rgb(0.12, 0.12, 0.12),
thickness: 0.5,
});
- page.drawText('Recipients', {
- x: 30,
- y: 575,
- size: subtitle,
- font: timesRomanFont,
- color: titleColor,
- });
- let yPosition1 = 550;
- let yPosition2 = 530;
- let yPosition3 = 510;
- let yPosition4 = 500;
- auditTrail.forEach(x => {
- page.drawText('Name :', {
+ let yPosition1 = 475;
+ let yPosition2 = 455;
+ let yPosition3 = 435;
+ let yPosition4 = 415;
+ let yPosition5 = 395;
+ let yPosition6 = 360;
+ auditTrail.slice(0, 3).forEach(async (x, i) => {
+ const embedPng = x.Signature ? await pdfDoc.embedPng(x.Signature) : '';
+ page.drawText(`Signer ${i + 1}`, {
x: 30,
y: yPosition1,
+ size: subtitle,
+ font: timesRomanFont,
+ color: titleColor,
+ });
+ page.drawText('Name :', {
+ x: 30,
+ y: yPosition2,
size: text,
font: timesRomanFont,
color: textKeyColor,
@@ -188,7 +268,23 @@ export default async function GenerateCertificate(docDetails) {
page.drawText(x?.Name, {
x: 75,
- y: yPosition1,
+ y: yPosition2,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+
+ page.drawText('Viewed on :', {
+ x: half,
+ y: yPosition2,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+
+ page.drawText(`${new Date(x.ViewedOn).toUTCString()}`, {
+ x: half + 75,
+ y: yPosition2,
size: text,
font: timesRomanFont,
color: textValueColor,
@@ -196,7 +292,7 @@ export default async function GenerateCertificate(docDetails) {
page.drawText('Email :', {
x: 30,
- y: yPosition2,
+ y: yPosition3,
size: text,
font: timesRomanFont,
color: textKeyColor,
@@ -204,41 +300,271 @@ export default async function GenerateCertificate(docDetails) {
page.drawText(x?.Email, {
x: 75,
- y: yPosition2,
+ y: yPosition3,
size: text,
font: timesRomanFont,
color: textValueColor,
});
- page.drawText('Accessed from :', {
- x: 30,
+ page.drawText('Signed on :', {
+ x: half,
y: yPosition3,
size: text,
font: timesRomanFont,
color: textKeyColor,
});
- page.drawText(x?.ipAddress, {
- x: 125,
+ page.drawText(`${new Date(x.SignedOn).toUTCString()}`, {
+ x: half + 70,
y: yPosition3,
size: text,
font: timesRomanFont,
color: textValueColor,
});
+ page.drawText('IP address :', {
+ x: 30,
+ y: yPosition4,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+
+ page.drawText(x?.ipAddress, {
+ x: 100,
+ y: yPosition4,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+ page.drawText('Security level :', {
+ x: half,
+ y: yPosition4,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+
+ page.drawText(`Email, OTP Auth`, {
+ x: half + 90,
+ y: yPosition4,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+
+ page.drawText('Signature :', {
+ x: 30,
+ y: yPosition5,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+
+ page.drawRectangle({
+ x: 98,
+ y: yPosition5 - 27,
+ width: 104,
+ height: 44,
+ borderColor: rgb(0.22, 0.18, 0.47),
+ borderWidth: 1,
+ });
+ if (embedPng) {
+ page.drawImage(embedPng, {
+ x: 100,
+ y: yPosition5 - 25,
+ width: 100,
+ height: 40,
+ });
+ }
page.drawLine({
- start: { x: 30, y: yPosition4 },
- end: { x: width - 30, y: yPosition4 },
+ start: { x: 30, y: yPosition6 },
+ end: { x: width - 30, y: yPosition6 },
color: rgb(0.12, 0.12, 0.12),
thickness: 0.5,
});
- yPosition1 = yPosition4 - 20;
+ yPosition1 = yPosition6 - 20;
yPosition2 = yPosition1 - 20;
yPosition3 = yPosition2 - 20;
- yPosition4 = yPosition4 - 70;
+ yPosition4 = yPosition3 - 20;
+ yPosition5 = yPosition4 - 20;
+ yPosition6 = yPosition6 - 140;
});
+ if (auditTrail.length > 3) {
+ let currentPageIndex = 1;
+ let currentPage = page;
+ auditTrail.slice(3).forEach(async (x, i) => {
+ const embedPng = x.Signature ? await pdfDoc.embedPng(x.Signature) : '';
+
+ // Calculate remaining space on current page
+ const remainingSpace = yPosition6;
+
+ // If there's not enough space for the next entry, create a new page
+ if (remainingSpace < 90) {
+ // Adjust the value as needed
+ currentPageIndex++;
+ currentPage = pdfDoc.addPage();
+ currentPage.drawRectangle({
+ x: startX,
+ y: startY,
+ width: width - 2 * startX,
+ height: height - 2 * startY,
+ borderColor: borderColor,
+ borderWidth: 1,
+ });
+ yPosition1 = currentPage.getHeight() - 40;
+ yPosition2 = yPosition1 - 20;
+ yPosition3 = yPosition2 - 20;
+ yPosition4 = yPosition3 - 20;
+ yPosition5 = yPosition4 - 20;
+ yPosition6 = currentPage.getHeight() - 160;
+ }
+
+ currentPage.drawText(`Signer ${4 + i}`, {
+ x: 30,
+ y: yPosition1,
+ size: subtitle,
+ font: timesRomanFont,
+ color: titleColor,
+ });
+ currentPage.drawText('Name :', {
+ x: 30,
+ y: yPosition2,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+
+ currentPage.drawText(x?.Name, {
+ x: 75,
+ y: yPosition2,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+
+ currentPage.drawText('Viewed on :', {
+ x: half,
+ y: yPosition2,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+
+ currentPage.drawText(`${new Date(x.ViewedOn).toUTCString()}`, {
+ x: half + 75,
+ y: yPosition2,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+
+ currentPage.drawText('Email :', {
+ x: 30,
+ y: yPosition3,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+
+ currentPage.drawText(x?.Email, {
+ x: 75,
+ y: yPosition3,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+
+ currentPage.drawText('Signed on :', {
+ x: half,
+ y: yPosition3,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+
+ currentPage.drawText(`${new Date(x.SignedOn).toUTCString()}`, {
+ x: half + 70,
+ y: yPosition3,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+
+ currentPage.drawText('IP address :', {
+ x: 30,
+ y: yPosition4,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+
+ currentPage.drawText(x?.ipAddress, {
+ x: 100,
+ y: yPosition4,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+ currentPage.drawText('Security level :', {
+ x: half,
+ y: yPosition4,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+
+ currentPage.drawText(`Email, OTP Auth`, {
+ x: half + 90,
+ y: yPosition4,
+ size: text,
+ font: timesRomanFont,
+ color: textValueColor,
+ });
+
+ currentPage.drawText('Signature :', {
+ x: 30,
+ y: yPosition5,
+ size: text,
+ font: timesRomanFont,
+ color: textKeyColor,
+ });
+ currentPage.drawRectangle({
+ x: 98,
+ y: yPosition5 - 27,
+ width: 104,
+ height: 44,
+ borderColor: rgb(0.22, 0.18, 0.47),
+ borderWidth: 1,
+ });
+ if (embedPng) {
+ currentPage.drawImage(embedPng, {
+ x: 100,
+ y: yPosition5 - 25,
+ width: 100,
+ height: 40,
+ });
+ }
+
+ currentPage.drawLine({
+ start: { x: 30, y: yPosition6 },
+ end: { x: width - 30, y: yPosition6 },
+ color: rgb(0.12, 0.12, 0.12),
+ thickness: 0.5,
+ });
+
+ // Update y positions for the next entry
+ yPosition1 = yPosition6 - 20;
+ yPosition2 = yPosition1 - 20;
+ yPosition3 = yPosition2 - 20;
+ yPosition4 = yPosition3 - 20;
+ yPosition5 = yPosition4 - 20;
+ yPosition6 = yPosition6 - 140;
+ });
+ }
+
const pdfBytes = await pdfDoc.save();
return pdfBytes;
}
diff --git a/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js b/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js
index 6b249f797..fec7ab4ef 100644
--- a/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js
+++ b/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js
@@ -8,85 +8,96 @@ import GenerateCertificate from './GenerateCertificate.js';
const serverUrl = process.env.SERVER_URL,
APPID = process.env.APP_ID,
masterKEY = process.env.MASTER_KEY;
-async function uploadFile(e, a) {
+async function uploadFile(e, t) {
try {
- var t = fs.readFileSync(a),
- s = new Parse.File(e, [...t], 'application/pdf'),
- r = (await s.save({ useMasterKey: !0 }), s.url());
- return { imageUrl: r };
+ var a = fs.readFileSync(t),
+ r = new Parse.File(e, [...a], 'application/pdf'),
+ i = (await r.save({ useMasterKey: !0 }), r.url());
+ return { imageUrl: i };
} catch (e) {
- console.log('Err ', e), fs.unlinkSync(a);
+ console.log('Err ', e), fs.unlinkSync(t);
}
}
-async function updateDoc(t, s, r, i, o, n) {
+async function updateDoc(a, r, i, s, o, n, l) {
try {
- var l = {
- UserPtr: { __type: 'Pointer', className: n, objectId: r },
- SignedUrl: s,
- Activity: 'Signed',
- ipAddress: i,
- };
+ var c,
+ d,
+ p = {
+ UserPtr: { __type: 'Pointer', className: n, objectId: i },
+ SignedUrl: r,
+ Activity: 'Signed',
+ ipAddress: s,
+ SignedOn: new Date(),
+ Signature: l,
+ };
let e;
- var d = (e = o.AuditTrail && 0 < o.AuditTrail.length ? [...o.AuditTrail, l] : [l]).filter(
- e => 'Signed' === e.Activity
- );
- let a = !1;
- !((o.Signers && 0 < o.Signers.length && d.length !== o.Signers.length) || !(a = !0));
- var c = { SignedUrl: s, AuditTrail: e, IsCompleted: a };
- await axios.put(serverUrl + '/classes/contracts_Document/' + t, c, {
+ var m = (e =
+ o.AuditTrail && 0 < o.AuditTrail.length
+ ? (-1 !==
+ (d = (c = JSON.parse(JSON.stringify(o.AuditTrail))).findIndex(
+ e => e.UserPtr.objectId === i && 'Created' !== e.Activity
+ ))
+ ? (c[d] = { ...c[d], ...p })
+ : c.push(p),
+ c)
+ : [p]).filter(e => 'Signed' === e.Activity);
+ let t = !1;
+ !((o.Signers && 0 < o.Signers.length && m.length !== o.Signers.length) || !(t = !0));
+ var g = { SignedUrl: r, AuditTrail: e, IsCompleted: t };
+ await axios.put(serverUrl + '/classes/contracts_Document/' + a, g, {
headers: {
'Content-Type': 'application/json',
'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY,
},
});
- return { isCompleted: a, message: 'success', AuditTrail: e };
+ return { isCompleted: t, message: 'success', AuditTrail: e };
} catch (e) {
return console.log('update doc err ', e), 'err';
}
}
async function sendCompletedMail(e) {
- var a = e.url,
- t = e.doc,
- s = e.doc.ExtUserPtr,
- r = t.Name,
- i = s.Email;
- let o = `Document "${r}" has been signed by all parties`,
+ var t = e.url,
+ a = e.doc,
+ r = e.doc.ExtUserPtr,
+ i = a.Name,
+ s = r.Email;
+ let o = `Document "${i}" has been signed by all parties`,
n =
" Document signed successfully
All parties have successfully signed the document " +
- `"${r}"` +
+ `"${i}"` +
'. Kindly download the document from the attachment.
This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender ' +
- s.Email +
+ r.Email +
' directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ here.
';
if (e?.isCustomMail)
try {
var l,
- d,
c,
+ d,
p,
m,
g = new Parse.Query('partners_Tenant');
- g.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: s.UserId.objectId });
- const u = await g.first();
- u &&
- ((l = JSON.parse(JSON.stringify(u)))?.CompletionSubject && (o = l?.CompletionSubject),
+ g.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: r.UserId.objectId });
+ const f = await g.first();
+ f &&
+ ((l = JSON.parse(JSON.stringify(f)))?.CompletionSubject && (o = l?.CompletionSubject),
l?.CompletionBody && (n = l?.CompletionBody),
- (d = t.ExpiryDate.iso),
- (c = new Date(d).toLocaleDateString('en-US', {
+ (c = a.ExpiryDate.iso),
+ (d = new Date(c).toLocaleDateString('en-US', {
day: 'numeric',
month: 'long',
year: 'numeric',
})),
(p = {
- document_title: r,
- sender_name: s.Name,
- sender_mail: s.Email,
- sender_phone: s.Phone,
- receiver_name: s.Name,
- receiver_email: s.Email,
- receiver_phone: s.Phone,
- expiry_date: c,
- company_name: s.Company,
+ document_title: i,
+ sender_name: r.Name,
+ sender_mail: r.Email,
+ sender_phone: r.Phone,
+ receiver_name: r.Name,
+ receiver_email: r.Email,
+ receiver_phone: r.Phone,
+ expiry_date: d,
+ company_name: r.Company,
}),
(m = replaceMailVaribles(o, n, p)),
(o = m.subject),
@@ -95,12 +106,12 @@ async function sendCompletedMail(e) {
console.log('error in fetch tenant in signpdf', e.message);
}
g = {
- extUserId: s.objectId,
- url: a,
+ extUserId: r.objectId,
+ url: t,
from: 'OpenSign™',
- recipient: i,
+ recipient: s,
subject: o,
- pdfName: r,
+ pdfName: i,
html: n,
mailProvider: e.mailProvider,
};
@@ -112,44 +123,40 @@ async function sendCompletedMail(e) {
},
});
}
-async function sendDoctoWebhook(t, e, a, s) {
- let r = [];
- (r = s
- ? { name: s?.Name, email: s?.Email, phone: s?.Phone }
- : t?.data?.Signers?.map(e => ({ name: e.Name, email: e.Email, phone: e.Phone })) || [
- {
- name: t?.data?.ExtUserPtr?.Name,
- email: t?.data?.ExtUserPtr?.Email,
- phone: t?.data?.ExtUserPtr?.Phone,
- },
+async function sendDoctoWebhook(a, e, t, r) {
+ let i = [];
+ (i = r
+ ? { name: r?.Name, email: r?.Email, phone: r?.Phone }
+ : a?.Signers?.map(e => ({ name: e.Name, email: e.Email, phone: e.Phone })) || [
+ { name: a?.ExtUserPtr?.Name, email: a?.ExtUserPtr?.Email, phone: a?.ExtUserPtr?.Phone },
]),
- t.data.ExtUserPtr?.Webhook &&
- ((s =
- 'signed' === a
- ? { signer: r, signedAt: new Date() }
- : { signers: r, completedAt: new Date() }),
- (a = {
- event: a,
- objectId: t?.data?.objectId,
+ a.ExtUserPtr?.Webhook &&
+ ((r =
+ 'signed' === t
+ ? { signer: i, signedAt: new Date() }
+ : { signers: i, completedAt: new Date() }),
+ (t = {
+ event: t,
+ objectId: a?.objectId,
file: e || '',
- name: t?.data?.Name,
- note: t?.data?.Note || '',
- description: t?.data?.Description || '',
- ...s,
- createdAt: t?.data?.createdAt,
+ name: a?.Name,
+ note: a?.Note || '',
+ description: a?.Description || '',
+ ...r,
+ createdAt: a?.createdAt,
}),
- await axios
- .post(t?.data?.ExtUserPtr?.Webhook, a, { headers: { 'Content-Type': 'application/json' } })
+ axios
+ .post(a?.ExtUserPtr?.Webhook, t, { headers: { 'Content-Type': 'application/json' } })
.then(e => {
try {
- var a = new Parse.Object('contracts_Webhook');
- a.set('Log', e?.status),
- a.set('UserId', {
+ var t = new Parse.Object('contracts_Webhook');
+ t.set('Log', e?.status),
+ t.set('UserId', {
__type: 'Pointer',
className: '_User',
- objectId: t.data.ExtUserPtr.UserId.objectId,
+ objectId: a.ExtUserPtr.UserId.objectId,
}),
- a.save(null, { useMasterKey: !0 });
+ t.save(null, { useMasterKey: !0 });
} catch (e) {
console.log('err save in contracts_Webhook', e.message);
}
@@ -157,109 +164,106 @@ async function sendDoctoWebhook(t, e, a, s) {
.catch(e => {
console.log('Err send data to webhook', e.message);
try {
- var a = new Parse.Object('contracts_Webhook');
- a.set('Log', e?.status),
- a.set('UserId', {
+ var t = new Parse.Object('contracts_Webhook');
+ t.set('Log', e?.status),
+ t.set('UserId', {
__type: 'Pointer',
className: '_User',
- objectId: t.data.ExtUserPtr.UserId.objectId,
+ objectId: a.ExtUserPtr.UserId.objectId,
}),
- a.save(null, { useMasterKey: !0 });
+ t.save(null, { useMasterKey: !0 });
} catch (e) {
console.log('err save in contracts_Webhook', e.message);
}
}));
}
+const sendMailsaveCertifcate = async (e, t, a, r, i, s) => {
+ var o = await GenerateCertificate(e),
+ o = await PDFDocument.load(o),
+ o =
+ (pdflibAddPlaceholder({
+ pdfDoc: o,
+ reason: 'Digitally signed by OpenSign.',
+ location: 'n/a',
+ signatureLength: 15e3,
+ }),
+ await o.save()),
+ o = Buffer.from(o),
+ t = await new SignPDF(o, t).signPDF(),
+ t =
+ (fs.writeFileSync('./exports/certificate.pdf', t),
+ await uploadFile('certificate.pdf', './exports/certificate.pdf')),
+ n = { CertificateUrl: t.imageUrl };
+ await axios.put(serverUrl + '/classes/contracts_Document/' + e.objectId, n, {
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-Parse-Application-Id': APPID,
+ 'X-Parse-Master-Key': masterKEY,
+ },
+ }),
+ e.IsSendMail && !1 === e.IsSendMail
+ ? console.log("don't send mail")
+ : sendCompletedMail({ url: a, isCustomMail: r, doc: e, mailProvider: i }),
+ saveFileUsage(o.length, t.imageUrl, s),
+ sendDoctoWebhook(e, a, 'completed');
+};
async function PDF(o) {
try {
- var n = o.params.docId,
- e = o.params.userId,
- l = o.params.isCustomCompletionMail || !1,
- d = o.params.mailProvider || '',
- c = await axios.get(
- serverUrl + '/classes/contracts_Document/' + n + '?include=ExtUserPtr,Signers',
- {
- headers: {
- 'Content-Type': 'application/json',
- 'X-Parse-Application-Id': APPID,
- 'X-Parse-Master-Key': masterKEY,
- },
- }
- ),
- p = await axios.get(serverUrl + '/users/me', {
- headers: {
- 'X-Parse-Application-Id': APPID,
- 'X-Parse-Session-Token': o.headers.sessiontoken,
- },
- });
- if (!p.data || !p.data.objectId) return { status: 'error', message: 'This user not allowed!' };
+ if (!o?.user)
+ throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
{
- var a,
- t,
- s,
- m = JSON.stringify({ objectId: e });
- let r, i;
- i = e
- ? (a = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + m, {
- headers: {
- 'X-Parse-Application-Id': APPID,
- 'X-Parse-Session-Token': o.headers.sessiontoken,
- },
- })).data && 0 < a.data.results.length
- ? ((r = a), 'contracts_Contactbook')
- : ((r = await axios.get(serverUrl + '/classes/contracts_Users?where=' + m, {
- headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY },
- })),
- 'contracts_Users')
- : ((t = JSON.stringify({
- UserId: { __type: 'Pointer', className: '_User', objectId: p.data.objectId },
- })),
- (s = await axios.get(serverUrl + '/classes/contracts_Users?where=' + t, {
- headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY },
- })).data && 0 < s.data.results.length
- ? ((r = s), 'contracts_Users')
- : ((r = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + t, {
- headers: {
- 'X-Parse-Application-Id': APPID,
- 'X-Parse-Session-Token': o.headers.sessiontoken,
- },
- })),
- 'contracts_Contactbook'));
- var g = r.data.results[0].Name,
- u = r.data.results[0].Email;
- if (!o.params.pdfFile) return { status: 'error', message: 'Pdf file not present!' };
+ var n = o?.user?.toJSON(),
+ e = o.params.docId;
+ const F = o.params.userId;
+ var l = o.params.isCustomCompletionMail || !1,
+ c = o.params.mailProvider || '',
+ d = o.params.signature || '',
+ t = new Parse.Query('contracts_Document'),
+ a =
+ (t.include('ExtUserPtr,Signers'),
+ t.equalTo('objectId', e),
+ await t.first({ useMasterKey: !0 }));
+ if (!a) throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.');
+ var r,
+ p = a?.toJSON();
+ let i, s;
+ F
+ ? ((r = p.Signers.find(e => e.objectId === F)),
+ console.log('_contractUser ', r),
+ r && ((i = r), (s = 'contracts_Contactbook')))
+ : ((s = 'contracts_Users'), (i = p.ExtUserPtr));
+ var m,
+ g = i.Name,
+ f = i.Email;
+ if (!o.params.pdfFile) throw (((m = new Error('Pdf file not present!')).code = 400), m);
{
let e = Buffer.from(o.params.pdfFile, 'base64');
- var h = process.env.PFX_BASE64,
- f = Buffer.from(h, 'base64'),
- P = {
- UserPtr: { __type: 'Pointer', className: i, objectId: r.data.results[0].objectId },
+ var u = process.env.PFX_BASE64,
+ h = Buffer.from(u, 'base64'),
+ y = {
+ UserPtr: { __type: 'Pointer', className: s, objectId: i.objectId },
SignedUrl: '',
Activity: 'Signed',
ipAddress: o.headers['x-real-ip'],
};
- let a;
- var y = (a =
- c.data.AuditTrail && 0 < c.data.AuditTrail.length
- ? [...c.data.AuditTrail, P]
- : [P]).filter(e => 'Signed' === e.Activity);
- let t = !1;
- !(
- (c.data.Signers && 0 < c.data.Signers.length && y.length !== c.data.Signers.length) ||
- !(t = !0)
+ let t;
+ var P = (t = p.AuditTrail && 0 < p.AuditTrail.length ? [...p.AuditTrail, y] : [y]).filter(
+ e => 'Signed' === e.Activity
);
+ let a = !1;
+ !((p.Signers && 0 < p.Signers.length && P.length !== p.Signers.length) || !(a = !0));
var v,
b,
- U,
- I,
+ S,
w,
+ U,
D,
- S = `exported_file_${Math.floor(5e3 * Math.random())}.pdf`,
- _ = './exports/' + S;
- let s = e.length;
- s = (
- t
- ? ((v = c.data.Signers?.map(e => e.Name + ' <' + e.Email + '>')),
+ I = `exported_file_${Math.floor(5e3 * Math.random())}.pdf`,
+ _ = './exports/' + I;
+ let r = e.length;
+ r = (
+ a
+ ? ((v = p.Signers?.map(e => e.Name + ' <' + e.Email + '>')),
(e =
v && 0 < v.length
? ((b = await PDFDocument.load(e)),
@@ -269,97 +273,53 @@ async function PDF(o) {
location: 'n/a',
signatureLength: 15e3,
}),
- (U = await b.save()),
- Buffer.from(U))
- : ((I = await PDFDocument.load(e)),
+ (S = await b.save()),
+ Buffer.from(S))
+ : ((w = await PDFDocument.load(e)),
pdflibAddPlaceholder({
- pdfDoc: I,
- reason: 'Digitally signed by OpenSign for ' + g + ' <' + u + '>',
+ pdfDoc: w,
+ reason: 'Digitally signed by OpenSign for ' + g + ' <' + f + '>',
location: 'n/a',
signatureLength: 15e3,
}),
- (w = await I.save()),
- Buffer.from(w))),
- (D = await new SignPDF(e, f).signPDF()),
+ (U = await w.save()),
+ Buffer.from(U))),
+ (D = await new SignPDF(e, h).signPDF()),
fs.writeFileSync(_, D),
D)
: (fs.writeFileSync(_, e), e)
).length;
- var A,
- x,
- E,
- j,
- k,
- F,
- C,
- T,
- N,
- M = await uploadFile(S, _);
- if (M && M.imageUrl)
- return (
- (A = await updateDoc(
+ var E = await uploadFile(I, _);
+ if (E && E.imageUrl) {
+ var x,
+ A,
+ j = await updateDoc(
o.params.docId,
- M.imageUrl,
- r.data.results[0].objectId,
+ E.imageUrl,
+ i.objectId,
o.headers['x-real-ip'],
- c.data,
- i
- )),
- sendDoctoWebhook(c, M.imageUrl, 'signed', r?.data.results?.[0]),
- saveFileUsage(s, M.imageUrl, p.data.objectId),
- A &&
- A.isCompleted &&
- ((x = { ...c.data, AuditTrail: A.AuditTrail }),
- (E = await GenerateCertificate(x)),
- (j = await PDFDocument.load(E)),
- pdflibAddPlaceholder({
- pdfDoc: j,
- reason: 'Digitally signed by OpenSign.',
- location: 'n/a',
- signatureLength: 15e3,
- }),
- (k = await j.save()),
- (F = Buffer.from(k)),
- (C = await new SignPDF(F, f).signPDF()),
- fs.writeFileSync('./exports/certificate.pdf', C),
- (N = {
- CertificateUrl: (T = await uploadFile(
- 'certificate.pdf',
- './exports/certificate.pdf'
- )).imageUrl,
- }),
- await axios.put(serverUrl + '/classes/contracts_Document/' + n, N, {
- headers: {
- 'Content-Type': 'application/json',
- 'X-Parse-Application-Id': APPID,
- 'X-Parse-Master-Key': masterKEY,
- },
- }),
- c.data.IsSendMail && !1 === c.data.IsSendMail
- ? console.log("don't send mail")
- : sendCompletedMail({
- url: M.imageUrl,
- isCustomMail: l,
- doc: c.data,
- mailProvider: d,
- }),
- saveFileUsage(F.length, T.imageUrl, p.data.objectId),
- sendDoctoWebhook(c, M.imageUrl, 'completed')),
+ p,
+ s,
+ d
+ );
+ if (
+ (sendDoctoWebhook(p, E.imageUrl, 'signed', i),
+ saveFileUsage(r, E.imageUrl, n.objectId),
+ j &&
+ j.isCompleted &&
+ ((x = { ...p, AuditTrail: j.AuditTrail }),
+ sendMailsaveCertifcate(x, h, E.imageUrl, l, c, n.objectId)),
fs.unlinkSync(_),
console.log('New Signed PDF created called: ' + _),
- 'success' === A.message
- ? { status: 'success', data: M.imageUrl }
- : { status: 'error', message: 'Please provide required parameters!' }
- );
+ 'success' === j.message)
+ )
+ return { status: 'success', data: E.imageUrl };
+ throw (((A = new Error('Please provide required parameters!')).code = 400), A);
+ }
}
}
} catch (e) {
- return (
- console.log('Err ', e),
- 'ERR_BAD_REQUEST' === e.code
- ? { status: 'error', message: 'Invalid session token!' }
- : { status: 'error', message: 'Encrypted files are currently not supported!' }
- );
+ throw (console.log('Err in signpdf', e), e);
}
}
export default PDF;
diff --git a/apps/OpenSignServer/cloud/parsefunction/saveSubscription.js b/apps/OpenSignServer/cloud/parsefunction/saveSubscription.js
index 9b1e262f6..2771e81c4 100644
--- a/apps/OpenSignServer/cloud/parsefunction/saveSubscription.js
+++ b/apps/OpenSignServer/cloud/parsefunction/saveSubscription.js
@@ -1,5 +1,5 @@
import axios from 'axios';
-export default async function saveSubscriptio(request) {
+export default async function saveSubscription(request) {
const serverUrl = process.env.SERVER_URL;
const appId = process.env.APP_ID;
const subscription = request.params.subscription;