mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-20 06:35:54 +02:00
v2.35.0
This commit is contained in:
@@ -2,59 +2,23 @@ async function DocumentAftersave(request) {
|
||||
try {
|
||||
if (!request.original) {
|
||||
console.log('new entry is insert in contracts_Document');
|
||||
const createdAt = request.object.get('createdAt');
|
||||
const Folder = request.object.get('Type');
|
||||
const obj = request.object;
|
||||
const objId = obj?.id;
|
||||
const createdAt = obj?.get?.('createdAt');
|
||||
const folder = obj?.get?.('Type');
|
||||
const ip = request?.headers?.['x-real-ip'] || '';
|
||||
const originIp = request?.object?.get('OriginIp') || '';
|
||||
if (createdAt && Folder === undefined) {
|
||||
// console.log("IN If condition")
|
||||
const TimeToCompleteDays = request.object.get('TimeToCompleteDays') || 15;
|
||||
const ExpiryDate = new Date(createdAt);
|
||||
ExpiryDate.setDate(ExpiryDate.getDate() + TimeToCompleteDays);
|
||||
const documentQuery = new Parse.Query('contracts_Document');
|
||||
documentQuery.include('ExtUserPtr.TenantId');
|
||||
const updateQuery = await documentQuery.get(request.object.id, { useMasterKey: true });
|
||||
updateQuery.set('ExpiryDate', ExpiryDate);
|
||||
if (!originIp) {
|
||||
updateQuery.set('OriginIp', ip);
|
||||
}
|
||||
const AutoReminder = request?.object?.get('AutomaticReminders') || false;
|
||||
if (AutoReminder) {
|
||||
const RemindOnceInEvery = request?.object?.get('RemindOnceInEvery') || 5;
|
||||
const ReminderDate = new Date(createdAt);
|
||||
ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery);
|
||||
updateQuery.set('NextReminderDate', ReminderDate);
|
||||
}
|
||||
await updateQuery.save(null, { useMasterKey: true });
|
||||
} else if (createdAt && Folder === 'AIDoc') {
|
||||
const TimeToCompleteDays = request.object.get('TimeToCompleteDays');
|
||||
const ExpiryDate = new Date(createdAt);
|
||||
ExpiryDate.setDate(ExpiryDate.getDate() + TimeToCompleteDays);
|
||||
const documentQuery = new Parse.Query('contracts_Document');
|
||||
documentQuery.include('ExtUserPtr.TenantId');
|
||||
const updateQuery = await documentQuery.get(request.object.id, { useMasterKey: true });
|
||||
updateQuery.set('ExpiryDate', ExpiryDate);
|
||||
if (!originIp) {
|
||||
updateQuery.set('OriginIp', ip);
|
||||
}
|
||||
const AutoReminder = request?.object?.get('AutomaticReminders') || false;
|
||||
if (AutoReminder) {
|
||||
const RemindOnceInEvery = request?.object?.get('RemindOnceInEvery') || 5;
|
||||
const ReminderDate = new Date(createdAt);
|
||||
ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery);
|
||||
updateQuery.set('NextReminderDate', ReminderDate);
|
||||
}
|
||||
await updateQuery.save(null, { useMasterKey: true });
|
||||
const originIp = obj?.get?.('OriginIp') || '';
|
||||
if (createdAt) {
|
||||
await updateDocumentMeta({ objId, createdAt, folder, ip, originIp });
|
||||
}
|
||||
|
||||
const signers = request.object.get('Signers');
|
||||
const signers = obj?.get?.('Signers');
|
||||
const hasSigners = Array.isArray(signers) && signers.length > 0;
|
||||
// update acl of New Document If There are signers present in array
|
||||
if (signers && signers.length > 0) {
|
||||
await updateAclDoc(request.object.id);
|
||||
} else {
|
||||
if (request?.object?.id && request.user) {
|
||||
await updateSelfDoc(request.object.id);
|
||||
}
|
||||
if (hasSigners) {
|
||||
await updateAclDoc(objId);
|
||||
} else if (objId && request?.user) {
|
||||
await updateSelfDoc(objId);
|
||||
}
|
||||
} else {
|
||||
if (request?.user) {
|
||||
@@ -73,17 +37,49 @@ async function DocumentAftersave(request) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
async function updateDocumentMeta({ objId, createdAt, folder, ip, originIp }) {
|
||||
const documentQuery = new Parse.Query('contracts_Document');
|
||||
documentQuery.include('ExtUserPtr.TenantId');
|
||||
|
||||
const doc = await documentQuery.get(objId, { useMasterKey: true });
|
||||
if (folder === undefined || folder === 'AIDoc') {
|
||||
// ExpiryDate
|
||||
const timeToCompleteDays =
|
||||
folder === undefined
|
||||
? doc.get('TimeToCompleteDays') || 15 // keep your default=15 only for "undefined folder"
|
||||
: doc.get('TimeToCompleteDays'); // keep original behavior for AIDoc (no forced default)
|
||||
|
||||
if (typeof timeToCompleteDays === 'number' && createdAt) {
|
||||
const expiryDate = new Date(createdAt);
|
||||
expiryDate.setDate(expiryDate.getDate() + timeToCompleteDays);
|
||||
doc.set('ExpiryDate', expiryDate);
|
||||
}
|
||||
|
||||
// OriginIp
|
||||
if (!originIp) {
|
||||
doc.set('OriginIp', ip);
|
||||
}
|
||||
|
||||
// Automatic reminders
|
||||
const autoReminder = doc.get('AutomaticReminders') || false;
|
||||
if (autoReminder && createdAt) {
|
||||
const remindOnceInEvery = doc.get('RemindOnceInEvery') || 5;
|
||||
const reminderDate = new Date(createdAt);
|
||||
reminderDate.setDate(reminderDate.getDate() + remindOnceInEvery);
|
||||
doc.set('NextReminderDate', reminderDate);
|
||||
}
|
||||
}
|
||||
|
||||
await doc.save(null, { useMasterKey: true });
|
||||
}
|
||||
|
||||
async function updateAclDoc(objId) {
|
||||
// console.log("In side updateAclDoc func")
|
||||
// console.log(objId)
|
||||
const Query = new Parse.Query('contracts_Document');
|
||||
Query.include('Signers');
|
||||
Query.include('ExtUserPtr.TenantId');
|
||||
Query.include('CreatedBy');
|
||||
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) {
|
||||
@@ -97,8 +93,6 @@ async function DocumentAftersave(request) {
|
||||
updateACL.set('Signers', ExtUserSigners);
|
||||
}
|
||||
|
||||
// console.log("UsersPtr")
|
||||
// console.log(JSON.stringify(UsersPtr))
|
||||
const newACL = new Parse.ACL();
|
||||
newACL.setPublicReadAccess(false);
|
||||
newACL.setPublicWriteAccess(false);
|
||||
@@ -116,14 +110,11 @@ async function DocumentAftersave(request) {
|
||||
}
|
||||
|
||||
async function updateSelfDoc(objId) {
|
||||
// console.log(objId)
|
||||
const Query = new Parse.Query('contracts_Document');
|
||||
Query.include('CreatedBy');
|
||||
Query.include('ExtUserPtr.TenantId');
|
||||
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);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { MAX_DESCRIPTION_LENGTH, MAX_NAME_LENGTH, MAX_NOTE_LENGTH } from '../../Utils.js';
|
||||
import { setDocumentCount } from '../../utils/CountUtils.js';
|
||||
|
||||
async function DocumentBeforesave(request) {
|
||||
if (!request.original) {
|
||||
@@ -33,24 +34,8 @@ async function DocumentBeforesave(request) {
|
||||
|
||||
// Check if SignedUrl field has been added (transition from undefined to defined)
|
||||
if (oldDocument && !oldDocument?.get('SignedUrl') && document?.get('SignedUrl')) {
|
||||
// Update count in contracts_Users class
|
||||
const query = new Parse.Query('contracts_Users');
|
||||
query.equalTo('objectId', oldDocument.get('ExtUserPtr').id);
|
||||
|
||||
try {
|
||||
const contractUser = await query.first({ useMasterKey: true });
|
||||
if (contractUser) {
|
||||
contractUser.increment('DocumentCount', 1);
|
||||
await contractUser.save(null, { useMasterKey: true });
|
||||
} else {
|
||||
// Create new entry if not found
|
||||
const ContractsUsers = Parse.Object.extend('contracts_Users');
|
||||
const newContractUser = new ContractsUsers();
|
||||
newContractUser.set('DocumentCount', 1);
|
||||
await newContractUser.save(null, { useMasterKey: true });
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error updating document count in contracts_Users: ' + error.message);
|
||||
if (oldDocument?.get('ExtUserPtr')?.id) {
|
||||
setDocumentCount(oldDocument?.get('ExtUserPtr')?.id);
|
||||
}
|
||||
if (document?.get('Signers') && document.get('Signers').length > 0) {
|
||||
document.set('DocSentAt', new Date());
|
||||
|
||||
@@ -36,7 +36,7 @@ export default async function forwardDoc(request) {
|
||||
let mailRes;
|
||||
for (let i = 0; i < recipients.length; i++) {
|
||||
const logo = `<img src='https://qikinnovation.ams3.digitaloceanspaces.com/logo.png' height='50' style='padding:20px'/>`;
|
||||
const opurl = ` <a href='www.opensignlabs.com' target=_blank>here</a>`;
|
||||
const opurl = ` <a href='mailto:complaint@opensiglabs.com' target=_blank>here</a>`;
|
||||
const themeColor = '#47a3ad';
|
||||
|
||||
let params = {
|
||||
@@ -52,7 +52,7 @@ export default async function forwardDoc(request) {
|
||||
`${logo}</div><div style='padding:2px;font-family:system-ui;background-color:${themeColor}'><p style='font-size:20px;font-weight:400;color:white;padding-left:20px'>Document Copy</p></div><div>` +
|
||||
`<p style='padding:20px;font-family:system-ui;font-size:14px'>A copy of the document <strong>${docName}</strong> is attached to this email. Kindly download the document from the attachment.</p>` +
|
||||
`</div></div><div><p>This is an automated email from ${TenantAppName}. For any queries regarding this email, please contact the sender ${replyTo} directly. ` +
|
||||
`If you think this email is inappropriate or spam, you may file a complaint with ${TenantAppName}${opurl}.</p></div></div></body></html>`,
|
||||
`If you think this email is inappropriate or spam, you may file a complaints with ${TenantAppName}${opurl}.</p></div></div></body></html>`,
|
||||
};
|
||||
mailRes = await axios.post(`${cloudServerUrl}/functions/sendmailv3`, params, {
|
||||
headers: {
|
||||
|
||||
@@ -2,27 +2,20 @@ 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');
|
||||
const AutoReminder = request?.object?.get('AutomaticReminders') || false;
|
||||
const obj = request.object;
|
||||
const objId = obj?.id;
|
||||
const ip = request?.headers?.['x-real-ip'] || '';
|
||||
const originIp = request?.object?.get('OriginIp') || '';
|
||||
if (AutoReminder) {
|
||||
const RemindOnceInEvery = request?.object?.get('RemindOnceInEvery') || 5;
|
||||
const ReminderDate = new Date(request?.object?.get('createdAt'));
|
||||
ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery);
|
||||
request.object.set('NextReminderDate', ReminderDate);
|
||||
}
|
||||
if (!originIp) {
|
||||
request.object.set('OriginIp', ip);
|
||||
}
|
||||
await request.object.save(null, { useMasterKey: true });
|
||||
if (signers && signers.length > 0) {
|
||||
await updateAclDoc(request.object.id);
|
||||
} else {
|
||||
if (request?.object?.id && request?.user) {
|
||||
await updateSelfDoc(request.object.id);
|
||||
}
|
||||
const originIp = obj?.get?.('OriginIp') || '';
|
||||
const createdAt = obj?.get?.('createdAt');
|
||||
|
||||
// update acl of New template If There are signers present in array
|
||||
const signers = obj?.get('Signers');
|
||||
const hasSigners = Array.isArray(signers) && signers.length > 0;
|
||||
updateTemplateMeta({ objId, createdAt, ip, originIp });
|
||||
if (hasSigners) {
|
||||
await updateAclDoc(objId);
|
||||
} else if (objId && request?.user) {
|
||||
await updateSelfDoc(objId);
|
||||
}
|
||||
} else {
|
||||
if (request?.user) {
|
||||
@@ -41,17 +34,33 @@ export default async function TemplateAfterSave(request) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
async function updateTemplateMeta({ objId, createdAt, ip, originIp }) {
|
||||
const templateQuery = new Parse.Query('contracts_Template');
|
||||
templateQuery.include('ExtUserPtr.TenantId');
|
||||
|
||||
const obj = await templateQuery.get(objId, { useMasterKey: true });
|
||||
|
||||
// Automatic reminders
|
||||
const AutoReminder = obj?.get('AutomaticReminders') || false;
|
||||
if (AutoReminder) {
|
||||
const RemindOnceInEvery = obj?.get('RemindOnceInEvery') || 5;
|
||||
const ReminderDate = new Date(createdAt);
|
||||
ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery);
|
||||
obj.set('NextReminderDate', ReminderDate);
|
||||
}
|
||||
if (!originIp) {
|
||||
obj.set('OriginIp', ip);
|
||||
}
|
||||
|
||||
await obj.save(null, { useMasterKey: true });
|
||||
}
|
||||
async function updateAclDoc(objId) {
|
||||
// console.log("In side updateAclDoc func")
|
||||
// console.log(objId)
|
||||
const Query = new Parse.Query('contracts_Template');
|
||||
Query.include('Signers');
|
||||
Query.include('CreatedBy');
|
||||
Query.include('ExtUserPtr.TenantId');
|
||||
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) {
|
||||
@@ -65,8 +74,6 @@ export default async function TemplateAfterSave(request) {
|
||||
updateACL.set('Signers', ExtUserSigners);
|
||||
}
|
||||
|
||||
// console.log("UsersPtr")
|
||||
// console.log(JSON.stringify(UsersPtr))
|
||||
const newACL = new Parse.ACL();
|
||||
newACL.setPublicReadAccess(false);
|
||||
newACL.setPublicWriteAccess(false);
|
||||
@@ -85,15 +92,11 @@ export default async function TemplateAfterSave(request) {
|
||||
}
|
||||
|
||||
async function updateSelfDoc(objId) {
|
||||
// console.log("Inside updateSelfDoc func")
|
||||
|
||||
const Query = new Parse.Query('contracts_Template');
|
||||
Query.include('CreatedBy');
|
||||
Query.include('ExtUserPtr.TenantId');
|
||||
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);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { MAX_DESCRIPTION_LENGTH, MAX_NAME_LENGTH, MAX_NOTE_LENGTH } from '../../Utils.js';
|
||||
import { setTemplateCount } from '../../utils/CountUtils.js';
|
||||
|
||||
async function TemplateBeforeSave(request) {
|
||||
if (!request.original) {
|
||||
@@ -31,24 +32,8 @@ async function TemplateBeforeSave(request) {
|
||||
// below code is used to update template when user sent template or self signed
|
||||
const template = request.object;
|
||||
|
||||
// Update count in contracts_Users class
|
||||
const query = new Parse.Query('contracts_Users');
|
||||
query.equalTo('objectId', template.get('ExtUserPtr').id);
|
||||
|
||||
try {
|
||||
const contractUser = await query.first({ useMasterKey: true });
|
||||
if (contractUser) {
|
||||
contractUser.increment('TemplateCount', 1);
|
||||
await contractUser.save(null, { useMasterKey: true });
|
||||
} else {
|
||||
// Create new entry if not found
|
||||
const ContractsUsers = Parse.Object.extend('contracts_Users');
|
||||
const newContractUser = new ContractsUsers();
|
||||
newContractUser.set('TemplateCount', 1);
|
||||
await newContractUser.save(null, { useMasterKey: true });
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Error updating template count in contracts_Users: ' + error.message);
|
||||
if (template?.get('ExtUserPtr')?.id) {
|
||||
setTemplateCount(template?.get('ExtUserPtr')?.id);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import axios from 'axios';
|
||||
import { cloudServerUrl, mailTemplate, replaceMailVaribles, serverAppId } from '../../Utils.js';
|
||||
import { setDocumentCount } from '../../utils/CountUtils.js';
|
||||
|
||||
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
|
||||
const appId = serverAppId;
|
||||
async function deductcount(docsCount, extUserId) {
|
||||
try {
|
||||
const extCls = new Parse.Object('contracts_Users');
|
||||
extCls.id = extUserId;
|
||||
extCls.increment('DocumentCount', docsCount);
|
||||
const resExt = await extCls.save(null, { useMasterKey: true });
|
||||
if (extUserId) {
|
||||
setDocumentCount(extUserId);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Err in deduct in quick send', err);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ async function sendDeclineMail(doc, publicUrl, userId, reason) {
|
||||
const TenantAppName = appName;
|
||||
const logo =
|
||||
"<img src='https://qikinnovation.ams3.digitaloceanspaces.com/logo.png' height='50' style='padding:20px'/>";
|
||||
const opurl = ` <a href=www.opensignlabs.com target=_blank>here</a>`;
|
||||
const opurl = ` <a href='mailto:complaint@opensiglabs.com' target=_blank>here</a>`;
|
||||
const removePrefill =
|
||||
doc?.Placeholders?.length > 0 && doc?.Placeholders?.filter(x => x?.Role !== 'prefill');
|
||||
const signUser =
|
||||
@@ -36,7 +36,7 @@ async function sendDeclineMail(doc, publicUrl, userId, reason) {
|
||||
`<p>${pdfName} has been declined by ${signerName} "${signerEmail}" on ${new Date().toLocaleDateString()}.</p>` +
|
||||
`<p>Decline Reason: ${reason || 'Not specified'}</p>` +
|
||||
`<p><a href=${viewDocUrl} target=_blank>View Document</a></p></div></div><div><p>This is an automated email from ${TenantAppName}. For any queries regarding this email, ` +
|
||||
`please contact the sender ${creatorEmail} directly. If you think this email is inappropriate or spam, you may file a complaint with ${TenantAppName}${opurl}.</p></div></div></body></html>`;
|
||||
`please contact the sender ${creatorEmail} directly. If you think this email is inappropriate or spam, you may file a complaints with ${TenantAppName}${opurl}.</p></div></div></body></html>`;
|
||||
|
||||
const params = {
|
||||
extUserId: sender.objectId,
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { cloudServerUrl, serverAppId } from '../../Utils.js';
|
||||
import reportJson from './reportsJson.js';
|
||||
import reportJson, { applySearch } from './reportsJson.js';
|
||||
import axios from 'axios';
|
||||
|
||||
// Escape regex special characters. Copied from filterDocs.js
|
||||
function escapeRegExp(str) {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
function buildClassesUrl({ serverUrl, clsName, paramsObj, keys, orderBy, skip, limit, include }) {
|
||||
const url = new URL(`${serverUrl}/classes/${clsName}`);
|
||||
url.searchParams.set('where', JSON.stringify(paramsObj));
|
||||
url.searchParams.set('keys', keys.join(','));
|
||||
url.searchParams.set('order', orderBy);
|
||||
url.searchParams.set('skip', String(skip));
|
||||
url.searchParams.set('limit', String(limit));
|
||||
if (include) url.searchParams.set('include', include);
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
export default async function getReport(request) {
|
||||
const reportId = request.params.reportId;
|
||||
const limit = request.params.limit;
|
||||
@@ -25,78 +29,76 @@ export default async function getReport(request) {
|
||||
},
|
||||
});
|
||||
const userId = userRes.data && userRes.data.objectId;
|
||||
if (userId) {
|
||||
const json = reportId && reportJson(reportId, userId);
|
||||
const clsName = json?.reportClass ? json.reportClass : 'contracts_Document';
|
||||
if (json) {
|
||||
const { params, keys } = json;
|
||||
const orderBy = '-updatedAt';
|
||||
const strKeys = keys.join();
|
||||
let paramsObj = { ...params };
|
||||
if (reportId == '6TeaPr321t') {
|
||||
const extUserQuery = new Parse.Query('contracts_Users');
|
||||
extUserQuery.equalTo('Email', userRes.data.email);
|
||||
extUserQuery.include('TeamIds');
|
||||
const extUser = await extUserQuery.first({ useMasterKey: true });
|
||||
if (extUser) {
|
||||
const _extUser = JSON.parse(JSON.stringify(extUser));
|
||||
if (_extUser?.TeamIds && _extUser.TeamIds?.length > 0) {
|
||||
let teamArr = [];
|
||||
_extUser?.TeamIds?.forEach(x => (teamArr = [...teamArr, ...x.Ancestors]));
|
||||
paramsObj = {
|
||||
...paramsObj,
|
||||
$or: [
|
||||
{ SharedWith: { $in: teamArr } },
|
||||
{
|
||||
ExtUserPtr: {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Users',
|
||||
objectId: extUser.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
SharedWithUsers: {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Users',
|
||||
objectId: extUser.id,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
} else {
|
||||
paramsObj = {
|
||||
...paramsObj,
|
||||
CreatedBy: { __type: 'Pointer', className: '_User', objectId: userId },
|
||||
};
|
||||
}
|
||||
}
|
||||
if (!userId) {
|
||||
return { error: 'Invalid session token' };
|
||||
}
|
||||
const json = reportId && reportJson(reportId, userId);
|
||||
if (json) {
|
||||
let paramsObj = { ...(json.params || {}) };
|
||||
if (reportId == '6TeaPr321t') {
|
||||
const extUserQuery = new Parse.Query('contracts_Users');
|
||||
extUserQuery.equalTo('Email', userRes.data.email);
|
||||
extUserQuery.include('TeamIds');
|
||||
const extUser = await extUserQuery.first({ useMasterKey: true });
|
||||
const userPtr = { __type: 'Pointer', className: '_User', objectId: userId };
|
||||
if (!extUser) {
|
||||
paramsObj = { ...paramsObj, CreatedBy: userPtr };
|
||||
}
|
||||
if (searchTerm) {
|
||||
const escaped = escapeRegExp(searchTerm);
|
||||
const _extUser = JSON.parse(JSON.stringify(extUser));
|
||||
const extPtr = { __type: 'Pointer', className: 'contracts_Users', objectId: extUser.id };
|
||||
if (_extUser?.TeamIds && _extUser.TeamIds?.length > 0) {
|
||||
// Collect ancestors efficiently + de-dupe
|
||||
const teamSet = new Set();
|
||||
for (const team of _extUser?.TeamIds) {
|
||||
const ancestors = team.Ancestors || [];
|
||||
for (const a of ancestors) teamSet.add(a);
|
||||
}
|
||||
const teamArr = [...teamSet];
|
||||
paramsObj = {
|
||||
...paramsObj,
|
||||
Name: { $regex: `.*${escaped}.*`, $options: 'i' },
|
||||
$or: [
|
||||
{ SharedWith: { $in: teamArr } },
|
||||
{ ExtUserPtr: extPtr },
|
||||
{ SharedWithUsers: extPtr },
|
||||
],
|
||||
};
|
||||
}
|
||||
const strParams = JSON.stringify(paramsObj);
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Master-Key': masterKey,
|
||||
};
|
||||
const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr,Placeholders.signerPtr,ExtUserPtr.TenantId`;
|
||||
const res = await axios.get(url, { headers: headers });
|
||||
if (res.data && res.data.results) {
|
||||
return res.data.results;
|
||||
} else {
|
||||
return [];
|
||||
paramsObj = { ...paramsObj, CreatedBy: userPtr };
|
||||
}
|
||||
} else {
|
||||
return { error: 'Report is not available!' };
|
||||
}
|
||||
paramsObj = applySearch({ reportId, baseWhere: paramsObj, searchTerm });
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Master-Key': masterKey,
|
||||
};
|
||||
|
||||
const clsName = json?.reportClass ? json.reportClass : 'contracts_Document';
|
||||
const orderBy = '-updatedAt';
|
||||
const include = 'AuditTrail.UserPtr,Placeholders.signerPtr,ExtUserPtr.TenantId';
|
||||
|
||||
const url = buildClassesUrl({
|
||||
serverUrl,
|
||||
clsName,
|
||||
paramsObj,
|
||||
keys: json.keys || [],
|
||||
orderBy,
|
||||
skip,
|
||||
limit,
|
||||
include,
|
||||
});
|
||||
const res = await axios.get(url, { headers: headers });
|
||||
if (res.data && res.data.results) {
|
||||
return res.data.results;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
return { error: 'Report is not available!' };
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err', err.message);
|
||||
const message = err?.response?.data?.error || err?.message || 'Something went wrong';
|
||||
console.log('getreport error:', message);
|
||||
if (err.code == 209) {
|
||||
return { error: 'Invalid session token' };
|
||||
} else {
|
||||
|
||||
@@ -122,7 +122,7 @@ async function sendNotifyMail(doc, signUser, mailProvider, publicUrl) {
|
||||
const TenantAppName = appName;
|
||||
const logo =
|
||||
"<img src='https://qikinnovation.ams3.digitaloceanspaces.com/logo.png' height='50' style='padding:20px'/>";
|
||||
const opurl = ` <a href=www.opensignlabs.com target=_blank>here</a>`;
|
||||
const opurl = ` <a href='mailto:complaint@opensiglabs.com' target=_blank>here</a>`;
|
||||
const auditTrailCount = doc?.AuditTrail?.filter(x => x.Activity === 'Signed')?.length || 0;
|
||||
const removePrefill =
|
||||
doc?.Placeholders?.length > 0 && doc?.Placeholders?.filter(x => x?.Role !== 'prefill');
|
||||
@@ -142,7 +142,7 @@ async function sendNotifyMail(doc, signUser, mailProvider, publicUrl) {
|
||||
`<div>${logo}</div><div style='padding:2px;font-family:system-ui;background-color:#47a3ad'><p style='font-size:20px;font-weight:400;color:white;padding-left:20px'>Document signed by ${signerName}</p>` +
|
||||
`</div><div style='padding:20px;font-family:system-ui;font-size:14px'><p>Dear ${creatorName},</p><p>${pdfName} has been signed by ${signerName} "${signerEmail}" successfully</p>` +
|
||||
`<p><a href=${viewDocUrl} target=_blank>View Document</a></p></div></div><div><p>This is an automated email from ${TenantAppName}. For any queries regarding this email, ` +
|
||||
`please contact the sender ${creatorEmail} directly. If you think this email is inappropriate or spam, you may file a complaint with ${TenantAppName}${opurl}.</p></div></div></body></html>`;
|
||||
`please contact the sender ${creatorEmail} directly. If you think this email is inappropriate or spam, you may file a complaints with ${TenantAppName}${opurl}.</p></div></div></body></html>`;
|
||||
|
||||
const params = {
|
||||
extUserId: sender.objectId,
|
||||
@@ -169,7 +169,7 @@ async function sendCompletedMail(obj) {
|
||||
const TenantAppName = appName;
|
||||
const logo =
|
||||
"<img src='https://qikinnovation.ams3.digitaloceanspaces.com/logo.png' height='50' style='padding:20px'/>";
|
||||
const opurl = ` <a href=www.opensignlabs.com target=_blank>here</a>`;
|
||||
const opurl = ` <a href='mailto:complaint@opensiglabs.com' target=_blank>here</a>`;
|
||||
let signersMail;
|
||||
if (doc?.Signers?.length > 0) {
|
||||
const isOwnerExistsinSigners = doc?.Signers?.find(x => x.Email === sender.Email);
|
||||
@@ -186,7 +186,7 @@ async function sendCompletedMail(obj) {
|
||||
`<div>${logo}</div><div style='padding:2px;font-family:system-ui;background-color:#47a3ad'><p style='font-size:20px;font-weight:400;color:white;padding-left:20px'>Document signed successfully</p></div><div>` +
|
||||
`<p style='padding:20px;font-family:system-ui;font-size:14px'>All parties have successfully signed the document <b>"${pdfName}"</b>. Kindly download the document from the attachment.</p>` +
|
||||
`</div></div><div><p>This is an automated email from ${TenantAppName}. For any queries regarding this email, please contact the sender ${sender.Email} directly.` +
|
||||
`If you think this email is inappropriate or spam, you may file a complaint with ${TenantAppName}${opurl}.</p></div></div></body></html>`;
|
||||
`If you think this email is inappropriate or spam, you may file a complaints with ${TenantAppName}${opurl}.</p></div></div></body></html>`;
|
||||
|
||||
if (obj?.isCustomMail) {
|
||||
const tenant = sender?.TenantId;
|
||||
|
||||
@@ -98,11 +98,6 @@ export default function reportJson(id, currentUserId) {
|
||||
IsCompleted: true,
|
||||
IsDeclined: { $ne: true },
|
||||
IsArchive: { $ne: true },
|
||||
// CreatedBy: {
|
||||
// __type: 'Pointer',
|
||||
// className: '_User',
|
||||
// objectId: currentUserId,
|
||||
// },
|
||||
$or: [
|
||||
// Condition 1: If `CreatedBy` exists, no need for `Signers` filter
|
||||
{ CreatedBy: { __type: 'Pointer', className: '_User', objectId: currentUserId } },
|
||||
@@ -230,3 +225,36 @@ export default function reportJson(id, currentUserId) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Escape regex special characters. Copied from filterDocs.js
|
||||
function escapeRegExp(str) {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies searchTerm rules; combines existing access $or with search $or using $and.
|
||||
*/
|
||||
export function applySearch({ reportId, baseWhere, searchTerm }) {
|
||||
if (!searchTerm) return baseWhere;
|
||||
|
||||
const escaped = escapeRegExp(searchTerm);
|
||||
const nameMatch = { Name: { $regex: `.*${escaped}.*`, $options: 'i' } };
|
||||
const emailMatch = { Email: { $regex: `.*${escaped}.*`, $options: 'i' } };
|
||||
|
||||
if (reportId === 'contacts') {
|
||||
return { ...baseWhere, $or: [nameMatch, emailMatch] };
|
||||
}
|
||||
|
||||
const searchOr = [
|
||||
nameMatch,
|
||||
{ Signers: { $inQuery: { className: 'contracts_Contactbook', where: emailMatch } } },
|
||||
];
|
||||
|
||||
// If baseWhere already has an access-control $or, combine using $and
|
||||
if (baseWhere.$or) {
|
||||
const { $or: accessOr, ...rest } = baseWhere;
|
||||
return { ...rest, $and: [{ $or: accessOr }, { $or: searchOr }] };
|
||||
}
|
||||
|
||||
return { ...baseWhere, $or: searchOr };
|
||||
}
|
||||
|
||||
@@ -58,15 +58,20 @@ async function sendMailProvider(req, plan, monthchange) {
|
||||
});
|
||||
} else {
|
||||
const httpsAgent = new https.Agent({ rejectUnauthorized: false }); // Disable SSL validation
|
||||
const localUrl = req.params.url;
|
||||
const newlocalUrl = localUrl.replace(
|
||||
'https://localhost:3001/api',
|
||||
'http://localhost:8080'
|
||||
);
|
||||
axios
|
||||
.get(req.params.url, { responseType: 'stream', httpsAgent })
|
||||
.get(newlocalUrl, { responseType: 'stream', httpsAgent: httpsAgent })
|
||||
.then(response => {
|
||||
response.data.pipe(Pdf);
|
||||
Pdf.on('finish', () => resolve('success'));
|
||||
Pdf.on('error', () => resolve('error'));
|
||||
})
|
||||
.catch(e => {
|
||||
console.log('error', e.message);
|
||||
console.log('error in localurl', e.message);
|
||||
resolve('error');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
export default async function setWidgetPreferences(request) {
|
||||
if (!request?.user) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||
}
|
||||
const dateWidgetParams = request?.params?.dateWidget;
|
||||
if (!dateWidgetParams || Object.keys(dateWidgetParams).length === 0) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Please provide parameters.');
|
||||
}
|
||||
try {
|
||||
const orgQuery = new Parse.Query('contracts_Users');
|
||||
orgQuery.equalTo('UserId', request.user);
|
||||
const userObj = await orgQuery.first({ useMasterKey: true });
|
||||
if (!userObj) {
|
||||
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'Permission denied.');
|
||||
}
|
||||
|
||||
const widgetPreferencesRaw = userObj?.get('WidgetPreferences');
|
||||
const widgetPreferences = Array.isArray(widgetPreferencesRaw) ? widgetPreferencesRaw : [];
|
||||
|
||||
// Normalize booleans (simple + safe)
|
||||
const dateWidget = {
|
||||
type: 'date',
|
||||
isSigningDate: !!dateWidgetParams.isSigningDate,
|
||||
isReadOnly: !!dateWidgetParams.isReadOnly,
|
||||
date: dateWidgetParams?.isSigningDate ? '' : dateWidgetParams?.date || '',
|
||||
format: dateWidgetParams.format || 'MM/dd/yyyy',
|
||||
};
|
||||
|
||||
// Upsert: replace if exists, otherwise append
|
||||
const updatedWidgetPreferences =
|
||||
widgetPreferences?.length > 0
|
||||
? widgetPreferences.map(w => (w.type === 'date' ? dateWidget : w))
|
||||
: [...widgetPreferences, dateWidget];
|
||||
|
||||
userObj.set('WidgetPreferences', updatedWidgetPreferences);
|
||||
const saved = await userObj.save(null, { useMasterKey: true });
|
||||
if (saved) {
|
||||
const response = typeof saved.toJSON === 'function' ? saved.toJSON() : saved;
|
||||
return {
|
||||
WidgetPreferences: response.WidgetPreferences,
|
||||
updatedAt: response.updatedAt,
|
||||
createdAt: response.createdAt,
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('set widget preferences error:', err);
|
||||
throw new Parse.Error(err?.code || 400, err?.message || 'Something went wrong.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user