diff --git a/apps/OpenSign/src/components/pdf/VerifyEmail.js b/apps/OpenSign/src/components/pdf/VerifyEmail.js new file mode 100644 index 000000000..48ed2b58b --- /dev/null +++ b/apps/OpenSign/src/components/pdf/VerifyEmail.js @@ -0,0 +1,85 @@ +import React from "react"; +import { rejectBtn, submitBtn, themeColor } from "../../constant/const"; + +function VerifyEmail(props) { + return ( +
+
+
+ OTP verification +
+ {props.isVerifyModal ? ( +
{ + props.setIsVerifyModal(false); + props.handleVerifyEmail(e); + }} + > +
+ + props.setOtp(e.target.value)} + /> +
+
+
+ + +
+
+ ) : props.otpLoader ? ( +
+
+
+ ) : ( +
+

Please verify your email !

+
+
+ +
+
+ )} +
+
+ ); +} + +export default VerifyEmail; diff --git a/apps/OpenSign/src/constant/Utils.js b/apps/OpenSign/src/constant/Utils.js index ab4f4e9a6..63289af0b 100644 --- a/apps/OpenSign/src/constant/Utils.js +++ b/apps/OpenSign/src/constant/Utils.js @@ -2008,3 +2008,18 @@ export const convertPdfArrayBuffer = async (url) => { return "Error"; } }; + +//`handleSendOTP` function is used to send otp on user's email using `SendOTPMailV1` cloud function +export const handleSendOTP = async (email) => { + try { + let url = `${localStorage.getItem("baseUrl")}functions/SendOTPMailV1`; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": localStorage.getItem("parseAppId") + }; + const body = { email: email }; + await axios.post(url, body, { headers: headers }); + } catch (error) { + alert(error.message); + } +}; diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js index 50be8ced4..4b4cb0781 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.js +++ b/apps/OpenSign/src/pages/PdfRequestFiles.js @@ -2,6 +2,7 @@ import React, { useState, useRef, useEffect } from "react"; import { isEnableSubscription, themeColor } from "../constant/const"; import { PDFDocument } from "pdf-lib"; import "../styles/signature.css"; +import Parse from "parse"; import axios from "axios"; import loader from "../assets/images/loader2.gif"; import { DndProvider } from "react-dnd"; @@ -25,7 +26,8 @@ import { replaceMailVaribles, fetchSubscription, convertPdfArrayBuffer, - contractUsers + contractUsers, + handleSendOTP } from "../constant/Utils"; import Loader from "../primitives/LoaderWithMsg"; import HandleError from "../primitives/HandleError"; @@ -35,6 +37,7 @@ import PdfDeclineModal from "../primitives/PdfDeclineModal"; import Title from "../components/Title"; import DefaultSignature from "../components/pdf/DefaultSignature"; import ModalUi from "../primitives/ModalUi"; +import VerifyEmail from "../components/pdf/VerifyEmail"; function PdfRequestFiles() { const { docId } = useParams(); @@ -57,10 +60,12 @@ function PdfRequestFiles() { const imageRef = useRef(null); const [handleError, setHandleError] = useState(); const [selectWidgetId, setSelectWidgetId] = useState(""); + const [otpLoader, setOtpLoader] = useState(false); const [isLoading, setIsLoading] = useState({ isLoad: true, message: "This might take some time" }); + const [defaultSignImg, setDefaultSignImg] = useState(); const [isDocId, setIsDocId] = useState(false); const [pdfNewWidth, setPdfNewWidth] = useState(); @@ -100,6 +105,9 @@ function PdfRequestFiles() { const [isSubscriptionExpired, setIsSubscriptionExpired] = useState(false); const [extUserId, setExtUserId] = useState(""); const [pdfArrayBuffer, setPdfArrayBuffer] = useState(""); + const [isEmailVerified, setIsEmailVerified] = useState(true); + const [isVerifyModal, setIsVerifyModal] = useState(false); + const [otp, setOtp] = useState(""); const divRef = useRef(null); const isMobile = window.innerWidth < 767; const rowLevel = @@ -139,6 +147,44 @@ function PdfRequestFiles() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [divRef.current]); + //function to use resend otp for email verification + const handleResend = async (e) => { + e.preventDefault(); + setOtpLoader(true); + await handleSendOTP(Parse.User.current().getEmail()); + setOtpLoader(false); + alert("OTP sent on you email"); + }; + //`handleVerifyEmail` function is used to verify email with otp + 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); + // handleRecipientSign(); + } catch (error) { + alert(error.message); + } finally { + setOtpLoader(false); + } + }; + + //`handleVerifyBtn` function is used to send otp on user mail + const handleVerifyBtn = async () => { + setIsVerifyModal(true); + await handleSendOTP(Parse.User.current().getEmail()); + }; async function checkIsSubscribed(extUserId, contactId) { const isGuestSign = location.pathname.includes("/load/") || false; const res = await fetchSubscription(extUserId, contactId, isGuestSign); @@ -238,6 +284,33 @@ function PdfRequestFiles() { setExpiredDate(expireDateFormat); } + const isGuestSign = location.pathname.includes("/load/"); + if ( + !isGuestSign && + !isCompleted && + !declined && + currDate < expireUpdateDate + ) { + const currentUser = JSON.parse(JSON.stringify(Parse.User.current())); + let isEmailVerified; + isEmailVerified = currentUser?.emailVerified; + if (isEmailVerified) { + setIsEmailVerified(isEmailVerified); + } else { + try { + const userQuery = new Parse.Query(Parse.User); + const user = await userQuery.get(currentUser.objectId, { + sessionToken: localStorage.getItem("accesstoken") + }); + if (user) { + isEmailVerified = user?.get("emailVerified"); + setIsEmailVerified(isEmailVerified); + } + } catch (e) { + setHandleError("Error: Something went wrong!"); + } + } + } if (documentData.length > 0) { const checkDocIdExist = documentData[0].AuditTrail && @@ -1179,6 +1252,18 @@ function PdfRequestFiles() { headMsg="Document Expired!" bodyMssg={`This document expired on ${expiredDate} and is no longer available to sign.`} /> + {!isEmailVerified && ( + + )} { fetchTenantDetails(); diff --git a/apps/OpenSign/src/pages/SignyourselfPdf.js b/apps/OpenSign/src/pages/SignyourselfPdf.js index 2b276d776..6ad106d93 100644 --- a/apps/OpenSign/src/pages/SignyourselfPdf.js +++ b/apps/OpenSign/src/pages/SignyourselfPdf.js @@ -1,6 +1,7 @@ import React, { useState, useRef, useEffect } from "react"; import { PDFDocument } from "pdf-lib"; import "../styles/signature.css"; +import Parse from "parse"; import { isEnableSubscription, themeColor } from "../constant/const"; import axios from "axios"; import Loader from "../primitives/LoaderWithMsg"; @@ -31,7 +32,8 @@ import { checkIsSubscribed, convertPdfArrayBuffer, fetchImageBase64, - changeImageWH + changeImageWH, + handleSendOTP } from "../constant/Utils"; import { useParams } from "react-router-dom"; import Tour from "reactour"; @@ -44,6 +46,7 @@ import TourContentWithBtn from "../primitives/TourContentWithBtn"; import Title from "../components/Title"; import ModalUi from "../primitives/ModalUi"; import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption"; +import VerifyEmail from "../components/pdf/VerifyEmail"; //For signYourself inProgress section signer can add sign and complete doc sign. function SignYourSelf() { @@ -91,6 +94,7 @@ function SignYourSelf() { const [containerWH, setContainerWH] = useState({}); const [isPageCopy, setIsPageCopy] = useState(false); const [selectWidgetId, setSelectWidgetId] = useState(""); + const [otpLoader, setOtpLoader] = useState(false); const [showAlreadySignDoc, setShowAlreadySignDoc] = useState({ status: false }); @@ -107,6 +111,9 @@ function SignYourSelf() { const [isCompleted, setIsCompleted] = useState(false); const [pdfArrayBuffer, setPdfArrayBuffer] = useState(""); const [activeMailAdapter, setActiveMailAdapter] = useState(""); + const [isEmailVerified, setIsEmailVerified] = useState(true); + const [isVerifyModal, setIsVerifyModal] = useState(false); + const [otp, setOtp] = useState(""); const divRef = useRef(null); const nodeRef = useRef(null); const [, drop] = useDrop({ @@ -226,6 +233,29 @@ function SignYourSelf() { setSignBtnPosition([]); } } + + if (!isCompleted) { + //check current user email verified or not + const currentUser = JSON.parse(JSON.stringify(Parse.User.current())); + let isEmailVerified; + isEmailVerified = currentUser?.emailVerified; + if (isEmailVerified) { + setIsEmailVerified(isEmailVerified); + } else { + try { + const userQuery = new Parse.Query(Parse.User); + const user = await userQuery.get(currentUser.objectId, { + sessionToken: localStorage.getItem("accesstoken") + }); + if (user) { + isEmailVerified = user?.get("emailVerified"); + setIsEmailVerified(isEmailVerified); + } + } catch (e) { + setHandleError("Error: Something went wrong!"); + } + } + } } else if ( documentData === "Error: Something went wrong!" || (documentData.result && documentData.result.error) @@ -533,6 +563,44 @@ function SignYourSelf() { setSelectWidgetId(key); setSignKey(key); }; + + //`handleResend` function is used to resend otp for email verification + const handleResend = async (e) => { + e.preventDefault(); + setOtpLoader(true); + await handleSendOTP(Parse.User.current().getEmail()); + setOtpLoader(false); + alert("OTP sent on you email"); + }; + //`handleVerifyEmail` function is used to verify email with otp + 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); + // handleRecipientSign(); + } catch (error) { + alert(error.message); + } finally { + setOtpLoader(false); + } + }; + //`handleVerifyBtn` function is used to send otp on user mail + const handleVerifyBtn = async () => { + setIsVerifyModal(true); + await handleSendOTP(Parse.User.current().getEmail()); + }; //function for send placeholder's co-ordinate(x,y) position embed signature url or stamp url async function embedWidgetsData() { let showAlert = false; @@ -1037,6 +1105,18 @@ function SignYourSelf() { )}
+ {!isEmailVerified && ( + + )} {/* this component used for UI interaction and show their functionality */} {pdfLoadFail && !checkTourStatus && ( { e.preventDefault(); @@ -185,27 +202,15 @@ function UserProfile() { const handleDisableDocId = () => { setIsDisableDocId((prevChecked) => !prevChecked); }; + //`handleVerifyBtn` function is used to send otp on user mail const handleVerifyBtn = async () => { setIsVerifyModal(true); - await handleSendOTP(); + await handleSendOTP(Parse.User.current().getEmail()); }; 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); - } - }; - + //`handleVerifyEmail` function is used to verify email with otp const handleVerifyEmail = async (e) => { e.preventDefault(); setOtpLoader(true); @@ -228,7 +233,8 @@ function UserProfile() { setOtpLoader(false); } }; - const handleReset = async (e) => { + //function to use resend otp for email verification + const handleResend = async (e) => { e.preventDefault(); setOtpLoader(true); await handleSendOTP(); @@ -497,6 +503,7 @@ function UserProfile() {