mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-20 22:52:39 +02:00
feat: add disable OTP feature to directly sign document without verification
This commit is contained in:
@@ -7,99 +7,101 @@ export default async function callWebhook(request) {
|
||||
const contactId = request.params.contactId;
|
||||
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
|
||||
const appId = process.env.APP_ID;
|
||||
const userRes = await axios.get(serverUrl + '/users/me', {
|
||||
headers: {
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
||||
},
|
||||
});
|
||||
|
||||
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]);
|
||||
try {
|
||||
const docQuery = new Parse.Query('contracts_Document');
|
||||
const docRes = await docQuery.get(docId, { useMasterKey: true });
|
||||
const isDisableOTP = docRes?.get('IsDisableOTP') || false;
|
||||
let userId;
|
||||
if (!isDisableOTP) {
|
||||
const userRes = await axios.get(serverUrl + '/users/me', {
|
||||
headers: {
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
||||
},
|
||||
});
|
||||
userId = userRes.data && userRes.data.objectId;
|
||||
}
|
||||
if (isDisableOTP || userId) {
|
||||
if (event === 'viewed' && contactId) {
|
||||
if (docRes) {
|
||||
const _docRes = docRes.toJSON();
|
||||
const userPtr = {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Contactbook',
|
||||
objectId: contactId,
|
||||
};
|
||||
const date = new Date().toISOString();
|
||||
const obj = {
|
||||
UserPtr: userPtr,
|
||||
SignedUrl: _docRes.SignedUrl,
|
||||
Activity: 'Viewed',
|
||||
ipAddress: request.headers['x-real-ip'],
|
||||
ViewedOn: date,
|
||||
};
|
||||
const isUserExist = _docRes?.AuditTrail?.some(
|
||||
x => x.UserPtr.objectId === contactId && x?.ViewedOn
|
||||
);
|
||||
if (!isUserExist) {
|
||||
const updateDoc = new Parse.Object('contracts_Document');
|
||||
updateDoc.id = docRes.id;
|
||||
if (_docRes?.AuditTrail && _docRes?.AuditTrail?.length > 0) {
|
||||
updateDoc.set('AuditTrail', [..._docRes?.AuditTrail, obj]);
|
||||
} else {
|
||||
updateDoc.set('AuditTrail', [obj]);
|
||||
}
|
||||
await updateDoc.save(null, { useMasterKey: true });
|
||||
}
|
||||
await updateDoc.save(null, { useMasterKey: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
const docQuery = new Parse.Query('contracts_Document');
|
||||
const resDoc = await docQuery.get(docId, { useMasterKey: true });
|
||||
const extendcls = new Parse.Query('contracts_Users');
|
||||
extendcls.equalTo('objectId', resDoc.get('ExtUserPtr')?.id);
|
||||
// extendcls.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: userId });
|
||||
const res = await extendcls.first({ useMasterKey: true });
|
||||
if (res) {
|
||||
const extUser = JSON.parse(JSON.stringify(res));
|
||||
if (extUser?.Webhook) {
|
||||
const params = {
|
||||
event: event,
|
||||
...body,
|
||||
};
|
||||
await axios
|
||||
.post(extUser?.Webhook, params, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then(res => {
|
||||
try {
|
||||
// console.log('res ', res);
|
||||
const webhook = new Parse.Object('contracts_Webhook');
|
||||
webhook.set('Log', res?.status);
|
||||
webhook.set('UserId', {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: userId,
|
||||
});
|
||||
webhook.save(null, { useMasterKey: true });
|
||||
} catch (err) {
|
||||
console.log('err save in contracts_Webhook', err.message);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('Err send data to webhook', err.message);
|
||||
try {
|
||||
const webhook = new Parse.Object('contracts_Webhook');
|
||||
webhook.set('Log', err?.status);
|
||||
webhook.set('UserId', {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: userId,
|
||||
});
|
||||
webhook.save(null, { useMasterKey: true });
|
||||
} catch (err) {
|
||||
console.log('err save in contracts_Webhook', err.message);
|
||||
}
|
||||
});
|
||||
const extendcls = new Parse.Query('contracts_Users');
|
||||
extendcls.equalTo('objectId', docRes.get('ExtUserPtr')?.id);
|
||||
// extendcls.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: userId });
|
||||
const resExt = await extendcls.first({ useMasterKey: true });
|
||||
if (resExt) {
|
||||
const extUser = JSON.parse(JSON.stringify(resExt));
|
||||
if (extUser?.Webhook) {
|
||||
const params = { event: event, ...body };
|
||||
await axios
|
||||
.post(extUser?.Webhook, params, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then(res => {
|
||||
try {
|
||||
const webhook = new Parse.Object('contracts_Webhook');
|
||||
webhook.set('Log', res?.status);
|
||||
webhook.set('UserId', {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: userId,
|
||||
});
|
||||
webhook.save(null, { useMasterKey: true });
|
||||
} catch (err) {
|
||||
console.log('err save in contracts_Webhook', err.message);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('Err send data to webhook', err.message);
|
||||
try {
|
||||
const webhook = new Parse.Object('contracts_Webhook');
|
||||
webhook.set('Log', err?.status);
|
||||
webhook.set('UserId', {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: userId,
|
||||
});
|
||||
webhook.save(null, { useMasterKey: true });
|
||||
} catch (err) {
|
||||
console.log('err save in contracts_Webhook', err.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
return { message: 'webhook called!' };
|
||||
}
|
||||
return { message: 'webhook called!' };
|
||||
} else {
|
||||
return { message: 'User not found!' };
|
||||
}
|
||||
} else {
|
||||
return { message: 'User not found!' };
|
||||
} catch (err) {
|
||||
console.log('Err in callwebhook', err);
|
||||
return { message: 'Something went wrong!' };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,6 +199,7 @@ export default async function createBatchDocs(request) {
|
||||
TimeToCompleteDays: x.TimeToCompleteDays || 15,
|
||||
OriginIp: Ip,
|
||||
DocSentAt: { __type: 'Date', iso: isoDate },
|
||||
IsDisableOTP: x?.IsDisableOTP || false,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
export default async function getContact(request) {
|
||||
const contactId = request.params.contactId;
|
||||
try {
|
||||
const contactCls = new Parse.Query('contracts_Contactbook');
|
||||
const contactRes = await contactCls.get(contactId, { useMasterKey: true });
|
||||
return contactRes;
|
||||
} catch (err) {
|
||||
console.log('Err in contracts_Contactbook class ', err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,7 @@ export default async function getDocument(request) {
|
||||
const docId = request.params.docId;
|
||||
|
||||
try {
|
||||
const userRes = await axios.get(serverUrl + '/users/me', {
|
||||
headers: {
|
||||
'X-Parse-Application-Id': process.env.APP_ID,
|
||||
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
||||
},
|
||||
});
|
||||
const userId = userRes.data && userRes.data.objectId;
|
||||
if (docId && userId) {
|
||||
if (docId) {
|
||||
try {
|
||||
const query = new Parse.Query('contracts_Document');
|
||||
query.equalTo('objectId', docId);
|
||||
@@ -26,11 +19,32 @@ export default async function getDocument(request) {
|
||||
query.notEqualTo('IsArchive', true);
|
||||
const res = await query.first({ useMasterKey: true });
|
||||
if (res) {
|
||||
const acl = res.getACL();
|
||||
if (acl && acl.getReadAccess(userId)) {
|
||||
const IsDisableOTP = res?.get('IsDisableOTP') || false;
|
||||
if (IsDisableOTP) {
|
||||
return res;
|
||||
} else {
|
||||
return { error: "You don't have access of this document!" };
|
||||
if (request?.headers?.['sessiontoken']) {
|
||||
try {
|
||||
const userRes = await axios.get(serverUrl + '/users/me', {
|
||||
headers: {
|
||||
'X-Parse-Application-Id': process.env.APP_ID,
|
||||
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
||||
},
|
||||
});
|
||||
const userId = userRes.data && userRes.data?.objectId;
|
||||
const acl = res.getACL();
|
||||
if (userId && acl && acl.getReadAccess(userId)) {
|
||||
return res;
|
||||
} else {
|
||||
return { error: "You don't have access of this document!" };
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err user in not authenticated', err);
|
||||
return { error: "You don't have access of this document!" };
|
||||
}
|
||||
} else {
|
||||
return { error: "You don't have access of this document!" };
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return { error: "You don't have access of this document!" };
|
||||
|
||||
@@ -28,15 +28,42 @@ export default function getPresignedUrl(url) {
|
||||
|
||||
export async function getSignedUrl(request) {
|
||||
try {
|
||||
const docId = request.params.docId || '';
|
||||
const url = request.params.url;
|
||||
if (!request?.user) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||
if (docId) {
|
||||
try {
|
||||
const query = new Parse.Query('contracts_Document');
|
||||
query.equalTo('objectId', docId);
|
||||
query.equalTo('IsDisableOTP', true);
|
||||
query.include('CreatedBy');
|
||||
query.include('Signers');
|
||||
query.include('AuditTrail.UserPtr');
|
||||
query.include('Placeholders');
|
||||
query.include('DeclineBy');
|
||||
query.notEqualTo('IsArchive', true);
|
||||
const res = await query.first({ useMasterKey: true });
|
||||
if (res) {
|
||||
if (useLocal !== 'true') {
|
||||
const presignedUrl = getPresignedUrl(url);
|
||||
return presignedUrl;
|
||||
} else {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Err in presigned url', err);
|
||||
throw err;
|
||||
}
|
||||
} else {
|
||||
if (useLocal !== 'true') {
|
||||
const presignedUrl = getPresignedUrl(url);
|
||||
return presignedUrl;
|
||||
if (!request?.user) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||
} else {
|
||||
return url;
|
||||
if (useLocal !== 'true') {
|
||||
const presignedUrl = getPresignedUrl(url);
|
||||
return presignedUrl;
|
||||
} else {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@@ -50,37 +50,24 @@ export default async function getSubscription(request) {
|
||||
}
|
||||
} else if (contactId) {
|
||||
try {
|
||||
const userRes = await axios.get(serverUrl + '/users/me', {
|
||||
headers: {
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
||||
},
|
||||
});
|
||||
|
||||
const userId = userRes.data && userRes.data.objectId;
|
||||
if (userId) {
|
||||
const contactCls = new Parse.Query('contracts_Contactbook');
|
||||
const contactUser = await contactCls.get(contactId, { useMasterKey: true });
|
||||
if (contactUser) {
|
||||
const subscriptionCls = new Parse.Query('contracts_Subscriptions');
|
||||
subscriptionCls.equalTo('TenantId', {
|
||||
__type: 'Pointer',
|
||||
className: 'partners_Tenant',
|
||||
objectId: contactUser.get('TenantId').id,
|
||||
});
|
||||
subscriptionCls.descending('createdAt');
|
||||
const subcripitions = await subscriptionCls.first({ useMasterKey: true });
|
||||
|
||||
if (subcripitions) {
|
||||
const _subcripitions = JSON.parse(JSON.stringify(subcripitions));
|
||||
if (_subcripitions.PlanCode === 'freeplan') {
|
||||
return { status: 'success', result: { isSubscribed: false, plan: 'freeplan' } };
|
||||
} else if (_subcripitions?.Next_billing_date?.iso) {
|
||||
if (new Date(_subcripitions.Next_billing_date.iso) > new Date()) {
|
||||
return { status: 'success', result: { isSubscribed: true } };
|
||||
} else {
|
||||
return { status: 'success', result: { isSubscribed: false } };
|
||||
}
|
||||
const contactCls = new Parse.Query('contracts_Contactbook');
|
||||
const contactUser = await contactCls.get(contactId, { useMasterKey: true });
|
||||
if (contactUser) {
|
||||
const subscriptionCls = new Parse.Query('contracts_Subscriptions');
|
||||
subscriptionCls.equalTo('TenantId', {
|
||||
__type: 'Pointer',
|
||||
className: 'partners_Tenant',
|
||||
objectId: contactUser.get('TenantId').id,
|
||||
});
|
||||
subscriptionCls.descending('createdAt');
|
||||
const subcripitions = await subscriptionCls.first({ useMasterKey: true });
|
||||
if (subcripitions) {
|
||||
const _subcripitions = JSON.parse(JSON.stringify(subcripitions));
|
||||
if (_subcripitions.PlanCode === 'freeplan') {
|
||||
return { status: 'success', result: { isSubscribed: false, plan: 'freeplan' } };
|
||||
} else if (_subcripitions?.Next_billing_date?.iso) {
|
||||
if (new Date(_subcripitions.Next_billing_date.iso) > new Date()) {
|
||||
return { status: 'success', result: { isSubscribed: true } };
|
||||
} else {
|
||||
return { status: 'success', result: { isSubscribed: false } };
|
||||
}
|
||||
@@ -88,10 +75,10 @@ export default async function getSubscription(request) {
|
||||
return { status: 'success', result: { isSubscribed: false } };
|
||||
}
|
||||
} else {
|
||||
return { status: 'error', result: 'User not found!' };
|
||||
return { status: 'success', result: { isSubscribed: false } };
|
||||
}
|
||||
} else {
|
||||
return { status: 'error', result: 'Invalid session token!' };
|
||||
return { status: 'error', result: 'User not found!' };
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Err in get subscription2', err.message);
|
||||
|
||||
@@ -32,6 +32,7 @@ export default async function GenerateCertificate(docDetails) {
|
||||
const OriginIp = docDetails?.OriginIp || '';
|
||||
const company = docDetails?.ExtUserPtr?.Company || '';
|
||||
const createdAt = docDetails?.DocSentAt?.iso || docDetails.createdAt;
|
||||
const isDisableOTP = docDetails?.IsDisableOTP || false;
|
||||
const auditTrail =
|
||||
docDetails?.Signers?.length > 0
|
||||
? docDetails.AuditTrail.map(x => {
|
||||
@@ -348,22 +349,22 @@ export default async function GenerateCertificate(docDetails) {
|
||||
font: timesRomanFont,
|
||||
color: textValueColor,
|
||||
});
|
||||
page.drawText('Security level :', {
|
||||
x: half + 55,
|
||||
y: yPosition4 + 10,
|
||||
size: timeText,
|
||||
font: timesRomanFont,
|
||||
color: textKeyColor,
|
||||
});
|
||||
|
||||
page.drawText(`Email, OTP Auth`, {
|
||||
x: half + 125,
|
||||
y: yPosition4 + 10,
|
||||
size: timeText,
|
||||
font: timesRomanFont,
|
||||
color: textValueColor,
|
||||
});
|
||||
|
||||
if (!isDisableOTP) {
|
||||
page.drawText('Security level :', {
|
||||
x: half + 55,
|
||||
y: yPosition4 + 10,
|
||||
size: timeText,
|
||||
font: timesRomanFont,
|
||||
color: textKeyColor,
|
||||
});
|
||||
page.drawText('Email, OTP Auth', {
|
||||
x: half + 125,
|
||||
y: yPosition4 + 10,
|
||||
size: timeText,
|
||||
font: timesRomanFont,
|
||||
color: textValueColor,
|
||||
});
|
||||
}
|
||||
page.drawText('Signature :', {
|
||||
x: 30,
|
||||
y: yPosition5,
|
||||
|
||||
@@ -272,157 +272,160 @@ const sendMailsaveCertifcate = async (doc, P12Buffer, url, isCustomMail, mailPro
|
||||
*/
|
||||
async function PDF(req) {
|
||||
try {
|
||||
if (!req?.user) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||
const userIP = req.headers['x-real-ip']; // client IPaddress
|
||||
const docId = req.params.docId;
|
||||
const reqUserId = req.params.userId;
|
||||
const isCustomMail = req.params.isCustomCompletionMail || false;
|
||||
const mailProvider = req.params.mailProvider || '';
|
||||
const sign = req.params.signature || '';
|
||||
// below bode is used to get info of docId
|
||||
const docQuery = new Parse.Query('contracts_Document');
|
||||
docQuery.include('ExtUserPtr,Signers');
|
||||
docQuery.equalTo('objectId', docId);
|
||||
const resDoc = await docQuery.first({ useMasterKey: true });
|
||||
if (!resDoc) {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.');
|
||||
}
|
||||
const IsDisableOTP = resDoc?.get('IsDisableOTP') || false;
|
||||
// if `IsDisableOTP` is true then we don't have to check authentication
|
||||
if (!IsDisableOTP) {
|
||||
if (!req?.user) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||
}
|
||||
}
|
||||
const _resDoc = resDoc?.toJSON();
|
||||
let signUser;
|
||||
let className;
|
||||
// `reqUserId` is send throught pdfrequest signing flow
|
||||
if (reqUserId) {
|
||||
// to get contracts_Contactbook details for currentuser from reqUserId
|
||||
const _contractUser = _resDoc.Signers.find(x => x.objectId === reqUserId);
|
||||
if (_contractUser) {
|
||||
signUser = _contractUser;
|
||||
className = 'contracts_Contactbook';
|
||||
}
|
||||
} else {
|
||||
const userIP = req.headers['x-real-ip']; // client IPaddress
|
||||
const docId = req.params.docId;
|
||||
const reqUserId = req.params.userId;
|
||||
const isCustomMail = req.params.isCustomCompletionMail || false;
|
||||
const mailProvider = req.params.mailProvider || '';
|
||||
const sign = req.params.signature || '';
|
||||
// below bode is used to get info of docId
|
||||
const docQuery = new Parse.Query('contracts_Document');
|
||||
docQuery.include('ExtUserPtr,Signers');
|
||||
docQuery.equalTo('objectId', docId);
|
||||
const resDoc = await docQuery.first({ useMasterKey: true });
|
||||
if (!resDoc) {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.');
|
||||
}
|
||||
const _resDoc = resDoc?.toJSON();
|
||||
let signUser;
|
||||
let className;
|
||||
// `reqUserId` is send throught pdfrequest signing flow
|
||||
if (reqUserId) {
|
||||
// to get contracts_Contactbook details for currentuser from reqUserId
|
||||
const _contractUser = _resDoc.Signers.find(x => x.objectId === reqUserId);
|
||||
if (_contractUser) {
|
||||
signUser = _contractUser;
|
||||
className = 'contracts_Contactbook';
|
||||
}
|
||||
className = 'contracts_Users';
|
||||
signUser = _resDoc.ExtUserPtr;
|
||||
}
|
||||
|
||||
const username = signUser.Name;
|
||||
const userEmail = signUser.Email;
|
||||
if (req.params.pdfFile) {
|
||||
// `PdfBuffer` used to create buffer from pdf file
|
||||
let PdfBuffer = Buffer.from(req.params.pdfFile, 'base64');
|
||||
// `P12Buffer` used to create buffer from p12 certificate
|
||||
const pfxFile = process.env.PFX_BASE64;
|
||||
// const P12Buffer = fs.readFileSync();
|
||||
const P12Buffer = Buffer.from(pfxFile, 'base64');
|
||||
const p12Cert = new P12Signer(P12Buffer, { passphrase: process.env.PASS_PHRASE || null });
|
||||
const UserPtr = { __type: 'Pointer', className: className, objectId: signUser.objectId };
|
||||
const obj = { UserPtr: UserPtr, SignedUrl: '', Activity: 'Signed', ipAddress: userIP };
|
||||
let updateAuditTrail;
|
||||
if (_resDoc.AuditTrail && _resDoc.AuditTrail.length > 0) {
|
||||
updateAuditTrail = [..._resDoc.AuditTrail, obj];
|
||||
} else {
|
||||
className = 'contracts_Users';
|
||||
signUser = _resDoc.ExtUserPtr;
|
||||
updateAuditTrail = [obj];
|
||||
}
|
||||
|
||||
const username = signUser.Name;
|
||||
const userEmail = signUser.Email;
|
||||
if (req.params.pdfFile) {
|
||||
// `PdfBuffer` used to create buffer from pdf file
|
||||
let PdfBuffer = Buffer.from(req.params.pdfFile, 'base64');
|
||||
// `P12Buffer` used to create buffer from p12 certificate
|
||||
const pfxFile = process.env.PFX_BASE64;
|
||||
// const P12Buffer = fs.readFileSync();
|
||||
const P12Buffer = Buffer.from(pfxFile, 'base64');
|
||||
const p12Cert = new P12Signer(P12Buffer, { passphrase: process.env.PASS_PHRASE || null });
|
||||
const UserPtr = { __type: 'Pointer', className: className, objectId: signUser.objectId };
|
||||
const obj = { UserPtr: UserPtr, SignedUrl: '', Activity: 'Signed', ipAddress: userIP };
|
||||
let updateAuditTrail;
|
||||
if (_resDoc.AuditTrail && _resDoc.AuditTrail.length > 0) {
|
||||
updateAuditTrail = [..._resDoc.AuditTrail, obj];
|
||||
} else {
|
||||
updateAuditTrail = [obj];
|
||||
}
|
||||
|
||||
const auditTrail = updateAuditTrail.filter(x => x.Activity === 'Signed');
|
||||
let isCompleted = false;
|
||||
if (_resDoc.Signers && _resDoc.Signers.length > 0) {
|
||||
if (auditTrail.length === _resDoc.Signers.length) {
|
||||
isCompleted = true;
|
||||
}
|
||||
} else {
|
||||
const auditTrail = updateAuditTrail.filter(x => x.Activity === 'Signed');
|
||||
let isCompleted = false;
|
||||
if (_resDoc.Signers && _resDoc.Signers.length > 0) {
|
||||
if (auditTrail.length === _resDoc.Signers.length) {
|
||||
isCompleted = true;
|
||||
}
|
||||
const randomNumber = Math.floor(Math.random() * 5000);
|
||||
const name = `exported_file_${randomNumber}.pdf`;
|
||||
const pdfName = `./exports/${name}`;
|
||||
let pdfSize = PdfBuffer.length;
|
||||
if (isCompleted) {
|
||||
const signersName = _resDoc.Signers?.map(x => x.Name + ' <' + x.Email + '>');
|
||||
if (signersName && signersName.length > 0) {
|
||||
// `pdflibAddPlaceholder` is used to add code of only digitial sign without widget
|
||||
const pdfDoc = await PDFDocument.load(PdfBuffer);
|
||||
pdflibAddPlaceholder({
|
||||
pdfDoc: pdfDoc,
|
||||
reason: 'Digitally signed by OpenSign for ' + signersName?.join(', '),
|
||||
location: 'n/a',
|
||||
name: eSignName,
|
||||
contactInfo: eSigncontact,
|
||||
signatureLength: 15000,
|
||||
});
|
||||
const pdfWithPlaceholderBytes = await pdfDoc.save();
|
||||
PdfBuffer = Buffer.from(pdfWithPlaceholderBytes);
|
||||
} else {
|
||||
// `pdflibAddPlaceholder` is used to add code of only digitial sign without widget (signyourself)
|
||||
const pdfDoc = await PDFDocument.load(PdfBuffer);
|
||||
pdflibAddPlaceholder({
|
||||
pdfDoc: pdfDoc,
|
||||
reason: 'Digitally signed by OpenSign for ' + username + ' <' + userEmail + '>',
|
||||
location: 'n/a',
|
||||
name: eSignName,
|
||||
contactInfo: eSigncontact,
|
||||
signatureLength: 15000,
|
||||
});
|
||||
const pdfWithPlaceholderBytes = await pdfDoc.save();
|
||||
PdfBuffer = Buffer.from(pdfWithPlaceholderBytes);
|
||||
}
|
||||
//`new signPDF` create new instance of pdfBuffer and p12Buffer
|
||||
const OBJ = new SignPdf();
|
||||
// `signedDocs` is used to signpdf digitally
|
||||
const signedDocs = await OBJ.sign(PdfBuffer, p12Cert);
|
||||
|
||||
//`saveUrl` is used to save signed pdf in exports folder
|
||||
const saveUrl = fs.writeFileSync(pdfName, signedDocs);
|
||||
pdfSize = signedDocs.length;
|
||||
} else {
|
||||
//`saveUrl` is used to save signed pdf in exports folder
|
||||
const saveUrl = fs.writeFileSync(pdfName, PdfBuffer);
|
||||
pdfSize = PdfBuffer.length;
|
||||
}
|
||||
|
||||
// `uploadFile` is used to upload pdf to aws s3 and get it's url
|
||||
const data = await uploadFile(name, pdfName);
|
||||
|
||||
if (data && data.imageUrl) {
|
||||
// `axios` is used to update signed pdf url in contracts_Document classes for given DocId
|
||||
const updatedDoc = await updateDoc(
|
||||
req.params.docId, //docId
|
||||
data.imageUrl, // url
|
||||
signUser.objectId, // userID
|
||||
userIP, // client ipAddress,
|
||||
_resDoc, // auditTrail, signers, etc data
|
||||
className, // className based on flow
|
||||
sign // sign base64
|
||||
);
|
||||
sendDoctoWebhook(_resDoc, data.imageUrl, 'signed', signUser);
|
||||
saveFileUsage(pdfSize, data.imageUrl, _resDoc?.CreatedBy?.objectId);
|
||||
if (updatedDoc && updatedDoc.isCompleted) {
|
||||
const doc = { ..._resDoc, AuditTrail: updatedDoc.AuditTrail };
|
||||
sendMailsaveCertifcate(
|
||||
doc,
|
||||
P12Buffer,
|
||||
data.imageUrl,
|
||||
isCustomMail,
|
||||
mailProvider,
|
||||
_resDoc?.CreatedBy?.objectId
|
||||
);
|
||||
}
|
||||
// `fs.unlinkSync` is used to remove exported signed pdf file from exports folder
|
||||
fs.unlinkSync(pdfName);
|
||||
console.log(`New Signed PDF created called: ${pdfName}`);
|
||||
if (updatedDoc.message === 'success') {
|
||||
return { status: 'success', data: data.imageUrl };
|
||||
} else {
|
||||
const error = new Error('Please provide required parameters!');
|
||||
error.code = 400; // Set the error code (e.g., 400 for bad request)
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const error = new Error('Pdf file not present!');
|
||||
error.code = 400; // Set the error code (e.g., 400 for bad request)
|
||||
throw error;
|
||||
isCompleted = true;
|
||||
}
|
||||
const randomNumber = Math.floor(Math.random() * 5000);
|
||||
const name = `exported_file_${randomNumber}.pdf`;
|
||||
const pdfName = `./exports/${name}`;
|
||||
let pdfSize = PdfBuffer.length;
|
||||
if (isCompleted) {
|
||||
const signersName = _resDoc.Signers?.map(x => x.Name + ' <' + x.Email + '>');
|
||||
if (signersName && signersName.length > 0) {
|
||||
// `pdflibAddPlaceholder` is used to add code of only digitial sign without widget
|
||||
const pdfDoc = await PDFDocument.load(PdfBuffer);
|
||||
pdflibAddPlaceholder({
|
||||
pdfDoc: pdfDoc,
|
||||
reason: 'Digitally signed by OpenSign for ' + signersName?.join(', '),
|
||||
location: 'n/a',
|
||||
name: eSignName,
|
||||
contactInfo: eSigncontact,
|
||||
signatureLength: 15000,
|
||||
});
|
||||
const pdfWithPlaceholderBytes = await pdfDoc.save();
|
||||
PdfBuffer = Buffer.from(pdfWithPlaceholderBytes);
|
||||
} else {
|
||||
// `pdflibAddPlaceholder` is used to add code of only digitial sign without widget (signyourself)
|
||||
const pdfDoc = await PDFDocument.load(PdfBuffer);
|
||||
pdflibAddPlaceholder({
|
||||
pdfDoc: pdfDoc,
|
||||
reason: 'Digitally signed by OpenSign for ' + username + ' <' + userEmail + '>',
|
||||
location: 'n/a',
|
||||
name: eSignName,
|
||||
contactInfo: eSigncontact,
|
||||
signatureLength: 15000,
|
||||
});
|
||||
const pdfWithPlaceholderBytes = await pdfDoc.save();
|
||||
PdfBuffer = Buffer.from(pdfWithPlaceholderBytes);
|
||||
}
|
||||
//`new signPDF` create new instance of pdfBuffer and p12Buffer
|
||||
const OBJ = new SignPdf();
|
||||
// `signedDocs` is used to signpdf digitally
|
||||
const signedDocs = await OBJ.sign(PdfBuffer, p12Cert);
|
||||
|
||||
//`saveUrl` is used to save signed pdf in exports folder
|
||||
const saveUrl = fs.writeFileSync(pdfName, signedDocs);
|
||||
pdfSize = signedDocs.length;
|
||||
} else {
|
||||
//`saveUrl` is used to save signed pdf in exports folder
|
||||
const saveUrl = fs.writeFileSync(pdfName, PdfBuffer);
|
||||
pdfSize = PdfBuffer.length;
|
||||
}
|
||||
|
||||
// `uploadFile` is used to upload pdf to aws s3 and get it's url
|
||||
const data = await uploadFile(name, pdfName);
|
||||
|
||||
if (data && data.imageUrl) {
|
||||
// `axios` is used to update signed pdf url in contracts_Document classes for given DocId
|
||||
const updatedDoc = await updateDoc(
|
||||
req.params.docId, //docId
|
||||
data.imageUrl, // url
|
||||
signUser.objectId, // userID
|
||||
userIP, // client ipAddress,
|
||||
_resDoc, // auditTrail, signers, etc data
|
||||
className, // className based on flow
|
||||
sign // sign base64
|
||||
);
|
||||
sendDoctoWebhook(_resDoc, data.imageUrl, 'signed', signUser);
|
||||
saveFileUsage(pdfSize, data.imageUrl, _resDoc?.CreatedBy?.objectId);
|
||||
if (updatedDoc && updatedDoc.isCompleted) {
|
||||
const doc = { ..._resDoc, AuditTrail: updatedDoc.AuditTrail };
|
||||
sendMailsaveCertifcate(
|
||||
doc,
|
||||
P12Buffer,
|
||||
data.imageUrl,
|
||||
isCustomMail,
|
||||
mailProvider,
|
||||
_resDoc?.CreatedBy?.objectId
|
||||
);
|
||||
}
|
||||
// `fs.unlinkSync` is used to remove exported signed pdf file from exports folder
|
||||
fs.unlinkSync(pdfName);
|
||||
console.log(`New Signed PDF created called: ${pdfName}`);
|
||||
if (updatedDoc.message === 'success') {
|
||||
return { status: 'success', data: data.imageUrl };
|
||||
} else {
|
||||
const error = new Error('Please provide required parameters!');
|
||||
error.code = 400; // Set the error code (e.g., 400 for bad request)
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const error = new Error('Pdf file not present!');
|
||||
error.code = 400; // Set the error code (e.g., 400 for bad request)
|
||||
throw error;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Err in signpdf', err);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
export default async function updateContactTour(request) {
|
||||
const contactId = request.params.contactId;
|
||||
try {
|
||||
const contactCls = new Parse.Query('contracts_Contactbook');
|
||||
const contactRes = await contactCls.get(contactId, { useMasterKey: true });
|
||||
if (contactRes) {
|
||||
const _contactRes = JSON.parse(JSON.stringify(contactRes));
|
||||
const tourStatus = _contactRes?.TourStatus?.length > 0 ? _contactRes.TourStatus : [];
|
||||
let updatedTourStatus = [];
|
||||
if (tourStatus.length > 0) {
|
||||
updatedTourStatus = [...tourStatus];
|
||||
const requestSignIndex = tourStatus.findIndex(
|
||||
obj => obj['requestSign'] === false || obj['requestSign'] === true
|
||||
);
|
||||
if (requestSignIndex !== -1) {
|
||||
updatedTourStatus[requestSignIndex] = { requestSign: true };
|
||||
} else {
|
||||
updatedTourStatus.push({ requestSign: true });
|
||||
}
|
||||
} else {
|
||||
updatedTourStatus = [{ requestSign: true }];
|
||||
}
|
||||
contactRes.set('TourStatus', updatedTourStatus);
|
||||
const updateRes = await contactRes.save(null, { useMasterKey: true });
|
||||
return updateRes;
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'contact not found.');
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Err in contracts_Contactbook class ', err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user