Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into api-v1-beta

This commit is contained in:
prafull-opensignlabs
2024-01-11 22:27:09 +05:30
106 changed files with 11025 additions and 4332 deletions
@@ -16,6 +16,7 @@ async function ContactbookAftersave(request) {
acl.setWriteAccess(object.get('UserId'), true);
object.setACL(acl);
object.set('IsDeleted', false)
// Continue saving the object
return object.save(null, { useMasterKey: true });
}
@@ -0,0 +1,53 @@
import axios from 'axios';
export default async function GetTemplate(request) {
const serverUrl = process.env.SERVER_URL;
const templateId = request.params.templateId;
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;
// console.log("templateId ", templateId)
// console.log("userId ",userId)
if (templateId && userId) {
try {
const template = new Parse.Query('contracts_Template');
template.equalTo('objectId', templateId);
template.include('ExtUserPtr');
template.include('Signers');
template.include('CreateBy');
const res = await template.first({ useMasterKey: true });
// console.log("res ", res)
if (res) {
// console.log("res ",res)
const acl = res.getACL();
console.log("acl", acl.getReadAccess(userId))
if (acl && acl.getReadAccess(userId)) {
return res;
} else {
return { error: "You don't have access of this document!" };
}
} else {
return { error: "You don't have access of this document!" };
}
} catch (err) {
console.log('err', err);
return err;
}
} else {
return { error: 'Please pass required parameters!' };
}
} catch (err) {
console.log('err', err);
if (err.code == 209) {
return { error: 'Invalid session token' };
} else {
return { error: "You don't have access of this document!" };
}
}
}
@@ -0,0 +1,83 @@
export default async function TemplateAfterSave(request) {
try {
if (!request.original) {
console.log('new entry is insert in contracts_Template');
// update acl of New Document If There are signers present in array
const signers = request.object.get('Signers');
if (signers && signers.length > 0) {
await updateAclDoc(request.object.id);
} else {
await updateSelfDoc(request.object.id);
}
} else {
if (request.user) {
const signers = request.object.get('Signers');
if (signers && signers.length > 0) {
await updateAclDoc(request.object.id);
} else {
await updateSelfDoc(request.object.id);
}
}
}
} catch (err) {
console.log('err in aftersave of contracts_Template');
console.log(err);
}
async function updateAclDoc(objId) {
// console.log("In side updateAclDoc func")
// console.log(objId)
const Query = new Parse.Query('contracts_Template');
Query.include('Signers');
const updateACL = await Query.get(objId, { useMasterKey: true });
const res = JSON.parse(JSON.stringify(updateACL));
// console.log("res");
// console.log(JSON.stringify(res));
const UsersPtr = res.Signers.map(item => item.UserId);
if (res.Signers[0].ExtUserPtr) {
const ExtUserSigners = res.Signers.map(item => {
return {
__type: 'Pointer',
className: 'contracts_Users',
objectId: item.ExtUserPtr.objectId,
};
});
updateACL.set('Signers', ExtUserSigners);
}
// console.log("UsersPtr")
// console.log(JSON.stringify(UsersPtr))
const newACL = new Parse.ACL();
newACL.setPublicReadAccess(false);
newACL.setPublicWriteAccess(false);
newACL.setReadAccess(request.user, true);
newACL.setWriteAccess(request.user, true);
UsersPtr.forEach(x => {
newACL.setReadAccess(x.objectId, true);
newACL.setWriteAccess(x.objectId, true);
});
updateACL.setACL(newACL);
updateACL.save(null, { useMasterKey: true });
}
async function updateSelfDoc(objId) {
// console.log("Inside updateSelfDoc func")
const Query = new Parse.Query('contracts_Template');
const updateACL = await Query.get(objId, { useMasterKey: true });
// const res = JSON.parse(JSON.stringify(updateACL));
// console.log("res");
// console.log(JSON.stringify(res));
const newACL = new Parse.ACL();
newACL.setPublicReadAccess(false);
newACL.setPublicWriteAccess(false);
newACL.setReadAccess(request.user, true);
newACL.setWriteAccess(request.user, true);
updateACL.setACL(newACL);
updateACL.save(null, { useMasterKey: true });
}
}
@@ -21,6 +21,7 @@ export default async function getDocument(request) {
query.include('Signers');
query.include('AuditTrail.UserPtr');
query.include('Placeholders');
query.notEqualTo('IsArchive', true)
const res = await query.first({ useMasterKey: true });
if (res) {
const acl = res.getACL();
@@ -40,7 +41,7 @@ export default async function getDocument(request) {
return { error: 'Please pass required parameters!' };
}
} catch (err) {
console.log('err');
console.log('err', err);
if (err.code == 209) {
return { error: 'Invalid session token' };
} else {
@@ -16,9 +16,9 @@ export default async function getDrive(request) {
if (userId) {
let url;
if (docId) {
url = `${classUrl}?where={"Folder":{"__type":"Pointer","className":"contracts_Document","objectId":"${docId}"},"$or":[{"CreatedBy":{"$exists":false}},{"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"}}]}&include=ExtUserPtr,Signers,Folder`;
url = `${classUrl}?where={"Folder":{"__type":"Pointer","className":"contracts_Document","objectId":"${docId}"},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"},"IsArchive":{"$ne":true}}&include=ExtUserPtr,Signers,Folder`;
} else {
url = `${classUrl}?where={"Folder":{"$exists":false},"$or":[{"CreatedBy":{"$exists":false}},{"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"}}]}&include=ExtUserPtr,Signers`;
url = `${classUrl}?where={"Folder":{"$exists":false},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"},"IsArchive":{"$ne":true}}&include=ExtUserPtr,Signers`;
}
try {
const res = await axios.get(url, {
@@ -19,7 +19,7 @@ export default async function getReport(request) {
const userId = userRes.data && userRes.data.objectId;
if (userId) {
const json = reportId && reportJson(reportId, userId);
const clsName = reportId === '5KhaPr482K' ? 'contracts_Contactbook' : 'contracts_Document';
const clsName = json?.reportClass ? json.reportClass : 'contracts_Document';
if (json) {
const { params, keys } = json;
const orderBy = '-updatedAt';
+110 -90
View File
@@ -2,7 +2,7 @@ import SignPDF from './SignPDF.min.cjs';
import fs from 'node:fs';
import axios from 'axios';
import FormData from 'form-data';
import plainplaceholder from './customSignPdf/plainplaceholder.min.js';
// import plainplaceholder from './customSignPdf/plainplaceholder.min.js';
import { plainAddPlaceholder } from 'node-signpdf/dist/helpers/index.js';
const serverUrl = process.env.SERVER_URL,
APPID = process.env.APP_ID,
@@ -19,20 +19,20 @@ async function uploadFile(a) {
console.log('err ', e), fs.unlinkSync(a);
}
}
async function updateDoc(t, s, r, i, o, n) {
async function updateDoc(t, s, r, i, n, o) {
try {
var d = {
UserPtr: { __type: 'Pointer', className: n, objectId: r },
UserPtr: { __type: 'Pointer', className: o, objectId: r },
SignedUrl: s,
Activity: 'Signed',
ipAddress: i,
};
let e;
var l = (e = o.AuditTrail && 0 < o.AuditTrail.length ? [...o.AuditTrail, d] : [d]).filter(
var l = (e = n.AuditTrail && 0 < n.AuditTrail.length ? [...n.AuditTrail, d] : [d]).filter(
e => 'Signed' === e.Activity
);
let a = !1;
!((o.Signers && 0 < o.Signers.length && l.length !== o.Signers.length) || !(a = !0));
!((n.Signers && 0 < n.Signers.length && l.length !== n.Signers.length) || !(a = !0));
var p = { SignedUrl: s, AuditTrail: e, IsCompleted: a };
await axios.put(serverUrl + '/classes/contracts_Document/' + t, p, {
headers: {
@@ -61,7 +61,7 @@ async function sendMail(e) {
s +
' Standard is attached to this email. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from Open Sign. For any queries regarding this email, please contact the sender ' +
t.Mail +
' directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign here.</p></div></div></body></html>',
' directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>'
};
await axios.post(serverUrl + '/functions/sendmailv3', a, {
headers: {
@@ -86,7 +86,7 @@ async function sendCompletedMail(e) {
s +
'. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from Open Sign. For any queries regarding this email, please contact the sender ' +
t.Mail +
' directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign here.</p></div></div></body></html>',
' directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>',
};
await axios.post(serverUrl + '/functions/sendmailv3', a, {
headers: {
@@ -96,115 +96,135 @@ async function sendCompletedMail(e) {
},
});
}
async function PDF(s, r) {
async function PDF(i, n) {
try {
var i = s.params.sign,
e = s.params.docId,
o = s.params.userId,
n = await axios.get(serverUrl + '/classes/contracts_Document/' + e + '?include=ExtUserPtr', {
headers: {
'Content-Type': 'application/json',
'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY,
},
}),
d = await axios.get(serverUrl + '/users/me', {
i.params.sign;
var e = i.params.docId,
a = i.params.userId,
o = await axios.get(
serverUrl + '/classes/contracts_Document/' + e + '?include=ExtUserPtr,Signers',
{
headers: {
'Content-Type': 'application/json',
'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY,
},
}
),
t = await axios.get(serverUrl + '/users/me', {
headers: {
'X-Parse-Application-Id': APPID,
'X-Parse-Session-Token': s.headers.sessiontoken,
'X-Parse-Session-Token': i.headers.sessiontoken,
},
});
if (!d.data || !d.data.objectId) return { status: 'error', message: 'this user not allowed!' };
if (!t.data || !t.data.objectId) return { status: 'error', message: 'this user not allowed!' };
{
var l,
var d,
l,
p,
c,
m = JSON.stringify({ objectId: o });
let a, t;
t = o
? (l = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + m, {
c = JSON.stringify({ objectId: a });
let s, r;
r = a
? (d = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + c, {
headers: {
'X-Parse-Application-Id': APPID,
'X-Parse-Session-Token': s.headers.sessiontoken,
'X-Parse-Session-Token': i.headers.sessiontoken,
},
})).data && 0 < l.data.results.length
? ((a = l), 'contracts_Contactbook')
: ((a = await axios.get(serverUrl + '/classes/contracts_Users?where=' + m, {
headers: {
'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY,
},
})).data && 0 < d.data.results.length
? ((s = d), 'contracts_Contactbook')
: ((s = await axios.get(serverUrl + '/classes/contracts_Users?where=' + c, {
headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY },
})),
'contracts_Users')
: ((p = JSON.stringify({
UserId: { __type: 'Pointer', className: '_User', objectId: d.data.objectId },
: ((l = JSON.stringify({
UserId: { __type: 'Pointer', className: '_User', objectId: t.data.objectId },
})),
(c = await axios.get(serverUrl + '/classes/contracts_Users?where=' + p, {
headers: {
'X-Parse-Application-Id': APPID,
'X-Parse-Master-Key': masterKEY,
},
})).data && 0 < c.data.results.length
? ((a = c), 'contracts_Users')
: ((a = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + p, {
(p = await axios.get(serverUrl + '/classes/contracts_Users?where=' + l, {
headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY },
})).data && 0 < p.data.results.length
? ((s = p), 'contracts_Users')
: ((s = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + l, {
headers: {
'X-Parse-Application-Id': APPID,
'X-Parse-Session-Token': s.headers.sessiontoken,
'X-Parse-Session-Token': i.headers.sessiontoken,
},
})),
'contracts_Contactbook'));
var g = a.data.results[0].Name,
h = a.data.results[0].Email;
if (!s.params.pdfFile) return { status: 'error', message: 'pdf file not present!' };
var m = s.data.results[0].Name,
g = s.data.results[0].Email;
if (!i.params.pdfFile) return { status: 'error', message: 'pdf file not present!' };
{
let e = Buffer.from(s.params.pdfFile, 'base64');
let e = Buffer.from(i.params.pdfFile, 'base64');
var u = process.env.PFX_BASE64,
f = Buffer.from(u, 'base64');
e = i
? plainplaceholder({
pdfBuffer: e,
reason: 'Digitally signed by Open sign for ' + g + ' <' + h + '>',
location: 'test location',
signatureLength: 1e4,
sign: i,
})
: plainAddPlaceholder({
pdfBuffer: e,
reason: 'Digitally signed by Open sign for ' + g + ' <' + h + '>',
location: 'test location',
signatureLength: 1e4,
});
var y = await new SignPDF(e, f).signPDF(),
v = `./exports/exported_file_${Math.floor(5e3 * Math.random())}.pdf`,
P = (fs.writeFileSync(v, y), await uploadFile(v));
if (P && P.imageUrl) {
const r = await updateDoc(
s.params.docId,
P.imageUrl,
a.data.results[0].objectId,
s.headers['x-real-ip'],
n.data,
t
h = Buffer.from(u, 'base64'),
f = {
UserPtr: { __type: 'Pointer', className: r, objectId: s.data.results[0].objectId },
SignedUrl: '',
Activity: 'Signed',
ipAddress: i.headers['x-real-ip'],
};
let a;
var y = (a =
o.data.AuditTrail && 0 < o.data.AuditTrail.length
? [...o.data.AuditTrail, f]
: [f]).filter(e => 'Signed' === e.Activity);
let t = !1;
!(
(o.data.Signers && 0 < o.data.Signers.length && y.length !== o.data.Signers.length) ||
!(t = !0)
);
var v,
P,
x = `./exports/exported_file_${Math.floor(5e3 * Math.random())}.pdf`,
A =
(t
? ((v = o.data.Signers?.map(e => e.Name + ' <' + e.Email + '>')),
(e =
v && 0 < v.length
? plainAddPlaceholder({
pdfBuffer: e,
reason: 'Digitally signed by Open sign for ' + v?.join(', '),
location: 'location',
signatureLength: 1e4,
})
: plainAddPlaceholder({
pdfBuffer: e,
reason: 'Digitally signed by Open sign for ' + m + ' <' + g + '>',
location: 'location',
signatureLength: 1e4,
})),
(P = await new SignPDF(e, h).signPDF()),
fs.writeFileSync(x, P))
: fs.writeFileSync(x, e),
await uploadFile(x));
if (A && A.imageUrl) {
const n = await updateDoc(
i.params.docId,
A.imageUrl,
s.data.results[0].objectId,
i.headers['x-real-ip'],
o.data,
r
);
return (
sendMail({
url: P.imageUrl,
sender: { Mail: n.data.ExtUserPtr.Email, Name: n.data.ExtUserPtr.Name },
pdfName: n.data.Name,
receiver: h,
url: A.imageUrl,
sender: { Mail: o.data.ExtUserPtr.Email, Name: o.data.ExtUserPtr.Name },
pdfName: o.data.Name,
receiver: g,
}),
r &&
r.isCompleted &&
n &&
n.isCompleted &&
sendCompletedMail({
url: P.imageUrl,
sender: { Mail: n.data.ExtUserPtr.Email, Name: 'Open sign' },
pdfName: n.data.Name,
receiver: n.data.ExtUserPtr.Email,
url: A.imageUrl,
sender: { Mail: o.data.ExtUserPtr.Email, Name: 'Open sign' },
pdfName: o.data.Name,
receiver: o.data.ExtUserPtr.Email,
}),
fs.unlinkSync(v),
console.log('New Signed PDF created called: ' + v),
'success' === r.message
? { status: 'success', data: P.imageUrl }
fs.unlinkSync(x),
console.log('New Signed PDF created called: ' + x),
'success' === n.message
? { status: 'success', data: A.imageUrl }
: { status: 'error', message: 'please provide required parameters!' }
);
}
@@ -7,11 +7,11 @@ export default function reportJson(id, userId) {
return {
reportName: 'Draft Documents',
params: {
Type: null,
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null },
],
Type: { $ne: 'Folder' },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
$or: [{Signers:{$eq:[]}}, { Signers: null }, { Signers: { $exists: true }, Placeholders: null }],
CreatedBy: {
__type: 'Pointer',
className: '_User',
@@ -28,10 +28,23 @@ export default function reportJson(id, userId) {
Type: { $ne: 'Folder' },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
ExpiryDate: {
$gt: { __type: 'Date', iso: new Date().toISOString() },
},
Placeholders: { $ne: null },
Signers: {
$inQuery: {
where: {
UserId: {
__type: 'Pointer',
className: '_User',
objectId: currentUserId,
},
},
className: 'contracts_Contactbook',
},
},
},
keys: [
'Name',
@@ -50,10 +63,11 @@ export default function reportJson(id, userId) {
reportName: 'In-progress documents',
params: {
Type: { $ne: 'Folder' },
Signers: { $ne: null },
Signers: { $exists: true, $ne: [] },
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
CreatedBy: {
__type: 'Pointer',
className: '_User',
@@ -70,7 +84,7 @@ export default function reportJson(id, userId) {
return {
reportName: 'Completed Documents',
params: {
Type: null,
Type: { $ne: 'Folder' },
IsCompleted: true,
CreatedBy: {
__type: 'Pointer',
@@ -78,6 +92,7 @@ export default function reportJson(id, userId) {
objectId: currentUserId,
},
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
},
keys: [
'Name',
@@ -96,6 +111,7 @@ export default function reportJson(id, userId) {
reportName: 'Declined Documents',
params: {
Type: null,
IsArchive: { $ne: true },
IsDeclined: true,
CreatedBy: {
__type: 'Pointer',
@@ -113,6 +129,7 @@ export default function reportJson(id, userId) {
params: {
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
Type: { $ne: 'Folder' },
$and: [
{
@@ -141,10 +158,11 @@ export default function reportJson(id, userId) {
reportName: 'Recently sent for signatures',
params: {
Type: { $ne: 'Folder' },
Signers: { $ne: null },
Signers: { $exists: true, $ne: [] },
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
CreatedBy: {
__type: 'Pointer',
className: '_User',
@@ -154,7 +172,7 @@ export default function reportJson(id, userId) {
$gt: { __type: 'Date', iso: new Date().toISOString() },
},
},
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
keys: ['Name', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
};
// Recent signature requests report show on dashboard
case '5Go51Q7T8r':
@@ -164,32 +182,36 @@ export default function reportJson(id, userId) {
Type: { $ne: 'Folder' },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
ExpiryDate: {
$gt: { __type: 'Date', iso: new Date().toISOString() },
},
Placeholders: { $ne: null },
Signers: {
$inQuery: {
where: {
UserId: {
__type: 'Pointer',
className: '_User',
objectId: currentUserId,
},
},
className: 'contracts_Contactbook',
},
},
},
keys: [
'Name',
'Note',
'Folder.Name',
'URL',
'ExtUserPtr.Name',
'Signers.Name',
'Signers.UserId',
'AuditTrail',
],
keys: ['Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name', 'Signers.UserId', 'AuditTrail'],
};
// Drafts report show on dashboard
case 'kC5mfynCi4':
return {
reportName: 'Drafts',
params: {
Type: null,
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null },
],
Type: { $ne: 'Folder' },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
$or: [{Signers:{$eq:[]}}, { Signers: null }, { Signers: { $exists: true }, Placeholders: null }],
CreatedBy: {
__type: 'Pointer',
className: '_User',
@@ -202,6 +224,7 @@ export default function reportJson(id, userId) {
case '5KhaPr482K':
return {
reportName: 'Contactbook',
reportClass: 'contracts_Contactbook',
params: {
CreatedBy: {
__type: 'Pointer',
@@ -212,6 +235,22 @@ export default function reportJson(id, userId) {
},
keys: ['Name', 'Email', 'Phone'],
};
// Templates report
case '6TeaPr321t':
return {
reportName: 'Templates',
reportClass: 'contracts_Template',
params: {
Type: { $ne: 'Folder' },
IsArchive: { $ne: true },
CreatedBy: {
__type: 'Pointer',
className: '_User',
objectId: currentUserId,
},
},
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
};
default:
return null;
}