Revert "v2.39.0 (#2180)"

This reverts commit 1e228c86c3.
This commit is contained in:
Raktima
2026-05-25 17:24:36 +05:30
committed by GitHub
parent 1e228c86c3
commit 7b4d0bf052
92 changed files with 5372 additions and 8680 deletions
@@ -17,22 +17,6 @@ import { SignPdf } from '@signpdf/signpdf';
import { P12Signer } from '@signpdf/signer-p12';
import { buildDownloadFilename, parseUploadFile } from '../../../utils/fileUtils.js';
import sendMailWithAttachment from '../sendMailWithAttachment.js';
import sendSystemMail from '../sendSystemMail.js';
import {
COMPLETION_ACTIVITIES,
findPlaceholderIndex,
findPendingPriorSigner,
isCompletionRelevant,
} from '../../../utils/workflowUtils.js';
// Audit-trail activities that count toward document completion. The free
// build only counts 'Signed'; EE additionally counts 'Approved'.
// A placeholder participates in completion unless it is a prefill entry.
// EE additionally excludes viewers (who never act on the document).
// Strict-order gating: returns the signerObjId of the prior placeholder
// still pending, or null when the strict-order requirement is satisfied.
const serverUrl = cloudServerUrl; // process.env.SERVER_URL;
const APPID = serverAppId;
@@ -78,24 +62,13 @@ async function uploadFile(pdfName, filepath) {
}
// `updateDoc` is used to update signedUrl, AuditTrail, Iscompleted in document
async function updateDoc(
docId,
url,
userId,
ipAddress,
data,
className,
sign,
documentHash,
activity
) {
async function updateDoc(docId, url, userId, ipAddress, data, className, sign, documentHash) {
try {
const UserPtr = { __type: 'Pointer', className: className, objectId: userId };
const auditActivity = 'Signed';
const obj = {
UserPtr: UserPtr,
SignedUrl: url,
Activity: auditActivity,
Activity: 'Signed',
ipAddress: ipAddress,
SignedOn: new Date(),
Signature: sign,
@@ -115,14 +88,13 @@ async function updateDoc(
updateAuditTrail = [obj];
}
// Count both Signed and Approved entries; only signer/approver
// placeholders count toward completion (viewers and prefill excluded).
const auditTrail = updateAuditTrail.filter(x => COMPLETION_ACTIVITIES.includes(x.Activity));
const auditTrail = updateAuditTrail.filter(x => x.Activity === 'Signed');
let isCompleted = false;
if (data.Signers && data.Signers.length > 0) {
const completionRelevant =
data.Placeholders?.length > 0 ? data.Placeholders.filter(isCompletionRelevant) : [];
if (auditTrail.length >= completionRelevant.length && completionRelevant.length > 0) {
//'removePrefill' is used to remove prefill role from placeholders filed then compare length to change status of document
const removePrefill =
data.Placeholders.length > 0 && data.Placeholders.filter(x => x.Role !== 'prefill');
if (auditTrail.length === removePrefill?.length) {
isCompleted = true;
}
} else {
@@ -152,11 +124,10 @@ async function sendNotifyMail(doc, signUser, mailProvider, publicUrl) {
const logo =
"<img src='https://qikinnovation.ams3.digitaloceanspaces.com/logo.png' height='50' style='padding:20px'/>";
const auditTrailCount =
doc?.AuditTrail?.filter(x => COMPLETION_ACTIVITIES.includes(x.Activity))?.length || 0;
const completionRelevant =
doc?.Placeholders?.length > 0 ? doc.Placeholders.filter(isCompletionRelevant) : [];
const signersCount = completionRelevant?.length;
const auditTrailCount = doc?.AuditTrail?.filter(x => x.Activity === 'Signed')?.length || 0;
const removePrefill =
doc?.Placeholders?.length > 0 && doc?.Placeholders?.filter(x => x?.Role !== 'prefill');
const signersCount = removePrefill?.length;
const remainingSign = signersCount - auditTrailCount;
if (remainingSign > 1 && doc?.NotifyOnSignatures) {
const sender = doc.ExtUserPtr;
@@ -183,7 +154,7 @@ async function sendNotifyMail(doc, signUser, mailProvider, publicUrl) {
html: body,
mailProvider: mailProvider,
};
await sendSystemMail({ params });
await axios.post(serverUrl + '/functions/sendmailv3', params, { headers });
}
} catch (err) {
console.log('err in sendnotifymail', err);
@@ -268,7 +239,6 @@ async function sendCompletedMail(obj) {
body = replaceVar.body;
}
const Bcc = doc?.Bcc?.length > 0 ? doc.Bcc.map(x => x.Email) : [];
const Cc = doc?.Cc?.length > 0 ? doc.Cc.map(x => x.Email) : [];
const updatedBcc = doc?.SenderMail ? [...Bcc, doc?.SenderMail] : Bcc;
const formatId = doc?.ExtUserPtr?.DownloadFilenameFormat;
const filename = pdfName?.length > 100 ? pdfName?.slice(0, 100) : pdfName;
@@ -288,7 +258,6 @@ async function sendCompletedMail(obj) {
html: body,
mailProvider: obj.mailProvider,
bcc: updatedBcc?.length > 0 ? updatedBcc : '',
cc: Cc?.length > 0 ? Cc : '',
certificatePath: `./exports/signed_certificate_${doc.objectId}.pdf`,
filename: docName,
};
@@ -391,14 +360,11 @@ async function PDF(req) {
const isCustomMail = req.params.isCustomCompletionMail || false;
const mailProvider = req.params.mailProvider || '';
const sign = req.params.signature || '';
const auditActivity = 'Signed';
const publicUrl = req.headers.public_url;
// below bode is used to get info of docId
const docQuery = new Parse.Query('contracts_Document');
docQuery.include('ExtUserPtr,Signers,ExtUserPtr.TenantId,Bcc,Cc,CreatedBy');
docQuery.include('ExtUserPtr,Signers,ExtUserPtr.TenantId,Bcc,CreatedBy');
docQuery.equalTo('objectId', docId);
docQuery.notEqualTo('IsDeclined', true);
docQuery.notEqualTo('IsArchive', true);
const resDoc = await docQuery.first({ useMasterKey: true });
if (!resDoc) {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.');
@@ -425,27 +391,7 @@ async function PDF(req) {
className = 'contracts_Users';
signUser = _resDoc.ExtUserPtr;
}
// Strict-order gating: when both `SendinOrder` and `SendInOrderStrict`
// are enabled the document creator wants the signing flow locked to a
// strict sequence — a signer/approver may only act once every previous
// signer/approver placeholder has a Signed/Approved audit entry. We
// skip this check entirely for the document owner (className=Users)
// because owners never sign through this path.
if (reqUserId && _resDoc?.SendinOrder === true && _resDoc?.SendInOrderStrict === true) {
const placeholders = Array.isArray(_resDoc?.Placeholders)
? _resDoc.Placeholders.filter(p => p?.Role !== 'prefill')
: [];
const myIdx = findPlaceholderIndex(placeholders, reqUserId);
if (myIdx > 0) {
const pendingId = findPendingPriorSigner(placeholders, myIdx, _resDoc?.AuditTrail);
if (pendingId) {
throw new Parse.Error(
Parse.Error.OPERATION_FORBIDDEN,
'Strict signing order is enabled — please wait for the previous signers to complete their action before signing.'
);
}
}
}
const username = signUser.Name;
const userEmail = signUser.Email;
if (req.params.pdfFile) {
@@ -462,7 +408,7 @@ async function PDF(req) {
const P12Buffer = Buffer.from(pfxFile, 'base64');
fs.writeFileSync(pfxname, P12Buffer);
const UserPtr = { __type: 'Pointer', className: className, objectId: signUser.objectId };
const obj = { UserPtr: UserPtr, SignedUrl: '', Activity: auditActivity, ipAddress: userIP };
const obj = { UserPtr: UserPtr, SignedUrl: '', Activity: 'Signed', ipAddress: userIP };
let updateAuditTrail;
if (_resDoc.AuditTrail && _resDoc.AuditTrail.length > 0) {
updateAuditTrail = [..._resDoc.AuditTrail, obj];
@@ -470,17 +416,14 @@ async function PDF(req) {
updateAuditTrail = [obj];
}
// Both Signed and Approved entries count toward completion. Only
// signer/approver placeholders are counted; viewers and prefill are
// excluded.
const auditTrail = updateAuditTrail.filter(x => COMPLETION_ACTIVITIES.includes(x.Activity));
const auditTrail = updateAuditTrail.filter(x => x.Activity === 'Signed');
let isCompleted = false;
if (_resDoc.Signers && _resDoc.Signers.length > 0) {
const completionRelevant =
_resDoc?.Placeholders?.length > 0
? _resDoc.Placeholders.filter(isCompletionRelevant)
: [];
if (auditTrail.length >= completionRelevant.length && completionRelevant.length > 0) {
const removePrefill =
_resDoc?.Placeholders?.length > 0 &&
_resDoc?.Placeholders?.filter(x => x?.Role !== 'prefill');
if (auditTrail.length === removePrefill?.length) {
// if (auditTrail.length === _resDoc.Signers.length) {
isCompleted = true;
}
} else {
@@ -533,8 +476,7 @@ async function PDF(req) {
_resDoc, // auditTrail, signers, etc data
className, // className based on flow
sign, // sign base64
isCompleted ? documentHash : undefined,
auditActivity
isCompleted ? documentHash : undefined
);
sendNotifyMail(_resDoc, signUser, mailProvider, publicUrl);
saveFileUsage(pdfSize, data.imageUrl, _resDoc?.CreatedBy?.objectId);