mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-20 06:35:54 +02:00
Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into fix_smtp
This commit is contained in:
@@ -8,7 +8,9 @@ async function ContractUsersAftersave(request) {
|
||||
contactbook.set('Name', request.object.get('Name'));
|
||||
contactbook.set('Email', request.object.get('Email'));
|
||||
contactbook.set('ExtUserPtr', request.object.get('objectId'));
|
||||
contactbook.set('Phone', request.object.get('Phone'));
|
||||
if (request.object?.get('Phone')) {
|
||||
contactbook.set('Phone', request.object.get('Phone'));
|
||||
}
|
||||
contactbook.set('ExtUserPtr', {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Users',
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
export default async function CreatePublicTemplate(request) {
|
||||
const templateid = request.params.templateid;
|
||||
const ispublic = request.params.ispublic;
|
||||
const publicrole = request.params.publicrole;
|
||||
try {
|
||||
if (!request?.user) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||
} else {
|
||||
const userId = request?.user && request?.user?.id;
|
||||
if (templateid) {
|
||||
const updateTemplate = new Parse.Object('contracts_Template');
|
||||
updateTemplate.id = templateid;
|
||||
if (ispublic) {
|
||||
updateTemplate.set('PublicRole', publicrole);
|
||||
}
|
||||
updateTemplate.set('IsPublic', ispublic);
|
||||
const Acl = new Parse.ACL();
|
||||
if (ispublic) {
|
||||
Acl.setPublicReadAccess(true);
|
||||
}
|
||||
Acl.setReadAccess(userId, true);
|
||||
Acl.setWriteAccess(userId, true);
|
||||
updateTemplate.setACL(Acl);
|
||||
const savedObject = await updateTemplate.save(null, { useMasterKey: true });
|
||||
const res = savedObject.toJSON();
|
||||
if (res) {
|
||||
return {
|
||||
status: 'success',
|
||||
};
|
||||
}
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Please provide required parameters!');
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const code = err.code || 400;
|
||||
const msg = err.message;
|
||||
const error = new Parse.Error(code, msg);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -14,19 +14,29 @@ async function DocumentAftersave(request) {
|
||||
const updateQuery = await documentQuery.get(request.object.id, { useMasterKey: true });
|
||||
updateQuery.set('ExpiryDate', ExpiryDate);
|
||||
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);
|
||||
// console.log("ExpiryDate")
|
||||
// console.log(ExpiryDate)
|
||||
ExpiryDate.setDate(ExpiryDate.getDate() + TimeToCompleteDays);
|
||||
// console.log("ExpiryDate date after update")
|
||||
// console.log(ExpiryDate)
|
||||
const documentQuery = new Parse.Query('contracts_Document');
|
||||
const updateQuery = await documentQuery.get(request.object.id, { useMasterKey: true });
|
||||
updateQuery.set('ExpiryDate', ExpiryDate);
|
||||
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 });
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import axios from "axios";
|
||||
import axios from 'axios';
|
||||
|
||||
const serverUrl = process.env.SERVER_URL;
|
||||
const APPID = process.env.APP_ID;
|
||||
@@ -18,23 +18,23 @@ export default async function FacebookSign(request) {
|
||||
const userGoogleId = request.params.Id;
|
||||
const userAccessToken = request.params.AccessToken;
|
||||
const userEmail = request.params.Email;
|
||||
const phone = request.params.Phone;
|
||||
const phone = request.params?.Phone || '';
|
||||
const name = request.params.Name;
|
||||
const authData = {
|
||||
facebook: { id: userGoogleId, access_token: userAccessToken },
|
||||
};
|
||||
const userQuery = new Parse.Query(Parse.User);
|
||||
userQuery.equalTo("email", userEmail);
|
||||
userQuery.equalTo('email', userEmail);
|
||||
const res = await userQuery.first({ useMasterKey: true });
|
||||
if (res) {
|
||||
try {
|
||||
const SignIn = await axios.put(
|
||||
serverUrl + "/users/" + res.id,
|
||||
serverUrl + '/users/' + res.id,
|
||||
{ authData: authData },
|
||||
{
|
||||
headers: {
|
||||
"X-Parse-Application-Id": APPID,
|
||||
"X-Parse-Master-key": masterKEY,
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Master-key': masterKEY,
|
||||
},
|
||||
}
|
||||
);
|
||||
@@ -42,22 +42,22 @@ export default async function FacebookSign(request) {
|
||||
if (SignIn.data) {
|
||||
// console.log("google Sign in", SignIn);
|
||||
const sessiontoken = SignIn.data.sessionToken;
|
||||
console.log("Google sessiontoken", sessiontoken);
|
||||
console.log('Google sessiontoken', sessiontoken);
|
||||
return {
|
||||
email: userEmail,
|
||||
message: "User Sign In",
|
||||
message: 'User Sign In',
|
||||
sessiontoken: sessiontoken,
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err in user google sign in", err);
|
||||
return { message: "Internal server error" };
|
||||
console.log('err in user google sign in', err);
|
||||
return { message: 'Internal server error' };
|
||||
}
|
||||
} else {
|
||||
// console.log("in sign up condition");
|
||||
try {
|
||||
const SignUp = await axios.post(
|
||||
serverUrl + "/users",
|
||||
serverUrl + '/users',
|
||||
{
|
||||
authData: authData,
|
||||
username: userEmail,
|
||||
@@ -67,8 +67,8 @@ export default async function FacebookSign(request) {
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
"X-Parse-Application-Id": APPID,
|
||||
"X-Parse-Revocable-Session": "1",
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Revocable-Session': '1',
|
||||
},
|
||||
}
|
||||
);
|
||||
@@ -79,14 +79,14 @@ export default async function FacebookSign(request) {
|
||||
const sessiontoken = SignUp.data.sessionToken;
|
||||
const payload = {
|
||||
email: userEmail,
|
||||
message: "User Sign Up",
|
||||
message: 'User Sign Up',
|
||||
sessiontoken: sessiontoken,
|
||||
};
|
||||
return payload;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err in user google sign up", err);
|
||||
return { message: "Internal server err" };
|
||||
console.log('err in user google sign up', err);
|
||||
return { message: 'Internal server err' };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
async function GetPublicTemplate(request) {
|
||||
try {
|
||||
const username = request.params.username;
|
||||
if (username) {
|
||||
const extUserQuery = new Parse.Query('contracts_Users');
|
||||
extUserQuery.equalTo('UserName', username);
|
||||
const res = await extUserQuery.first({ useMasterKey: true });
|
||||
const userId = res.get('UserId').id;
|
||||
if (userId) {
|
||||
const templatQuery = new Parse.Query('contracts_Template');
|
||||
templatQuery.equalTo('CreatedBy', {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: userId,
|
||||
});
|
||||
templatQuery.equalTo('IsPublic', true);
|
||||
const getTemplate = await templatQuery.find({ useMasterKey: true });
|
||||
return getTemplate;
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Template not found');
|
||||
}
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Please provide required parameters!');
|
||||
}
|
||||
} catch (err) {
|
||||
const code = err.code || 400;
|
||||
const msg = err.message;
|
||||
const error = new Parse.Error(code, msg);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
export default GetPublicTemplate;
|
||||
@@ -0,0 +1,23 @@
|
||||
async function GetPublicUserName(request) {
|
||||
try {
|
||||
if (!request?.user) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||
} else {
|
||||
const username = request.params.username;
|
||||
if (username) {
|
||||
const userQuery = new Parse.Query('contracts_Users');
|
||||
userQuery.equalTo('UserName', username);
|
||||
const res = await userQuery.first({ useMasterKey: true });
|
||||
return res;
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Please provide required parameters!');
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const code = err.code || 400;
|
||||
const msg = err.message;
|
||||
const error = new Parse.Error(code, msg);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
export default GetPublicUserName;
|
||||
@@ -26,7 +26,7 @@ export default async function GetTemplate(request) {
|
||||
if (res) {
|
||||
// console.log("res ",res)
|
||||
const acl = res.getACL();
|
||||
console.log("acl", acl.getReadAccess(userId))
|
||||
// console.log("acl", acl.getReadAccess(userId))
|
||||
if (acl && acl.getReadAccess(userId)) {
|
||||
return res;
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import axios from "axios";
|
||||
import axios from 'axios';
|
||||
|
||||
const serverUrl = process.env.SERVER_URL;
|
||||
const APPID = process.env.APP_ID;
|
||||
@@ -9,8 +9,8 @@ const masterKEY = process.env.MASTER_KEY;
|
||||
* @param Id It is google Id
|
||||
* @param TokenId It is google token Id
|
||||
* @param Gmail It is user's gmail with user sign in/sign up
|
||||
* @param Phone It is user's Phone number
|
||||
* @param Name It is user's Name
|
||||
* @param Phone It is user's Phone number
|
||||
* @param Name It is user's Name
|
||||
* @returns if success {email, message, sessiontoken} else on reject {message}
|
||||
*/
|
||||
|
||||
@@ -18,21 +18,21 @@ export default async function GoogleSign(request) {
|
||||
const userGoogleId = request.params.Id;
|
||||
const userTokenId = request.params.TokenId;
|
||||
const userEmail = request.params.Gmail;
|
||||
const phone = request.params.Phone;
|
||||
const phone = request.params?.Phone || '';
|
||||
const name = request.params.Name;
|
||||
const authData = { google: { id: userGoogleId, id_token: userTokenId } };
|
||||
const userQuery = new Parse.Query(Parse.User);
|
||||
userQuery.equalTo("email", userEmail);
|
||||
userQuery.equalTo('email', userEmail);
|
||||
const res = await userQuery.first({ useMasterKey: true });
|
||||
if (res) {
|
||||
try {
|
||||
const SignIn = await axios.put(
|
||||
serverUrl + "/users/" + res.id,
|
||||
serverUrl + '/users/' + res.id,
|
||||
{ authData: authData },
|
||||
{
|
||||
headers: {
|
||||
"X-Parse-Application-Id": APPID,
|
||||
"X-Parse-Master-key": masterKEY,
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Master-key': masterKEY,
|
||||
},
|
||||
}
|
||||
);
|
||||
@@ -40,22 +40,22 @@ export default async function GoogleSign(request) {
|
||||
if (SignIn.data) {
|
||||
// console.log("google Sign in", SignIn);
|
||||
const sessiontoken = SignIn.data.sessionToken;
|
||||
console.log("Google sessiontoken", sessiontoken);
|
||||
console.log('Google sessiontoken', sessiontoken);
|
||||
return {
|
||||
email: userEmail,
|
||||
message: "User Sign In",
|
||||
message: 'User Sign In',
|
||||
sessiontoken: sessiontoken,
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err in user google sign in", err);
|
||||
return { message: "Internal server error" };
|
||||
console.log('err in user google sign in', err);
|
||||
return { message: 'Internal server error' };
|
||||
}
|
||||
} else {
|
||||
// console.log("in sign up condition");
|
||||
try {
|
||||
const SignUp = await axios.post(
|
||||
serverUrl + "/users",
|
||||
serverUrl + '/users',
|
||||
{
|
||||
authData: authData,
|
||||
username: userEmail,
|
||||
@@ -65,8 +65,8 @@ export default async function GoogleSign(request) {
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
"X-Parse-Application-Id": APPID,
|
||||
"X-Parse-Revocable-Session": "1",
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Revocable-Session': '1',
|
||||
},
|
||||
}
|
||||
);
|
||||
@@ -77,14 +77,14 @@ export default async function GoogleSign(request) {
|
||||
const sessiontoken = SignUp.data.sessionToken;
|
||||
const payload = {
|
||||
email: userEmail,
|
||||
message: "User Sign Up",
|
||||
message: 'User Sign Up',
|
||||
sessiontoken: sessiontoken,
|
||||
};
|
||||
return payload;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err in user google sign up", err);
|
||||
return { message: "Internal server err" };
|
||||
console.log('err in user google sign up', err);
|
||||
return { message: 'Internal server err' };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@ export default async function TemplateAfterSave(request) {
|
||||
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;
|
||||
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);
|
||||
await request.object.save(null, { useMasterKey: true });
|
||||
}
|
||||
if (signers && signers.length > 0) {
|
||||
await updateAclDoc(request.object.id);
|
||||
} else {
|
||||
|
||||
@@ -2,41 +2,41 @@
|
||||
|
||||
//-- Export Modules
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
import axios from "axios";
|
||||
dotenv.config();
|
||||
import axios from 'axios';
|
||||
|
||||
export async function getUserGroups(request) {
|
||||
try {
|
||||
var appname = request.params.appname;
|
||||
if (appname == "") {
|
||||
return Promise.reject("Error:please provide appname");
|
||||
if (appname == '') {
|
||||
return Promise.reject('Error:please provide appname');
|
||||
}
|
||||
var response = {};
|
||||
var rolelist = {};
|
||||
appname = appname + "_";
|
||||
appname = appname + '_';
|
||||
//--function to get the userid from session token
|
||||
function getuserid(request) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const options = {
|
||||
url: process.env.SERVER_URL + "/users/me",
|
||||
method: "get",
|
||||
url: process.env.SERVER_URL + '/users/me',
|
||||
method: 'get',
|
||||
headers: {
|
||||
"X-Parse-Application-Id": process.env.APP_ID,
|
||||
"X-Parse-Session-Token": request.headers["sessiontoken"],
|
||||
'X-Parse-Application-Id': process.env.APP_ID,
|
||||
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
||||
},
|
||||
};
|
||||
|
||||
axios(options)
|
||||
.then((x) => {
|
||||
.then(x => {
|
||||
const body = x.data;
|
||||
var error = body == "" ? true : false;
|
||||
var error = body == '' ? true : false;
|
||||
if (error) {
|
||||
reject("result not found!");
|
||||
reject('result not found!');
|
||||
} else {
|
||||
resolve(body);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
@@ -46,7 +46,7 @@ export async function getUserGroups(request) {
|
||||
}
|
||||
var userData = await getuserid(request);
|
||||
var userid = userData.objectId;
|
||||
console.log("userid " + userid);
|
||||
// console.log("userid " + userid);
|
||||
var url =
|
||||
process.env.SERVER_URL +
|
||||
'/roles?where={"users":{"__type":"Pointer","className":"_User","objectId":"' +
|
||||
@@ -60,29 +60,29 @@ export async function getUserGroups(request) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const options = {
|
||||
url: url,
|
||||
method: "get",
|
||||
method: 'get',
|
||||
headers: {
|
||||
"X-Parse-Application-Id": process.env.APP_ID,
|
||||
'X-Parse-Application-Id': process.env.APP_ID,
|
||||
},
|
||||
};
|
||||
|
||||
axios(options)
|
||||
.then((x) => {
|
||||
.then(x => {
|
||||
const body = x.data;
|
||||
var roleres = [];
|
||||
for (var i = 0; i < body["results"].length; i++) {
|
||||
var rolename = body["results"][i]["name"];
|
||||
for (var i = 0; i < body['results'].length; i++) {
|
||||
var rolename = body['results'][i]['name'];
|
||||
//var roleprefix = rolename.split("_")[0];
|
||||
roleres.push(rolename);
|
||||
}
|
||||
var error = roleres == "" ? true : false;
|
||||
var error = roleres == '' ? true : false;
|
||||
if (error) {
|
||||
reject("result not found!");
|
||||
reject('result not found!');
|
||||
} else {
|
||||
resolve(roleres);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
@@ -92,7 +92,7 @@ export async function getUserGroups(request) {
|
||||
}
|
||||
|
||||
rolelist = await getRoleList(request);
|
||||
console.log(rolelist);
|
||||
// console.log(rolelist);
|
||||
//--check user roles according to appId
|
||||
var rolesInapp = [];
|
||||
for (let i = 0; i < rolelist.length; i++) {
|
||||
@@ -102,11 +102,11 @@ export async function getUserGroups(request) {
|
||||
rolesInapp.push(rolelist[i]);
|
||||
}
|
||||
}
|
||||
console.log(rolesInapp);
|
||||
// console.log(rolesInapp);
|
||||
return rolesInapp;
|
||||
} catch (err) {
|
||||
console.log("err in usergroup");
|
||||
console.log('err in usergroup');
|
||||
console.log(err);
|
||||
return Promise.reject("Error:Result not found");
|
||||
return Promise.reject('Error:Result not found');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,15 @@ export default async function ZohoDetails(request) {
|
||||
// console.log("Access Token:", res.data);
|
||||
if (res.data.access_token) {
|
||||
const hostedpages = request.params.hostedpagesId;
|
||||
const userData = await axios.get('https://billing.zoho.in/api/v1/hostedpages/' + hostedpages, {
|
||||
headers: {
|
||||
Authorization: 'Zoho-oauthtoken ' + res.data.access_token,
|
||||
'X-com-zoho-subscriptions-organizationid': process.env.ZOHO_BILLING_ORG_ID,
|
||||
},
|
||||
});
|
||||
const userData = await axios.get(
|
||||
'https://www.zohoapis.in/billing/v1/hostedpages/' + hostedpages,
|
||||
{
|
||||
headers: {
|
||||
Authorization: 'Zoho-oauthtoken ' + res.data.access_token,
|
||||
'X-com-zoho-subscriptions-organizationid': process.env.ZOHO_BILLING_ORG_ID,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const first_name = userData.data.data.subscription.contactpersons[0].first_name || '';
|
||||
const last_name = userData.data.data.subscription.contactpersons[0].last_name || '';
|
||||
@@ -44,7 +47,7 @@ export default async function ZohoDetails(request) {
|
||||
userData.data.data.subscription.customer.cd_job_title) ||
|
||||
'';
|
||||
const resData = {
|
||||
phone: userData.data.data.subscription.contactpersons[0].mobile,
|
||||
phone: userData.data.data.subscription.contactpersons[0]?.mobile || '',
|
||||
name: first_name + ' ' + last_name,
|
||||
email: userData.data.data.subscription.contactpersons[0].email,
|
||||
nextBillingDate: userData.data.data.subscription.next_billing_at,
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
import axios from 'axios';
|
||||
|
||||
const serverUrl = process.env.SERVER_URL;
|
||||
const appId = process.env.APP_ID;
|
||||
|
||||
async function sendMail(document, sessionToken) {
|
||||
const baseUrl = new URL(process.env.PUBLIC_URL);
|
||||
|
||||
// console.log("pdfDetails", pdfDetails);
|
||||
const timeToCompleteDays = document?.TimeToCompleteDays || 15;
|
||||
const ExpireDate = new Date(document.createdAt);
|
||||
ExpireDate.setDate(ExpireDate.getDate() + timeToCompleteDays);
|
||||
const newDate = ExpireDate;
|
||||
const localExpireDate = newDate.toLocaleDateString('en-US', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
});
|
||||
const sender = document.ExtUserPtr.Email;
|
||||
let signerMail = document.Placeholders;
|
||||
|
||||
if (document.SendinOrder) {
|
||||
signerMail = signerMail.slice();
|
||||
signerMail.splice(1);
|
||||
}
|
||||
for (let i = 0; i < signerMail.length; i++) {
|
||||
try {
|
||||
const imgPng = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png';
|
||||
let url = `${serverUrl}/functions/sendmailv3`;
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': appId,
|
||||
sessionToken: sessionToken,
|
||||
};
|
||||
const objectId = signerMail[i]?.signerObjId;
|
||||
const hostUrl = baseUrl.origin;
|
||||
let encodeBase64;
|
||||
let existSigner = {};
|
||||
if (objectId) {
|
||||
existSigner = document?.Signers?.find(user => user.objectId === objectId);
|
||||
encodeBase64 = btoa(`${document.objectId}/${existSigner?.Email}/${objectId}`);
|
||||
} else {
|
||||
encodeBase64 = btoa(`${document.objectId}/${signerMail[i].email}`);
|
||||
}
|
||||
let signPdf = `${hostUrl}/login/${encodeBase64}`;
|
||||
const openSignUrl = 'https://www.opensignlabs.com/';
|
||||
const orgName = document.ExtUserPtr.Company ? document.ExtUserPtr.Company : '';
|
||||
const themeBGcolor = '#47a3ad';
|
||||
let params = {
|
||||
extUserId: document.ExtUserPtr.objectId,
|
||||
recipient: objectId ? existSigner?.Email : signerMail[i].email,
|
||||
subject: `${document.ExtUserPtr.Name} has requested you to sign "${document.Name}"`,
|
||||
mailProvider: document?.ExtUserPtr?.active_mail_adapter || '',
|
||||
from: sender,
|
||||
html:
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> </head> <body> <div style='background-color: #f5f5f5; padding: 20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background: white;padding-bottom: 20px;'> <div style='padding:10px 10px 0 10px'><img src='" +
|
||||
imgPng +
|
||||
"' height='50' style='padding:20px; width:170px; height:40px;' /></div><div style='padding: 2px;font-family: system-ui;background-color:" +
|
||||
themeBGcolor +
|
||||
";'><p style='font-size: 20px;font-weight: 400;color: white;padding-left: 20px;' > Digital Signature Request</p></div><div><p style='padding: 20px;font-family: system-ui;font-size: 14px; margin-bottom: 10px;'> " +
|
||||
document.ExtUserPtr.Name +
|
||||
' has requested you to review and sign <strong> ' +
|
||||
document.Name +
|
||||
"</strong>.</p><div style='padding: 5px 0px 5px 25px;display: flex;flex-direction: row;justify-content: space-around;'><table> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td> <td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||
sender +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td> <td> </td><td style='color:#626363;font-weight:bold'> " +
|
||||
orgName +
|
||||
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||
localExpireDate +
|
||||
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" +
|
||||
signPdf +
|
||||
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px;'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||
sender +
|
||||
' directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=' +
|
||||
openSignUrl +
|
||||
' target=_blank>here</a>.</p> </div></div></body> </html>',
|
||||
};
|
||||
const sendMail = await axios.post(url, params, { headers: headers });
|
||||
// if (sendMail.data.result.status === 'success') {
|
||||
// console.log('batch login mail sent');
|
||||
// }
|
||||
} catch (error) {
|
||||
console.log('error', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
export default async function createBatchDocs(request) {
|
||||
const strDocuments = request.params.Documents;
|
||||
const sessionToken = request.headers['sessiontoken'];
|
||||
const Documents = JSON.parse(strDocuments);
|
||||
const Ip = request?.headers?.['x-real-ip'] || '';
|
||||
// console.log('Documents ', Documents);
|
||||
const parseConfig = {
|
||||
baseURL: serverUrl, //localStorage.getItem('baseUrl'),
|
||||
headers: {
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Session-Token': sessionToken,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
};
|
||||
try {
|
||||
const requests = Documents.map(x => {
|
||||
const Signers = x.Signers;
|
||||
const allSigner = x?.Placeholders?.map(
|
||||
item => Signers?.find(e => item?.signerPtr?.objectId === e?.objectId) || item?.signerPtr
|
||||
).filter(signer => Object.keys(signer).length > 0);
|
||||
const date = new Date();
|
||||
const isoDate = date.toISOString();
|
||||
let Acl = { [x.CreatedBy.objectId]: { read: true, write: true } };
|
||||
if (allSigner && allSigner.length > 0) {
|
||||
allSigner.forEach(x => {
|
||||
const obj = { [x.CreatedBy.objectId]: { read: true, write: true } };
|
||||
Acl = { ...Acl, ...obj };
|
||||
});
|
||||
}
|
||||
return {
|
||||
method: 'POST',
|
||||
path: '/app/classes/contracts_Document',
|
||||
body: {
|
||||
Name: x.Name,
|
||||
URL: x.URL,
|
||||
Note: x.Note,
|
||||
Description: x.Description,
|
||||
CreatedBy: x.CreatedBy,
|
||||
SendinOrder: x.SendinOrder || true,
|
||||
ExtUserPtr: {
|
||||
__type: 'Pointer',
|
||||
className: x.ExtUserPtr.className,
|
||||
objectId: x.ExtUserPtr.objectId,
|
||||
},
|
||||
Placeholders: x.Placeholders.map(y =>
|
||||
y?.signerPtr?.objectId
|
||||
? {
|
||||
...y,
|
||||
signerPtr: {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Contactbook',
|
||||
objectId: y.signerPtr.objectId,
|
||||
},
|
||||
signerObjId: y.signerObjId,
|
||||
}
|
||||
: { ...y, signerPtr: {}, signerObjId: '' }
|
||||
),
|
||||
SignedUrl: x.URL || x.SignedUrl,
|
||||
SentToOthers: true,
|
||||
Signers: allSigner?.map(y => ({
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Contactbook',
|
||||
objectId: y.objectId,
|
||||
})),
|
||||
ACL: Acl,
|
||||
SentToOthers: true,
|
||||
RemindOnceInEvery: x.RemindOnceInEvery || 5,
|
||||
AutomaticReminders: x.AutomaticReminders || false,
|
||||
TimeToCompleteDays: x.TimeToCompleteDays || 15,
|
||||
OriginIp: Ip,
|
||||
DocSentAt: { __type: 'Date', iso: isoDate },
|
||||
},
|
||||
};
|
||||
});
|
||||
// console.log('requests ', requests);
|
||||
|
||||
const response = await axios.post('batch', { requests: requests }, parseConfig);
|
||||
// // Handle the batch query response
|
||||
// console.log('Batch query response:', response.data);
|
||||
if (response.data && response.data.length > 0) {
|
||||
const updateDocuments = Documents.map((x, i) => ({
|
||||
...x,
|
||||
objectId: response.data[i]?.success?.objectId,
|
||||
createdAt: response.data[i]?.success?.createdAt,
|
||||
}));
|
||||
for (let i = 0; i < updateDocuments.length; i++) {
|
||||
sendMail(updateDocuments[i], sessionToken);
|
||||
}
|
||||
return 'success';
|
||||
}
|
||||
|
||||
// Handle individual responses within response.data.results
|
||||
} catch (error) {
|
||||
console.error('Error performing batch query:', error);
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ export default async function getReport(request) {
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Master-Key': process.env.MASTER_KEY,
|
||||
};
|
||||
const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr`;
|
||||
const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr,Placeholders.signerPtr`;
|
||||
const res = await axios.get(url, { headers: headers });
|
||||
if (res.data && res.data.results) {
|
||||
return res.data.results;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Checks if a user exists in the extended class 'contracts_Users' based on the provided email.
|
||||
* @param email - The request contains parameters, such as the user's email.
|
||||
* @returns {Object} - Returns an object indicating whether the user exists.
|
||||
*/
|
||||
export default async function isextenduser(request) {
|
||||
try {
|
||||
// Query the 'contracts_Users' class in the database based on the provided email
|
||||
const userQuery = new Parse.Query('contracts_Users');
|
||||
userQuery.equalTo('Email', request.params.email);
|
||||
|
||||
// Execute the query
|
||||
const res = await userQuery.first({ useMasterKey: true });
|
||||
|
||||
// Check if a user was found
|
||||
if (res) {
|
||||
// If user exists, return object with 'isUserExist' set to true
|
||||
return { isUserExist: true };
|
||||
} else {
|
||||
// If user does not exist, return object with 'isUserExist' set to false
|
||||
return { isUserExist: false };
|
||||
}
|
||||
} catch (err) {
|
||||
// Handle errors
|
||||
console.log('Error in userexist', err);
|
||||
const code = err?.code || 400;
|
||||
const message = err?.message || 'Something went wrong.';
|
||||
throw new Parse.Error(code, message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
// `saveRoleContact` is used to save user in contracts_Guest role and create contact
|
||||
const saveRoleContact = async contact => {
|
||||
try {
|
||||
const Role = new Parse.Query(Parse.Role);
|
||||
const guestRole = await Role.equalTo('name', 'contracts_Guest').first();
|
||||
if (guestRole) {
|
||||
// Check if the user is already in the role
|
||||
const relation = guestRole.relation('users');
|
||||
const usersInRoleQuery = relation.query();
|
||||
usersInRoleQuery.equalTo('objectId', contact.UserId.objectId);
|
||||
const usersInRole = await usersInRoleQuery.find();
|
||||
if (usersInRole.length > 0) {
|
||||
console.log('User already added to Guest role.');
|
||||
} else {
|
||||
relation.add({ __type: 'Pointer', className: '_User', id: contact.UserId.objectId });
|
||||
await guestRole.save(null, { useMasterKey: true });
|
||||
// console.log('User added to Guest role successfully.');
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err in role save', err);
|
||||
}
|
||||
const contactQuery = new Parse.Object('contracts_Contactbook');
|
||||
contactQuery.set('Name', contact.Name);
|
||||
contactQuery.set('Email', contact.Email);
|
||||
if (contact?.Phone) {
|
||||
contactQuery.set('Phone', contact.Phone);
|
||||
}
|
||||
contactQuery.set('CreatedBy', contact.CreatedBy);
|
||||
contactQuery.set('UserId', contact.UserId);
|
||||
contactQuery.set('UserRole', 'contracts_Guest');
|
||||
contactQuery.set('TenantId', contact.TenantId);
|
||||
contactQuery.set('IsDeleted', false);
|
||||
const acl = new Parse.ACL();
|
||||
acl.setReadAccess(contact.CreatedBy.objectId, true);
|
||||
acl.setWriteAccess(contact.CreatedBy.objectId, true);
|
||||
acl.setReadAccess(contact.UserId.objectId, true);
|
||||
acl.setWriteAccess(contact.UserId.objectId, true);
|
||||
contactQuery.setACL(acl);
|
||||
const contactRes = await contactQuery.save();
|
||||
if (contactRes) {
|
||||
return contactRes;
|
||||
}
|
||||
};
|
||||
|
||||
// `linkContactToDoc` cloud function is used to create contact, add this contact in contracts_Guest role and
|
||||
// save contact pointer in placeholder, signers and ACL of Document
|
||||
export default async function linkContactToDoc(req) {
|
||||
const email = req.params.email;
|
||||
const docId = req.params.docId;
|
||||
const name = req.params.name;
|
||||
const phone = req.params.phone;
|
||||
try {
|
||||
if (docId) {
|
||||
// Execute the query to get the document with the specified 'docId'
|
||||
const docQuery = new Parse.Query('contracts_Document');
|
||||
docQuery.include('ExtUserPtr');
|
||||
const docRes = await docQuery.get(docId, { useMasterKey: true });
|
||||
// Check if the document was found; if not, throw an error indicating the document was not found
|
||||
if (!docRes) {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.');
|
||||
}
|
||||
const _docRes = JSON.parse(JSON.stringify(docRes));
|
||||
const Placeholders = _docRes?.Placeholders || [];
|
||||
const index = Placeholders?.findIndex(x => x.email && x.email === email);
|
||||
if (index !== -1) {
|
||||
// `signerObjectId` holds the value of `signerObjId` from the `Placeholders` array at the current index.
|
||||
// This value is used to check if `signerObjId` is present or not.
|
||||
const signerObjectId = Placeholders[index]?.signerObjId;
|
||||
if (signerObjectId) {
|
||||
return { contactId: signerObjectId };
|
||||
}
|
||||
// Execute the query to check if a contact already exists in the 'contracts_Contactbook' class
|
||||
const contactCls = new Parse.Query('contracts_Contactbook');
|
||||
contactCls.equalTo('Email', email);
|
||||
contactCls.equalTo('CreatedBy', _docRes.CreatedBy);
|
||||
contactCls.notEqualTo('IsDeleted', true);
|
||||
const existContact = await contactCls.first({ useMasterKey: true });
|
||||
if (existContact) {
|
||||
//update contact in placeholder, signers and update ACl in provide document
|
||||
const updateDoc = new Parse.Object('contracts_Document');
|
||||
updateDoc.id = docId;
|
||||
const signers = _docRes?.Signers || [];
|
||||
const signerobj = {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Contactbook',
|
||||
objectId: existContact.id,
|
||||
};
|
||||
// The splice method is used to add a signer at the desired index
|
||||
// index is the variable where the signer needs to be added
|
||||
// 0 indicates that no elements should be deleted
|
||||
// signerobj is the reference to the signer object
|
||||
signers.splice(index, 0, signerobj);
|
||||
updateDoc.set('Signers', signers);
|
||||
|
||||
Placeholders[index] = {
|
||||
...Placeholders[index],
|
||||
signerObjId: existContact.id,
|
||||
signerPtr: {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Contactbook',
|
||||
objectId: existContact.id,
|
||||
},
|
||||
};
|
||||
updateDoc.set('Placeholders', Placeholders);
|
||||
const Acl = docRes.getACL();
|
||||
Acl.setReadAccess(existContact.get('UserId').id, true);
|
||||
Acl.setWriteAccess(existContact.get('UserId').id, true);
|
||||
updateDoc.setACL(Acl);
|
||||
// const parseData = JSON.parse(JSON.stringify(res));
|
||||
const resDoc = await updateDoc.save(null, { useMasterKey: true });
|
||||
if (resDoc) {
|
||||
return { contactId: existContact.id };
|
||||
}
|
||||
} else {
|
||||
// Execute the query to check if a user already exists in the 'contracts_Users' class
|
||||
const extUserQuery = new Parse.Query('contracts_Users');
|
||||
extUserQuery.equalTo('Email', email);
|
||||
const extUser = await extUserQuery.first({ useMasterKey: true });
|
||||
if (extUser) {
|
||||
const _extUser = JSON.parse(JSON.stringify(extUser));
|
||||
const contact = {
|
||||
UserId: _extUser.UserId,
|
||||
Name: _extUser.Name,
|
||||
Email: email,
|
||||
Phone: _extUser?.Phone ? _extUser.Phone : '',
|
||||
CreatedBy: _docRes.CreatedBy,
|
||||
TenantId: _docRes.ExtUserPtr.TenantId,
|
||||
};
|
||||
// if user present on platform create contact on the basis of extended user details
|
||||
const contactRes = await saveRoleContact(contact);
|
||||
//update contact in placeholder, signers and update ACl in provide document
|
||||
const updateDoc = new Parse.Object('contracts_Document');
|
||||
updateDoc.id = docId;
|
||||
const signers = _docRes?.Signers || [];
|
||||
const signerobj = {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Contactbook',
|
||||
objectId: contactRes.id,
|
||||
};
|
||||
// The splice method is used to add a signer at the desired index
|
||||
// index is the variable where the signer needs to be added
|
||||
// 0 indicates that no elements should be deleted
|
||||
// signerobj is the reference to the signer object
|
||||
signers.splice(index, 0, signerobj);
|
||||
updateDoc.set('Signers', signers);
|
||||
|
||||
Placeholders[index] = {
|
||||
...Placeholders[index],
|
||||
signerObjId: contactRes.id,
|
||||
signerPtr: {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Contactbook',
|
||||
objectId: contactRes.id,
|
||||
},
|
||||
};
|
||||
updateDoc.set('Placeholders', Placeholders);
|
||||
const Acl = docRes.getACL();
|
||||
Acl.setReadAccess(_extUser.UserId.objectId, true);
|
||||
Acl.setWriteAccess(_extUser.UserId.objectId, true);
|
||||
updateDoc.setACL(Acl);
|
||||
// const parseData = JSON.parse(JSON.stringify(res));
|
||||
const resDoc = await updateDoc.save(null, { useMasterKey: true });
|
||||
if (resDoc) {
|
||||
return { contactId: contactRes.id };
|
||||
}
|
||||
} else if (name) {
|
||||
try {
|
||||
// Execute the query to check if a user already exists in the '_User' class
|
||||
const userQuery = new Parse.Query(Parse.User);
|
||||
userQuery.equalTo('email', email);
|
||||
const userRes = await userQuery.first({ useMasterKey: true });
|
||||
if (userRes) {
|
||||
const contact = {
|
||||
UserId: { __type: 'Pointer', className: '_User', objectId: userRes.id },
|
||||
Name: name,
|
||||
Email: email,
|
||||
Phone: phone,
|
||||
CreatedBy: _docRes.CreatedBy,
|
||||
TenantId: _docRes.ExtUserPtr.TenantId,
|
||||
};
|
||||
// Create new contract on the basis provided contact details by user and userId from _User class
|
||||
const contactRes = await saveRoleContact(contact);
|
||||
//update contact in placeholder, signers and update ACl in provide document
|
||||
const updateDoc = new Parse.Object('contracts_Document');
|
||||
updateDoc.id = docId;
|
||||
const signers = _docRes?.Signers || [];
|
||||
const signerobj = {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Contactbook',
|
||||
objectId: contactRes.id,
|
||||
};
|
||||
// The splice method is used to add a signer at the desired index
|
||||
// index is the variable where the signer needs to be added
|
||||
// 0 indicates that no elements should be deleted
|
||||
// signerobj is the reference to the signer object
|
||||
signers.splice(index, 0, signerobj);
|
||||
updateDoc.set('Signers', signers);
|
||||
|
||||
Placeholders[index] = {
|
||||
...Placeholders[index],
|
||||
signerObjId: contactRes.id,
|
||||
signerPtr: {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Contactbook',
|
||||
objectId: contactRes.id,
|
||||
},
|
||||
};
|
||||
updateDoc.set('Placeholders', Placeholders);
|
||||
const Acl = docRes.getACL();
|
||||
Acl.setReadAccess(userRes.id, true);
|
||||
Acl.setWriteAccess(userRes.id, true);
|
||||
updateDoc.setACL(Acl);
|
||||
// const parseData = JSON.parse(JSON.stringify(res));
|
||||
const resDoc = await updateDoc.save(null, { useMasterKey: true });
|
||||
if (resDoc) {
|
||||
return { contactId: contactRes.id };
|
||||
}
|
||||
} else {
|
||||
// create new user in _User class on the basis of details provide by user
|
||||
const _users = Parse.Object.extend('User');
|
||||
const _user = new _users();
|
||||
_user.set('name', name);
|
||||
_user.set('username', email);
|
||||
_user.set('email', email);
|
||||
_user.set('password', email);
|
||||
if (phone) {
|
||||
_user.set('phone', phone);
|
||||
}
|
||||
const newUserRes = await _user.save();
|
||||
const contact = {
|
||||
UserId: { __type: 'Pointer', className: '_User', objectId: newUserRes.id },
|
||||
Name: name,
|
||||
Email: email,
|
||||
Phone: phone,
|
||||
CreatedBy: _docRes.CreatedBy,
|
||||
TenantId: _docRes.ExtUserPtr.TenantId,
|
||||
};
|
||||
// Create new contract on the basis provided contact details by user and userId from _User class
|
||||
const contactRes = await saveRoleContact(contact);
|
||||
//update contact in placeholder, signers and update ACl in provide document
|
||||
const updateDoc = new Parse.Object('contracts_Document');
|
||||
updateDoc.id = docId;
|
||||
const signers = _docRes?.Signers || [];
|
||||
const signerobj = {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Contactbook',
|
||||
objectId: contactRes.id,
|
||||
};
|
||||
// The splice method is used to add a signer at the desired index
|
||||
// index is the variable where the signer needs to be added
|
||||
// 0 indicates that no elements should be deleted
|
||||
// signerobj is the reference to the signer object
|
||||
signers.splice(index, 0, signerobj);
|
||||
updateDoc.set('Signers', signers);
|
||||
Placeholders[index] = {
|
||||
...Placeholders[index],
|
||||
signerObjId: contactRes.id,
|
||||
signerPtr: {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Contactbook',
|
||||
objectId: contactRes.id,
|
||||
},
|
||||
};
|
||||
updateDoc.set('Placeholders', Placeholders);
|
||||
const Acl = docRes.getACL();
|
||||
Acl.setReadAccess(newUserRes.id, true);
|
||||
Acl.setWriteAccess(newUserRes.id, true);
|
||||
updateDoc.setACL(Acl);
|
||||
// const parseData = JSON.parse(JSON.stringify(res));
|
||||
const resDoc = await updateDoc.save(null, { useMasterKey: true });
|
||||
if (resDoc) {
|
||||
return { contactId: contactRes.id };
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Err', err);
|
||||
}
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'User not found.');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'unauthorized');
|
||||
}
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.');
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err in linkcontacttodoc', err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,473 @@
|
||||
import fs from 'node:fs';
|
||||
import axios from 'axios';
|
||||
import { SignPdf } from '@signpdf/signpdf';
|
||||
import { P12Signer } from '@signpdf/signer-p12';
|
||||
import { pdflibAddPlaceholder } from '@signpdf/placeholder-pdf-lib';
|
||||
import { PDFDocument } from 'pdf-lib';
|
||||
import { replaceMailVaribles, saveFileUsage } from '../../../Utils.js';
|
||||
import GenerateCertificate from './GenerateCertificate.js';
|
||||
const serverUrl = process.env.SERVER_URL;
|
||||
const APPID = process.env.APP_ID;
|
||||
const masterKEY = process.env.MASTER_KEY;
|
||||
const eSignName = 'opensign';
|
||||
const eSigncontact = 'hello@opensignlabs.com';
|
||||
// `updateDoc` is used to create url in from pdfFile
|
||||
async function uploadFile(pdfName, filepath) {
|
||||
try {
|
||||
const filedata = fs.readFileSync(filepath);
|
||||
const file = new Parse.File(pdfName, [...filedata], 'application/pdf');
|
||||
await file.save({ useMasterKey: true });
|
||||
const fileUrl = file.url();
|
||||
return { imageUrl: fileUrl };
|
||||
} catch (err) {
|
||||
console.log('Err ', err);
|
||||
// `fs.unlinkSync` is used to remove exported signed pdf file from exports folder
|
||||
fs.unlinkSync(filepath);
|
||||
}
|
||||
}
|
||||
|
||||
// `updateDoc` is used to update signedUrl, AuditTrail, Iscompleted in document
|
||||
async function updateDoc(docId, url, userId, ipAddress, data, className, sign) {
|
||||
try {
|
||||
const UserPtr = {
|
||||
__type: 'Pointer',
|
||||
className: className,
|
||||
objectId: userId,
|
||||
};
|
||||
const obj = {
|
||||
UserPtr: UserPtr,
|
||||
SignedUrl: url,
|
||||
Activity: 'Signed',
|
||||
ipAddress: ipAddress,
|
||||
SignedOn: new Date(),
|
||||
Signature: sign,
|
||||
};
|
||||
let updateAuditTrail;
|
||||
if (data.AuditTrail && data.AuditTrail.length > 0) {
|
||||
const AuditTrail = JSON.parse(JSON.stringify(data.AuditTrail));
|
||||
const existingIndex = AuditTrail.findIndex(
|
||||
entry => entry.UserPtr.objectId === userId && entry.Activity !== 'Created'
|
||||
);
|
||||
existingIndex !== -1
|
||||
? (AuditTrail[existingIndex] = { ...AuditTrail[existingIndex], ...obj })
|
||||
: AuditTrail.push(obj);
|
||||
|
||||
updateAuditTrail = AuditTrail;
|
||||
} else {
|
||||
updateAuditTrail = [obj];
|
||||
}
|
||||
|
||||
const auditTrail = updateAuditTrail.filter(x => x.Activity === 'Signed');
|
||||
let isCompleted = false;
|
||||
if (data.Signers && data.Signers.length > 0) {
|
||||
if (auditTrail.length === data.Placeholders.length) {
|
||||
isCompleted = true;
|
||||
}
|
||||
} else {
|
||||
isCompleted = true;
|
||||
}
|
||||
const body = {
|
||||
SignedUrl: url,
|
||||
AuditTrail: updateAuditTrail,
|
||||
IsCompleted: isCompleted,
|
||||
};
|
||||
const signedRes = await axios.put(serverUrl + '/classes/contracts_Document/' + docId, body, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Master-Key': masterKEY,
|
||||
},
|
||||
});
|
||||
return { isCompleted: isCompleted, message: 'success', AuditTrail: updateAuditTrail };
|
||||
} catch (err) {
|
||||
console.log('update doc err ', err);
|
||||
return 'err';
|
||||
}
|
||||
}
|
||||
|
||||
// `sendCompletedMail` is used to send copy of completed document mail
|
||||
async function sendCompletedMail(obj) {
|
||||
const url = obj.url;
|
||||
const doc = obj.doc;
|
||||
const sender = obj.doc.ExtUserPtr;
|
||||
const pdfName = doc.Name;
|
||||
const mailLogo = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png';
|
||||
const recipient = sender.Email;
|
||||
let subject = `Document "${pdfName}" has been signed by all parties`;
|
||||
let body =
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body> <div style='background-color:#f5f5f5;padding:20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'> <div><img src=" +
|
||||
mailLogo +
|
||||
" height='50' style='padding:20px'/> </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 OpenSign™. 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 OpenSign™ <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>';
|
||||
|
||||
if (obj?.isCustomMail) {
|
||||
try {
|
||||
const tenantCreditsQuery = new Parse.Query('partners_Tenant');
|
||||
tenantCreditsQuery.equalTo('UserId', {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: sender.UserId.objectId,
|
||||
});
|
||||
const res = await tenantCreditsQuery.first();
|
||||
if (res) {
|
||||
const _res = JSON.parse(JSON.stringify(res));
|
||||
if (_res?.CompletionSubject) {
|
||||
subject = _res?.CompletionSubject;
|
||||
}
|
||||
if (_res?.CompletionBody) {
|
||||
body = _res?.CompletionBody;
|
||||
}
|
||||
const expireDate = doc.ExpiryDate.iso;
|
||||
const newDate = new Date(expireDate);
|
||||
const localExpireDate = newDate.toLocaleDateString('en-US', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
});
|
||||
|
||||
const variables = {
|
||||
document_title: pdfName,
|
||||
sender_name: sender.Name,
|
||||
sender_mail: sender.Email,
|
||||
sender_phone: sender?.Phone || '',
|
||||
receiver_name: sender.Name,
|
||||
receiver_email: sender.Email,
|
||||
receiver_phone: sender?.Phone || '',
|
||||
expiry_date: localExpireDate,
|
||||
company_name: sender.Company,
|
||||
};
|
||||
const replaceVar = replaceMailVaribles(subject, body, variables);
|
||||
subject = replaceVar.subject;
|
||||
body = replaceVar.body;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('error in fetch tenant in signpdf', err.message);
|
||||
}
|
||||
}
|
||||
const params = {
|
||||
extUserId: sender.objectId,
|
||||
url: url,
|
||||
from: 'OpenSign™',
|
||||
recipient: recipient,
|
||||
subject: subject,
|
||||
pdfName: pdfName,
|
||||
html: body,
|
||||
mailProvider: obj.mailProvider,
|
||||
};
|
||||
const res = await axios.post(serverUrl + '/functions/sendmailv3', params, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Master-Key': masterKEY,
|
||||
},
|
||||
});
|
||||
// console.log('Res ', res);
|
||||
}
|
||||
|
||||
// `sendDoctoWebhook` is used to send res data of document on webhook
|
||||
async function sendDoctoWebhook(doc, Url, event, signUser, certificateUrl) {
|
||||
let signers = [];
|
||||
if (signUser) {
|
||||
signers = {
|
||||
name: signUser?.Name,
|
||||
email: signUser?.Email,
|
||||
phone: signUser?.Phone,
|
||||
};
|
||||
} else {
|
||||
signers = doc?.Signers?.map(x => ({
|
||||
name: x.Name,
|
||||
email: x.Email,
|
||||
phone: x.Phone,
|
||||
})) || [
|
||||
{
|
||||
name: doc?.ExtUserPtr?.Name,
|
||||
email: doc?.ExtUserPtr?.Email,
|
||||
phone: doc?.ExtUserPtr?.Phone,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (doc.ExtUserPtr?.Webhook) {
|
||||
const time =
|
||||
event === 'signed'
|
||||
? { signer: signers, signedAt: new Date() }
|
||||
: { signers: signers, completedAt: new Date() };
|
||||
const certificate = certificateUrl ? { certificate: certificateUrl } : {};
|
||||
const params = {
|
||||
event: event,
|
||||
objectId: doc?.objectId,
|
||||
file: Url || '',
|
||||
...certificate,
|
||||
name: doc?.Name,
|
||||
note: doc?.Note || '',
|
||||
description: doc?.Description || '',
|
||||
...time,
|
||||
createdAt: doc?.createdAt,
|
||||
};
|
||||
axios
|
||||
.post(doc?.ExtUserPtr?.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: doc.ExtUserPtr.UserId.objectId,
|
||||
});
|
||||
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: doc.ExtUserPtr.UserId.objectId,
|
||||
});
|
||||
webhook.save(null, { useMasterKey: true });
|
||||
} catch (err) {
|
||||
console.log('err save in contracts_Webhook', err.message);
|
||||
}
|
||||
});
|
||||
// console.log('res ', res.data);
|
||||
}
|
||||
}
|
||||
|
||||
// `sendMailsaveCertifcate` is used send completion mail and update complete status of document
|
||||
const sendMailsaveCertifcate = async (doc, P12Buffer, url, isCustomMail, mailProvider, userId) => {
|
||||
const certificate = await GenerateCertificate(doc);
|
||||
const certificatePdf = await PDFDocument.load(certificate);
|
||||
const p12 = new P12Signer(P12Buffer, { passphrase: process.env.PASS_PHRASE || null });
|
||||
// `pdflibAddPlaceholder` is used to add code of only digitial sign in certificate
|
||||
pdflibAddPlaceholder({
|
||||
pdfDoc: certificatePdf,
|
||||
reason: 'Digitally signed by OpenSign.',
|
||||
location: 'n/a',
|
||||
name: eSignName,
|
||||
contactInfo: eSigncontact,
|
||||
signatureLength: 15000,
|
||||
});
|
||||
const pdfWithPlaceholderBytes = await certificatePdf.save();
|
||||
const CertificateBuffer = Buffer.from(pdfWithPlaceholderBytes);
|
||||
//`new signPDF` create new instance of CertificateBuffer and p12Buffer
|
||||
const certificateOBJ = new SignPdf();
|
||||
// `signedCertificate` is used to sign certificate digitally
|
||||
const signedCertificate = await certificateOBJ.sign(CertificateBuffer, p12);
|
||||
|
||||
//below is used to save signed certificate in exports folder
|
||||
fs.writeFileSync('./exports/certificate.pdf', signedCertificate);
|
||||
const file = await uploadFile('certificate.pdf', './exports/certificate.pdf');
|
||||
const body = { CertificateUrl: file.imageUrl };
|
||||
await axios.put(serverUrl + '/classes/contracts_Document/' + doc.objectId, body, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Master-Key': masterKEY,
|
||||
},
|
||||
});
|
||||
// used in API only
|
||||
if (doc.IsSendMail === false) {
|
||||
console.log("don't send mail");
|
||||
} else {
|
||||
const mailObj = {
|
||||
url: url,
|
||||
isCustomMail: isCustomMail,
|
||||
doc: doc,
|
||||
mailProvider: mailProvider,
|
||||
};
|
||||
sendCompletedMail(mailObj);
|
||||
}
|
||||
|
||||
saveFileUsage(CertificateBuffer.length, file.imageUrl, userId);
|
||||
sendDoctoWebhook(doc, url, 'completed', '', file.imageUrl);
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param docId Id of Document in which user is signing
|
||||
* @param pdfFile base64 of pdfFile which you want sign
|
||||
* @returns if success {status, data} else {status, message}
|
||||
*/
|
||||
async function PDF(req) {
|
||||
try {
|
||||
if (!req?.user) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||
} else {
|
||||
const password = '';
|
||||
const authUser = req?.user?.toJSON();
|
||||
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';
|
||||
}
|
||||
} else {
|
||||
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: req.headers['x-real-ip'],
|
||||
};
|
||||
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 {
|
||||
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
|
||||
req.headers['x-real-ip'], // client ipAddress,
|
||||
_resDoc, // auditTrail, signers, etc data
|
||||
className,
|
||||
sign
|
||||
);
|
||||
sendDoctoWebhook(_resDoc, data.imageUrl, 'signed', signUser);
|
||||
saveFileUsage(pdfSize, data.imageUrl, authUser.objectId);
|
||||
if (updatedDoc && updatedDoc.isCompleted) {
|
||||
const doc = { ..._resDoc, AuditTrail: updatedDoc.AuditTrail };
|
||||
sendMailsaveCertifcate(
|
||||
doc,
|
||||
P12Buffer,
|
||||
data.imageUrl,
|
||||
isCustomMail,
|
||||
mailProvider,
|
||||
authUser.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);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
export default PDF;
|
||||
@@ -1,326 +0,0 @@
|
||||
import SignPDF from './SignPDF.min.cjs';
|
||||
import fs from 'node:fs';
|
||||
import axios from 'axios';
|
||||
import { pdflibAddPlaceholder } from './customSignPdf/pdflibplaceholder.min.js';
|
||||
import { PDFDocument } from 'pdf-lib';
|
||||
import { replaceMailVaribles, saveFileUsage } from '../../../Utils.js';
|
||||
import GenerateCertificate from './GenerateCertificate.js';
|
||||
const serverUrl = process.env.SERVER_URL,
|
||||
APPID = process.env.APP_ID,
|
||||
masterKEY = process.env.MASTER_KEY;
|
||||
async function uploadFile(e, t) {
|
||||
try {
|
||||
var a = fs.readFileSync(t),
|
||||
r = new Parse.File(e, [...a], 'application/pdf'),
|
||||
i = (await r.save({ useMasterKey: !0 }), r.url());
|
||||
return { imageUrl: i };
|
||||
} catch (e) {
|
||||
console.log('Err ', e), fs.unlinkSync(t);
|
||||
}
|
||||
}
|
||||
async function updateDoc(a, r, i, s, o, n, l) {
|
||||
try {
|
||||
var c,
|
||||
d,
|
||||
p = {
|
||||
UserPtr: { __type: 'Pointer', className: n, objectId: i },
|
||||
SignedUrl: r,
|
||||
Activity: 'Signed',
|
||||
ipAddress: s,
|
||||
SignedOn: new Date(),
|
||||
Signature: l,
|
||||
};
|
||||
let e;
|
||||
var m = (e =
|
||||
o.AuditTrail && 0 < o.AuditTrail.length
|
||||
? (-1 !==
|
||||
(d = (c = JSON.parse(JSON.stringify(o.AuditTrail))).findIndex(
|
||||
e => e.UserPtr.objectId === i && 'Created' !== e.Activity
|
||||
))
|
||||
? (c[d] = { ...c[d], ...p })
|
||||
: c.push(p),
|
||||
c)
|
||||
: [p]).filter(e => 'Signed' === e.Activity);
|
||||
let t = !1;
|
||||
!((o.Signers && 0 < o.Signers.length && m.length !== o.Signers.length) || !(t = !0));
|
||||
var g = { SignedUrl: r, AuditTrail: e, IsCompleted: t };
|
||||
await axios.put(serverUrl + '/classes/contracts_Document/' + a, g, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Master-Key': masterKEY,
|
||||
},
|
||||
});
|
||||
return { isCompleted: t, message: 'success', AuditTrail: e };
|
||||
} catch (e) {
|
||||
return console.log('update doc err ', e), 'err';
|
||||
}
|
||||
}
|
||||
async function sendCompletedMail(e) {
|
||||
var t = e.url,
|
||||
a = e.doc,
|
||||
r = e.doc.ExtUserPtr,
|
||||
i = a.Name,
|
||||
s = r.Email;
|
||||
let o = `Document "${i}" has been signed by all parties`,
|
||||
n =
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body> <div style='background-color:#f5f5f5;padding:20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'> <div><img src=https://qikinnovation.ams3.digitaloceanspaces.com/logo.png height='50' style='padding:20px'/> </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>"${i}"</b>` +
|
||||
'. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender ' +
|
||||
r.Email +
|
||||
' directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>';
|
||||
if (e?.isCustomMail)
|
||||
try {
|
||||
var l,
|
||||
c,
|
||||
d,
|
||||
p,
|
||||
m,
|
||||
g = new Parse.Query('partners_Tenant');
|
||||
g.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: r.UserId.objectId });
|
||||
const f = await g.first();
|
||||
f &&
|
||||
((l = JSON.parse(JSON.stringify(f)))?.CompletionSubject && (o = l?.CompletionSubject),
|
||||
l?.CompletionBody && (n = l?.CompletionBody),
|
||||
(c = a.ExpiryDate.iso),
|
||||
(d = new Date(c).toLocaleDateString('en-US', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
})),
|
||||
(p = {
|
||||
document_title: i,
|
||||
sender_name: r.Name,
|
||||
sender_mail: r.Email,
|
||||
sender_phone: r.Phone,
|
||||
receiver_name: r.Name,
|
||||
receiver_email: r.Email,
|
||||
receiver_phone: r.Phone,
|
||||
expiry_date: d,
|
||||
company_name: r.Company,
|
||||
}),
|
||||
(m = replaceMailVaribles(o, n, p)),
|
||||
(o = m.subject),
|
||||
(n = m.body));
|
||||
} catch (e) {
|
||||
console.log('error in fetch tenant in signpdf', e.message);
|
||||
}
|
||||
g = {
|
||||
extUserId: r.objectId,
|
||||
url: t,
|
||||
from: 'OpenSign™',
|
||||
recipient: s,
|
||||
subject: o,
|
||||
pdfName: i,
|
||||
html: n,
|
||||
mailProvider: e.mailProvider,
|
||||
};
|
||||
await axios.post(serverUrl + '/functions/sendmailv3', g, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Master-Key': masterKEY,
|
||||
},
|
||||
});
|
||||
}
|
||||
async function sendDoctoWebhook(a, e, t, r, i) {
|
||||
let s = [];
|
||||
(s = r
|
||||
? { name: r?.Name, email: r?.Email, phone: r?.Phone }
|
||||
: a?.Signers?.map(e => ({ name: e.Name, email: e.Email, phone: e.Phone })) || [
|
||||
{ name: a?.ExtUserPtr?.Name, email: a?.ExtUserPtr?.Email, phone: a?.ExtUserPtr?.Phone },
|
||||
]),
|
||||
a.ExtUserPtr?.Webhook &&
|
||||
((r =
|
||||
'signed' === t
|
||||
? { signer: s, signedAt: new Date() }
|
||||
: { signers: s, completedAt: new Date() }),
|
||||
(t = {
|
||||
event: t,
|
||||
objectId: a?.objectId,
|
||||
file: e || '',
|
||||
...(i ? { certificate: i } : {}),
|
||||
name: a?.Name,
|
||||
note: a?.Note || '',
|
||||
description: a?.Description || '',
|
||||
...r,
|
||||
createdAt: a?.createdAt,
|
||||
}),
|
||||
axios
|
||||
.post(a?.ExtUserPtr?.Webhook, t, { headers: { 'Content-Type': 'application/json' } })
|
||||
.then(e => {
|
||||
try {
|
||||
var t = new Parse.Object('contracts_Webhook');
|
||||
t.set('Log', e?.status),
|
||||
t.set('UserId', {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: a.ExtUserPtr.UserId.objectId,
|
||||
}),
|
||||
t.save(null, { useMasterKey: !0 });
|
||||
} catch (e) {
|
||||
console.log('err save in contracts_Webhook', e.message);
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
console.log('Err send data to webhook', e.message);
|
||||
try {
|
||||
var t = new Parse.Object('contracts_Webhook');
|
||||
t.set('Log', e?.status),
|
||||
t.set('UserId', {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: a.ExtUserPtr.UserId.objectId,
|
||||
}),
|
||||
t.save(null, { useMasterKey: !0 });
|
||||
} catch (e) {
|
||||
console.log('err save in contracts_Webhook', e.message);
|
||||
}
|
||||
}));
|
||||
}
|
||||
const sendMailsaveCertifcate = async (e, t, a, r, i, s) => {
|
||||
var o = await GenerateCertificate(e),
|
||||
o = await PDFDocument.load(o),
|
||||
o =
|
||||
(pdflibAddPlaceholder({
|
||||
pdfDoc: o,
|
||||
reason: 'Digitally signed by OpenSign.',
|
||||
location: 'n/a',
|
||||
signatureLength: 15e3,
|
||||
}),
|
||||
await o.save()),
|
||||
o = Buffer.from(o),
|
||||
t = await new SignPDF(o, t).signPDF(),
|
||||
t =
|
||||
(fs.writeFileSync('./exports/certificate.pdf', t),
|
||||
await uploadFile('certificate.pdf', './exports/certificate.pdf')),
|
||||
n = { CertificateUrl: t.imageUrl };
|
||||
await axios.put(serverUrl + '/classes/contracts_Document/' + e.objectId, n, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Master-Key': masterKEY,
|
||||
},
|
||||
}),
|
||||
e.IsSendMail && !1 === e.IsSendMail
|
||||
? console.log("don't send mail")
|
||||
: sendCompletedMail({ url: a, isCustomMail: r, doc: e, mailProvider: i }),
|
||||
saveFileUsage(o.length, t.imageUrl, s),
|
||||
sendDoctoWebhook(e, a, 'completed', '', t.imageUrl);
|
||||
};
|
||||
async function PDF(o) {
|
||||
try {
|
||||
if (!o?.user)
|
||||
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||
{
|
||||
var n = o?.user?.toJSON(),
|
||||
e = o.params.docId;
|
||||
const F = o.params.userId;
|
||||
var l = o.params.isCustomCompletionMail || !1,
|
||||
c = o.params.mailProvider || '',
|
||||
d = o.params.signature || '',
|
||||
t = new Parse.Query('contracts_Document'),
|
||||
a =
|
||||
(t.include('ExtUserPtr,Signers'),
|
||||
t.equalTo('objectId', e),
|
||||
await t.first({ useMasterKey: !0 }));
|
||||
if (!a) throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.');
|
||||
var r,
|
||||
p = a?.toJSON();
|
||||
let i, s;
|
||||
F
|
||||
? ((r = p.Signers.find(e => e.objectId === F)),
|
||||
console.log('_contractUser ', r),
|
||||
r && ((i = r), (s = 'contracts_Contactbook')))
|
||||
: ((s = 'contracts_Users'), (i = p.ExtUserPtr));
|
||||
var m,
|
||||
g = i.Name,
|
||||
f = i.Email;
|
||||
if (!o.params.pdfFile) throw (((m = new Error('Pdf file not present!')).code = 400), m);
|
||||
{
|
||||
let e = Buffer.from(o.params.pdfFile, 'base64');
|
||||
var u = process.env.PFX_BASE64,
|
||||
h = Buffer.from(u, 'base64'),
|
||||
y = {
|
||||
UserPtr: { __type: 'Pointer', className: s, objectId: i.objectId },
|
||||
SignedUrl: '',
|
||||
Activity: 'Signed',
|
||||
ipAddress: o.headers['x-real-ip'],
|
||||
};
|
||||
let t;
|
||||
var P = (t = p.AuditTrail && 0 < p.AuditTrail.length ? [...p.AuditTrail, y] : [y]).filter(
|
||||
e => 'Signed' === e.Activity
|
||||
);
|
||||
let a = !1;
|
||||
!((p.Signers && 0 < p.Signers.length && P.length !== p.Signers.length) || !(a = !0));
|
||||
var v,
|
||||
b,
|
||||
S,
|
||||
w,
|
||||
U,
|
||||
D,
|
||||
I = `exported_file_${Math.floor(5e3 * Math.random())}.pdf`,
|
||||
_ = './exports/' + I;
|
||||
let r = e.length;
|
||||
r = (
|
||||
a
|
||||
? ((v = p.Signers?.map(e => e.Name + ' <' + e.Email + '>')),
|
||||
(e =
|
||||
v && 0 < v.length
|
||||
? ((b = await PDFDocument.load(e)),
|
||||
pdflibAddPlaceholder({
|
||||
pdfDoc: b,
|
||||
reason: 'Digitally signed by OpenSign for ' + v?.join(', '),
|
||||
location: 'n/a',
|
||||
signatureLength: 15e3,
|
||||
}),
|
||||
(S = await b.save()),
|
||||
Buffer.from(S))
|
||||
: ((w = await PDFDocument.load(e)),
|
||||
pdflibAddPlaceholder({
|
||||
pdfDoc: w,
|
||||
reason: 'Digitally signed by OpenSign for ' + g + ' <' + f + '>',
|
||||
location: 'n/a',
|
||||
signatureLength: 15e3,
|
||||
}),
|
||||
(U = await w.save()),
|
||||
Buffer.from(U))),
|
||||
(D = await new SignPDF(e, h).signPDF()),
|
||||
fs.writeFileSync(_, D),
|
||||
D)
|
||||
: (fs.writeFileSync(_, e), e)
|
||||
).length;
|
||||
var E = await uploadFile(I, _);
|
||||
if (E && E.imageUrl) {
|
||||
var x,
|
||||
A,
|
||||
j = await updateDoc(
|
||||
o.params.docId,
|
||||
E.imageUrl,
|
||||
i.objectId,
|
||||
o.headers['x-real-ip'],
|
||||
p,
|
||||
s,
|
||||
d
|
||||
);
|
||||
if (
|
||||
(sendDoctoWebhook(p, E.imageUrl, 'signed', i),
|
||||
saveFileUsage(r, E.imageUrl, n.objectId),
|
||||
j &&
|
||||
j.isCompleted &&
|
||||
((x = { ...p, AuditTrail: j.AuditTrail }),
|
||||
sendMailsaveCertifcate(x, h, E.imageUrl, l, c, n.objectId)),
|
||||
fs.unlinkSync(_),
|
||||
console.log('New Signed PDF created called: ' + _),
|
||||
'success' === j.message)
|
||||
)
|
||||
return { status: 'success', data: E.imageUrl };
|
||||
throw (((A = new Error('Please provide required parameters!')).code = 400), A);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
throw (console.log('Err in signpdf', e), e);
|
||||
}
|
||||
}
|
||||
export default PDF;
|
||||
@@ -1 +0,0 @@
|
||||
const signer=require("node-signpdf").default;class SignPDF{constructor(e,t){this.pdfDoc=e,this.certificate=t}async signPDF(){return signer.sign(this.pdfDoc,this.certificate, process.env.PASS_PHRASE ? {passphrase : process.env.PASS_PHRASE}: null)}static unit8ToBuffer(e){var t=Buffer.alloc(e.byteLength),r=new Uint8Array(e);for(let e=0;e<t.length;++e)t[e]=r[e];return t}}module.exports=SignPDF;
|
||||
-1
@@ -1 +0,0 @@
|
||||
class PDFAbstractReference{toString(){throw new Error("Must be implemented by subclasses")}}export default PDFAbstractReference;
|
||||
-1
@@ -1 +0,0 @@
|
||||
import PDFAbstractReference from"./PDFAbstractReference.min.js";class PDFKitReferenceMock extends PDFAbstractReference{constructor(e,t=void 0){super(),this.index=e,void 0!==t&&Object.assign(this,t)}toString(){return this.index+" 0 R"}}export default PDFKitReferenceMock;
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
const ERROR_TYPE_UNKNOWN = 1,
|
||||
ERROR_TYPE_INPUT = 2,
|
||||
ERROR_TYPE_PARSE = 3,
|
||||
ERROR_VERIFY_SIGNATURE = 4;
|
||||
class SignPdfError extends Error {
|
||||
constructor(R, E = ERROR_TYPE_UNKNOWN) {
|
||||
super(R), (this.type = E);
|
||||
}
|
||||
}
|
||||
(SignPdfError.TYPE_UNKNOWN = ERROR_TYPE_UNKNOWN),
|
||||
(SignPdfError.TYPE_INPUT = ERROR_TYPE_INPUT),
|
||||
(SignPdfError.TYPE_PARSE = ERROR_TYPE_PARSE),
|
||||
(SignPdfError.VERIFY_SIGNATURE = ERROR_VERIFY_SIGNATURE);
|
||||
export {
|
||||
ERROR_TYPE_UNKNOWN,
|
||||
ERROR_TYPE_INPUT,
|
||||
ERROR_TYPE_PARSE,
|
||||
ERROR_VERIFY_SIGNATURE,
|
||||
SignPdfError,
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
const DEFAULT_SIGNATURE_LENGTH=8192,DEFAULT_BYTE_RANGE_PLACEHOLDER="**********",SUBFILTER_ADOBE_PKCS7_DETACHED="adbe.pkcs7.detached",SUBFILTER_ADOBE_PKCS7_SHA1="adbe.pkcs7.sha1",SUBFILTER_ADOBE_X509_SHA1="adbe.x509.rsa.sha1",SUBFILTER_ETSI_CADES_DETACHED="ETSI.CAdES.detached";export{DEFAULT_SIGNATURE_LENGTH,DEFAULT_BYTE_RANGE_PLACEHOLDER,SUBFILTER_ADOBE_PKCS7_DETACHED,SUBFILTER_ADOBE_PKCS7_SHA1,SUBFILTER_ADOBE_X509_SHA1,SUBFILTER_ETSI_CADES_DETACHED};
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
import findObject from"./findObject.min.js";import getIndexFromRef from"./getIndexFromRef.min.js";const createBufferPageWithAnnotation=(e,t,n,f)=>{e=findObject(e,t.xref,n).toString();let r,o,i;r=e.indexOf("/Annots"),i=-1<r?(o=e.indexOf("]",r),(i=e.substr(r,o+1-r)).substr(0,i.length-1)):(r=e.length,o=e.length,"/Annots [");t=getIndexFromRef(t.xref,n),n=f.toString(),i+=` ${n}]`,f=e.substr(0,r);let m="";return e.length>o&&(m=e.substr(o+1)),Buffer.concat([Buffer.from(t+` 0 obj
|
||||
`),Buffer.from("<<\n"),Buffer.from(f+i+m+`
|
||||
`),Buffer.from("\n>>\nendobj\n")])};export default createBufferPageWithAnnotation;
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
import getIndexFromRef from"./getIndexFromRef.min.js";const createBufferRootWithAcroform=(r,f,o)=>{var e=getIndexFromRef(f.xref,f.rootRef);return Buffer.concat([Buffer.from(e+` 0 obj
|
||||
`),Buffer.from("<<\n"),Buffer.from(f.root+`
|
||||
`),Buffer.from("/AcroForm "+o),Buffer.from("\n>>\nendobj\n")])};export default createBufferRootWithAcroform;
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
const createBufferTrailer=(f,r,e)=>{let o=[];return o[0]="0000000000 65535 f ",e.forEach((f,r)=>{f=("0000000000"+f).slice(-10);o[r+1]=r+` 1
|
||||
${f} 00000 n `}),o=o.filter(f=>void 0!==f),Buffer.concat([Buffer.from("xref\n"),Buffer.from(r.xref.startingIndex+` 1
|
||||
`),Buffer.from(o.join("\n")),Buffer.from("\ntrailer\n"),Buffer.from("<<\n"),Buffer.from(`/Size ${r.xref.maxIndex+1}
|
||||
`),Buffer.from(`/Root ${r.rootRef}
|
||||
`),Buffer.from(r.infoRef?`/Info ${r.infoRef}
|
||||
`:""),Buffer.from(`/Prev ${r.xRefPosition}
|
||||
`),Buffer.from(">>\n"),Buffer.from("startxref\n"),Buffer.from(f.length+`
|
||||
`),Buffer.from("%%EOF")])};export default createBufferTrailer;
|
||||
@@ -1 +0,0 @@
|
||||
import getIndexFromRef from"./getIndexFromRef.min.js";const findObject=(e,t,f)=>{f=getIndexFromRef(t,f),t=t.offsets.get(f);let n=e.slice(t);return n=(n=(n=n.slice(0,n.indexOf("endobj","utf8"))).slice(n.indexOf("<<","utf8")+2)).slice(0,n.lastIndexOf(">>","utf8"))};export default findObject;
|
||||
-1
@@ -1 +0,0 @@
|
||||
import SignPdfError from"./SignPdfError.min.js";const getIndexFromRef=(r,e)=>{var[o]=e.split(" "),o=parseInt(o);if(r.offsets.has(o))return o;throw new SignPdfError(`Failed to locate object "${e}".`,SignPdfError.TYPE_PARSE)};export default getIndexFromRef;
|
||||
@@ -1 +0,0 @@
|
||||
import getPagesDictionaryRef from"./getPagesDictionaryRef.min.js";import findObject from"./findObject.min.js";export default function getPageRef(e,t,i){var n=getPagesDictionaryRef(t),e=findObject(e,t.xref,n),t=e.indexOf("/Kids"),n=e.indexOf("[",t)+1,t=e.indexOf("]",t);const f=e.slice(n,t).toString();for(var r=[],o=0;o<f.length;o++)"R"===f[o]&&r.push(o);let a={},g=0;return r.forEach((e,t)=>{a={...a,[t+1]:f.substring(g+1,e+1)},g=e+1}),i?a[i]:a[1]}
|
||||
-1
@@ -1 +0,0 @@
|
||||
import SignPdfError from"./SignPdfError.min.js";export default function getPagesDictionaryRef(r){r=/\/Pages\s+(\d+\s+\d+\s+R)/g.exec(r.root);if(null===r)throw new SignPdfError("Failed to find the pages descriptor. This is probably a problem in node-signpdf.",SignPdfError.TYPE_PARSE);return r[1]}
|
||||
@@ -1 +0,0 @@
|
||||
import PDFAbstractReference from"./PDFAbstractReference.min.js";const pad=(e,t)=>(Array(t+1).join("0")+e).slice(-t),escapableRe=/[\n\r\t\b\f()\\]/g,escapable={"\n":"\\n","\r":"\\r","\t":"\\t","\b":"\\b","\f":"\\f","\\":"\\\\","(":"\\(",")":"\\)"},swapBytes=e=>e.swap16();export default class PDFObject{static convert(t,a=null){if("string"==typeof t)return"/"+t;if(t instanceof String){let r=t,n=!1;for(let e=0,t=r.length;e<t;e+=1)if(127<r.charCodeAt(e)){n=!0;break}let e;return e=n?swapBytes(Buffer.from(``+r,"utf16le")):Buffer.from(r,"ascii"),`(${r=(r=(a?a(e):e).toString("binary")).replace(escapableRe,e=>escapable[e])})`}if(Buffer.isBuffer(t))return`<${t.toString("hex")}>`;if(t instanceof PDFAbstractReference)return t.toString();if(t instanceof Date){let e=`D:${pad(t.getUTCFullYear(),4)}${pad(t.getUTCMonth()+1,2)}${pad(t.getUTCDate(),2)}${pad(t.getUTCHours(),2)}${pad(t.getUTCMinutes(),2)}${pad(t.getUTCSeconds(),2)}Z`;return`(${e=a?(e=a(Buffer.from(e,"ascii")).toString("binary")).replace(escapableRe,e=>escapable[e]):e})`}if(Array.isArray(t))return`[${t.map(e=>PDFObject.convert(e,a)).join(" ")}]`;if("[object Object]"!=={}.toString.call(t))return"number"==typeof t?PDFObject.number(t):""+t;{const n=["<<"];return Object.entries(t).forEach(([e,t])=>{let r="";r=t&&-1!==t.toString().indexOf("<<")?t:PDFObject.convert(t,a),n.push(`/${e} `+r)}),n.push(">>"),n.join("\n")}}static number(e){if(-1e21<e&&e<1e21)return Math.round(1e6*e)/1e6;throw new Error("unsupported number: "+e)}}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
import{DEFAULT_BYTE_RANGE_PLACEHOLDER,DEFAULT_SIGNATURE_LENGTH,SUBFILTER_ADOBE_PKCS7_DETACHED}from"./const.min.js";import PDFKitReferenceMock from"./PDFKitReferenceMock.min.js";import PNG from"png-js";import zlib from"zlib";const specialCharacters=["á","Á","é","É","í","Í","ó","Ó","ö","Ö","ő","Ő","ú","Ú","ű","Ű"],MARKERS=[65472,65473,65474,65475,65477,65478,65479,65480,65481,65482,65483,65484,65485,65486,65487],COLOR_SPACE_MAP={1:"DeviceGray",3:"DeviceRGB",4:"DeviceCMYK"};function getImage(e,t){let n;if(255===e[0]&&216===e[1])n=getJpgImage(t,e);else{if(137!==e[0]||"PNG"!==e.toString("ascii",1,4))throw new Error("Unknown image format.");n=getPngImage(t,e)}return n}function getAnnotationApparance(e,t,n){return e.ref({CropBox:[0,10,200,60],Type:"XObject",FormType:1,BBox:[0,10,200,60],Resources:`<</XObject <<
|
||||
/Img${t.index} ${t.index} 0 R
|
||||
>>
|
||||
/Font <<
|
||||
/f1 ${n.index} 0 R
|
||||
>>
|
||||
>>`,MediaBox:[0,10,200,60],Subtype:"Form"},null,getStream(t.index))}const getStream=e=>getConvertedText(`
|
||||
1.0 1.0 1.0 rg
|
||||
0.0 0.0 0.0 RG
|
||||
q
|
||||
q
|
||||
200 0 0 50 0 10 cm
|
||||
/Img${e} Do
|
||||
Q
|
||||
0 0 0 rg
|
||||
BT
|
||||
0 Tr
|
||||
/f1 10.0 Tf
|
||||
1.4 0 0 1 20 45.97412 Tm
|
||||
ET
|
||||
BT
|
||||
0 Tr
|
||||
/f1 10.0 Tf
|
||||
1.4 0 0 1 20 33.56006 Tm
|
||||
ET
|
||||
Q`),getFont=(e,t)=>e.ref({Type:"Font",BaseFont:t,Encoding:"WinAnsiEncoding",Subtype:"Type1"}),getJpgImage=(e,t)=>{if(65496!==t.readUInt16BE(0))throw"SOI not found in JPEG";let n=2,a;for(;n<t.length&&(a=t.readUInt16BE(n),n+=2,!MARKERS.includes(a));)n+=t.readUInt16BE(n);if(!MARKERS.includes(a))throw"Invalid JPEG.";n+=2;var r=t[n++],o=t.readUInt16BE(n),i=(n+=2,t.readUInt16BE(n)),l=(n+=2,t[n++]),l=COLOR_SPACE_MAP[l],r={Type:"XObject",Subtype:"Image",BitsPerComponent:r,Width:i,Height:o,ColorSpace:l,Filter:"DCTDecode"},i=("DeviceCMYK"===l&&(r.Decode=[1,0,1,0,1,0,1,0]),e.ref(r,null,t));return i},getPngImage=(e,t)=>{var t=new PNG(t),n=t.hasAlphaChannel,a={Type:"XObject",Subtype:"Image",BitsPerComponent:n?8:t.bits,Width:t.width,Height:t.height,Filter:"FlateDecode"};if(n||(r=e.ref({Predictor:15,Colors:t.colors,BitsPerComponent:t.bits,Columns:t.width}),a.DecodeParms=r),0===t.palette.length?a.ColorSpace=t.colorSpace:(r=e.ref({stream:new Buffer(t.palette)}),a.ColorSpace=["Indexed","DeviceRGB",t.palette.length/3-1,r]),null!=t.transparency.grayscale){var r=t.transparency.grayscale;a.Mask=[r,r]}else if(t.transparency.rgb){var o,r=t.transparency["rgb"],i=[];for(o of r)i.push(o,o);a.Mask=i}else t.transparency.indexed?loadIndexedAlphaChannel(t):n&&(splitAlphaChannel(t),r=getSmask(e,t),a.Mask=r);return e.ref(a,null,t.imgData)},loadIndexedAlphaChannel=e=>{const o=e.transparency.indexed;return e.decodePixels(n=>{var a=new Buffer(e.width*e.height);let r=0;for(let e=0,t=n.length;e<t;e++)a[r++]=o[n[e]];e.alphaChannel=zlib.deflateSync(a)})},splitAlphaChannel=d=>{d.decodePixels(t=>{let e,n;var a=d.colors,r=d.width*d.height,o=new Buffer(r*a),i=new Buffer(r);let l=n=e=0;for(var c=t.length,g=16===d.bits?1:0;l<c;){for(let e=0;e<a;e++)o[n++]=t[l++],l+=g;i[e++]=t[l++],l+=g}d.imgData=zlib.deflateSync(o),d.alphaChannel=zlib.deflateSync(i)})},getSmask=(e,t)=>{let n;return console.log("image.hasAlphaChannel ",t.hasAlphaChannel),t.hasAlphaChannel&&(console.log("image.alphaChannel ",t.alphaChannel),n=e.ref({Type:"XObject",Subtype:"Image",Height:t.height,Width:t.width,BitsPerComponent:8,Filter:"FlateDecode",ColorSpace:"DeviceGray",Decode:[0,1],stream:t.alphaChannel})),n},getConvertedText=e=>e.split("").map(e=>specialCharacters.includes(e)?getOctalCodeFromCharacter(e):e).join(""),getOctalCodeFromCharacter=e=>"\\"+e.charCodeAt(0).toString(8),pdfkitAddPlaceholder=({pdf:e,pdfBuffer:a,reason:r,contactInfo:t="emailfromp1289@gmail.com",name:n="Name from p12",location:o="Location from p12",signatureLength:i=DEFAULT_SIGNATURE_LENGTH,byteRangePlaceholder:l=DEFAULT_BYTE_RANGE_PLACEHOLDER,subFilter:c=SUBFILTER_ADOBE_PKCS7_DETACHED,sign:g})=>{var d=getFont(e,"Helvetica"),s=getFont(e,"ZapfDingbats"),p=getFont(e,"Helvetica"),f=g.Base64,f=getAnnotationApparance(e,getImage(Buffer.from(f,"base64"),e),p,g),p=e.ref({Type:"Sig",Filter:"Adobe.PPKLite",SubFilter:c,ByteRange:[0,l,l,l],Contents:Buffer.from(String.fromCharCode(0).repeat(i)),Reason:new String(r),M:new Date,ContactInfo:new String(t),Name:new String(n),Location:new String(o)}),h=a.lastIndexOf("/Type /AcroForm"),c=-1!==h;let m=[],C;if(c){let e=h;var S=h-10;let t="",n=11;for(n;n<22;n+=1){var A=a.slice(h-n,S).toString();if("\n"===A[0])break;t=A,e=h-n}l=a.slice(e),i=l.slice(0,l.indexOf("endobj")).toString(),r=(C=parseInt(t),i.slice(i.indexOf("/Fields [")+9,i.indexOf("]")));m=r.split(" ").filter((e,t)=>t%3==0).map(e=>new PDFKitReferenceMock(e))}t=g.Left,n=g.Bottom,o=t+g.Width,l=n+g.Height,i=e.ref({Type:"Annot",Subtype:"Widget",FT:"Sig",Rect:[t,n,o,l],V:p,T:new String("Signature"+(m.length+1)),F:4,P:e.page.dictionary,AP:`<</N ${f.index} 0 R>>`,DA:new String("/Helvetica 0 Tf 0 g")});e.page.dictionary.data.Annots=[i];let T;return T=c?e.ref({Type:"AcroForm",SigFlags:3,Fields:[...m,i],DR:`<</Font
|
||||
<</Helvetica ${d.index} 0 R/ZapfDingbats ${s.index} 0 R>>
|
||||
>>`},C):e.ref({Type:"AcroForm",SigFlags:3,Fields:[...m,i]}),{signature:p,form:e._root.data.AcroForm=T,widget:i}};export default pdfkitAddPlaceholder;
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
import {
|
||||
DEFAULT_BYTE_RANGE_PLACEHOLDER,
|
||||
DEFAULT_SIGNATURE_LENGTH,
|
||||
SUBFILTER_ADOBE_PKCS7_DETACHED,
|
||||
} from './const.min.js';
|
||||
import { SignPdfError } from './SignPdfError.min.js';
|
||||
import {
|
||||
PDFArray,
|
||||
PDFDict,
|
||||
PDFHexString,
|
||||
PDFName,
|
||||
PDFNumber,
|
||||
PDFInvalidObject,
|
||||
PDFString,
|
||||
} from 'pdf-lib';
|
||||
const pdflibAddPlaceholder = ({
|
||||
pdfDoc: e = void 0,
|
||||
pdfPage: o = void 0,
|
||||
reason: t,
|
||||
contactInfo: r = 'emailfromp1289@gmail.com',
|
||||
name: i = 'Name from p12',
|
||||
location: n,
|
||||
signingTime: a = void 0,
|
||||
signatureLength: P = DEFAULT_SIGNATURE_LENGTH,
|
||||
byteRangePlaceholder: F = DEFAULT_BYTE_RANGE_PLACEHOLDER,
|
||||
subFilter: D = SUBFILTER_ADOBE_PKCS7_DETACHED,
|
||||
widgetRect: f = [0, 0, 0, 0],
|
||||
appName: g = void 0,
|
||||
}) => {
|
||||
if (void 0 === e && void 0 === o)
|
||||
throw new SignPdfError('PDFDoc or PDFPage must be set.', SignPdfError.TYPE_INPUT);
|
||||
var e = e ?? o.doc,
|
||||
o = o ?? e.getPages()[0],
|
||||
m = PDFArray.withContext(e.context),
|
||||
F =
|
||||
(m.push(PDFNumber.of(0)),
|
||||
m.push(PDFName.of(F)),
|
||||
m.push(PDFName.of(F)),
|
||||
m.push(PDFName.of(F)),
|
||||
PDFHexString.of(String.fromCharCode(0).repeat(P))),
|
||||
P = g ? { App: { Name: g } } : {},
|
||||
g = e.context.obj({
|
||||
Type: 'Sig',
|
||||
Filter: 'Adobe.PPKLite',
|
||||
SubFilter: D,
|
||||
ByteRange: m,
|
||||
Contents: F,
|
||||
Reason: PDFString.of(t),
|
||||
M: PDFString.fromDate(a ?? new Date()),
|
||||
ContactInfo: PDFString.of(r),
|
||||
Name: PDFString.of(i),
|
||||
Location: PDFString.of(n),
|
||||
Prop_Build: { Filter: { Name: 'Adobe.PPKLite' }, ...P },
|
||||
}),
|
||||
D = new Uint8Array(g.sizeInBytes()),
|
||||
m = (g.copyBytesInto(D, 0), PDFInvalidObject.of(D)),
|
||||
F = e.context.register(m);
|
||||
const s = PDFArray.withContext(e.context);
|
||||
f.forEach(e => s.push(PDFNumber.of(e)));
|
||||
(t = e.context.formXObject([], { BBox: f, Resources: {} })),
|
||||
(a = e.context.obj({
|
||||
Type: 'Annot',
|
||||
Subtype: 'Widget',
|
||||
FT: 'Sig',
|
||||
Rect: s,
|
||||
V: F,
|
||||
T: PDFString.of('Signature1'),
|
||||
F: 4,
|
||||
P: o.ref,
|
||||
AP: { N: e.context.register(t) },
|
||||
})),
|
||||
(r = e.context.register(a));
|
||||
let c = o.node.lookupMaybe(PDFName.of('Annots'), PDFArray),
|
||||
d =
|
||||
((c = void 0 === c ? e.context.obj([]) : c).push(r),
|
||||
o.node.set(PDFName.of('Annots'), c),
|
||||
e.catalog.lookupMaybe(PDFName.of('AcroForm'), PDFDict));
|
||||
void 0 === d &&
|
||||
((d = e.context.obj({ Fields: [] })),
|
||||
(i = e.context.register(d)),
|
||||
e.catalog.set(PDFName.of('AcroForm'), i));
|
||||
let N;
|
||||
N = d.has(PDFName.of('SigFlags')) ? d.get(PDFName.of('SigFlags')) : PDFNumber.of(0);
|
||||
n = PDFNumber.of(3 | N.asNumber());
|
||||
d.set(PDFName.of('SigFlags'), n), d.get(PDFName.of('Fields')).push(r);
|
||||
};
|
||||
export { pdflibAddPlaceholder };
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
import PDFObject from"./pdfObject.min.js";import PDFKitReferenceMock from"./PDFKitReferenceMock.min.js";import removeTrailingNewLine from"./removeTrailingNewLine.min.js";import{DEFAULT_SIGNATURE_LENGTH,SUBFILTER_ADOBE_PKCS7_DETACHED}from"./const.min.js";import pdfkitAddPlaceholder from"./pdfkitAddPlaceholder.min.js";import getIndexFromRef from"./getIndexFromRef.min.js";import readPdf from"./readPdf.min.js";import getPageRef from"./getPageRef.min.js";import createBufferRootWithAcroform from"./createBufferRootWithAcroform.min.js";import createBufferPageWithAnnotation from"./createBufferPageWithAnnotation.min.js";import createBufferTrailer from"./createBufferTrailer.min.js";const isContainBufferRootWithAcroform=e=>{e=/\/AcroForm\s+(\d+\s\d+\sR)/g.exec(e.toString());return null!=e&&null!=e[1]&&""!==e[1]},getAssembledPdf=(e,r,f,o)=>{let t=e;return t=Buffer.concat([t,Buffer.from("\n"),Buffer.from(r+` 0 obj
|
||||
`),Buffer.from(PDFObject.convert(f))]),o&&(t=Buffer.concat([t,Buffer.from("\nstream\n"),Buffer.from(o),Buffer.from("\nendstream")])),t=Buffer.concat([t,Buffer.from("\nendobj\n")])},plainAddPlaceholder=({pdfBuffer:e,reason:r,contactInfo:f="emailfromp1289@gmail.com",name:o="Name from p12",location:t="Location from p12",signatureLength:n=DEFAULT_SIGNATURE_LENGTH,subFilter:i=SUBFILTER_ADOBE_PKCS7_DETACHED,sign:m})=>{let a=removeTrailingNewLine(e);const c=readPdf(a);var d=getPageRef(a,c,m.Page),u=getIndexFromRef(c.xref,d);const l=new Map;var s={ref:(e,r,f)=>{c.xref.maxIndex+=1;r=null!=r?r:c.xref.maxIndex;return l.set(r,a.length+1),a=getAssembledPdf(a,r,e,f),new PDFKitReferenceMock(c.xref.maxIndex)},page:{dictionary:new PDFKitReferenceMock(u,{data:{Annots:[]}})},_root:{data:{}}},{form:s,widget:e}=pdfkitAddPlaceholder({pdf:s,pdfBuffer:e,reason:r,contactInfo:f,name:o,location:t,signatureLength:n,subFilter:i,sign:m});return isContainBufferRootWithAcroform(a)||(r=getIndexFromRef(c.xref,c.rootRef),l.set(r,a.length+1),a=Buffer.concat([a,Buffer.from("\n"),createBufferRootWithAcroform(a,c,s)])),l.set(u,a.length+1),a=Buffer.concat([a,Buffer.from("\n"),createBufferPageWithAnnotation(a,c,d,e)]),a=Buffer.concat([a,Buffer.from("\n"),createBufferTrailer(a,c,l)])};export default plainAddPlaceholder;
|
||||
@@ -1 +0,0 @@
|
||||
import readRefTable from"./readRefTable.min.js";import findObject from"./findObject.min.js";const getValue=(e,t)=>{let r=e.indexOf(t);if(-1!==r)return e=e.slice(r),-1===(r=e.indexOf("/",1))&&(r=e.indexOf(">",1)),e.slice(t.length+1,r).toString().trim()},readPdf=e=>{var t=e.lastIndexOf("trailer"),r=e.slice(t,e.length-6),f=r.slice(r.lastIndexOf("startxref")+10).toString(),f=parseInt(f),i=readRefTable(e),n=getValue(r,"/Root");return{xref:i,rootRef:n,root:findObject(e,i,n).toString(),infoRef:getValue(r,"/Info"),trailerStart:t,previousXrefs:[],xRefPosition:f}};export default readPdf;
|
||||
@@ -1 +0,0 @@
|
||||
import SignPdfError from"./SignPdfError.min.js";import xrefToRefMap from"./xrefToRefMap.min.js";const getLastTrailerPosition=e=>{var r=e.lastIndexOf(Buffer.from("trailer","utf8")),r=e.slice(r,e.length-6),e=r.slice(r.lastIndexOf(Buffer.from("startxref","utf8"))+10).toString();return parseInt(e)},getXref=(e,r)=>{let t=e.slice(r);e=t.indexOf(Buffer.from("xref","utf8"));if(-1===e)throw new SignPdfError(`Could not find xref anywhere at or after ${r}.`,SignPdfError.TYPE_PARSE);if(0<e&&""!==t.slice(0,e).toString().replace(/\s*/g,""))throw new SignPdfError(`Expected xref at ${r} but found other content.`,SignPdfError.TYPE_PARSE);r=t.indexOf(Buffer.from("%%EOF","utf8"));if(-1===r)throw new SignPdfError("Expected EOF after xref and trailer but could not find one.",SignPdfError.TYPE_PARSE);if(!(r=(t=(t=(t=t.slice(0,r)).slice(e+4)).slice(t.indexOf("\n")+1)).toString().split("/Size")[1]))throw new SignPdfError("Size not found in xref table.",SignPdfError.TYPE_PARSE);if(null===(r=/^\s*(\d+)/.exec(r)))throw new SignPdfError("Failed to parse size of xref table.",SignPdfError.TYPE_PARSE);var r=parseInt(r[1]),[e,f]=t.toString().split("trailer");let n;null!=f.split("/Prev")[1]&&([,f]=/Prev (\d+)/g.exec(f),n=f);f=xrefToRefMap(e);return{size:r,prev:n,xRefContent:f}},getFullXrefTable=e=>{var r=getLastTrailerPosition(e),t=getXref(e,r);return void 0===t.prev?t.xRefContent:(e=e.slice(0,r),r=getFullXrefTable(e),new Map([...r,...t.xRefContent]))},readRefTable=e=>{e=getFullXrefTable(e);return{startingIndex:0,maxIndex:Math.max(...e.keys()),offsets:e}};export default readRefTable;export{getLastTrailerPosition,getXref,getFullXrefTable};
|
||||
-1
@@ -1 +0,0 @@
|
||||
import SignPdfError from"./SignPdfError.min.js";const sliceLastChar=(r,e)=>{return r.slice(r.length-1).toString()===e?r.slice(0,r.length-1):r},removeTrailingNewLine=r=>{if(!(r instanceof Buffer))throw new SignPdfError("PDF expected as Buffer.",SignPdfError.TYPE_INPUT);r=sliceLastChar(r,"\n");if("\n%%EOF"!==(r=sliceLastChar(r,"\r")).slice(r.length-6).toString())throw new SignPdfError("A PDF file must end with an EOF line.",SignPdfError.TYPE_PARSE);return r};export default removeTrailingNewLine;
|
||||
@@ -1 +0,0 @@
|
||||
import SignPdfError from"./SignPdfError.min.js";const xrefToRefMap=r=>{r=r.split("\n").filter(r=>""!==r);let n=0,t=0;const f=new Map;return r.forEach(r=>{r=r.split(" ");if(2===r.length)n=parseInt(r[0]),t=parseInt(r[1]);else{if(t<=0)throw new SignPdfError("Too many lines in xref table.",SignPdfError.TYPE_PARSE);--t;var[r,,e]=r;if("f"!==e.trim()){if("n"!==e.trim())throw new SignPdfError(`Unknown in-use flag "${e}". Expected "n" or "f".`,SignPdfError.TYPE_PARSE);if(!/^\d+$/.test(r.trim()))throw new SignPdfError(`Expected integer offset. Got "${r}".`,SignPdfError.TYPE_PARSE);e=parseInt(r.trim());f.set(n,e)}n+=1}}),f};export default xrefToRefMap;
|
||||
@@ -27,6 +27,7 @@ export default function reportJson(id, userId) {
|
||||
'Signers.Name',
|
||||
'Signers.Email',
|
||||
'Signers.Phone',
|
||||
'Placeholders',
|
||||
],
|
||||
};
|
||||
|
||||
@@ -67,6 +68,7 @@ export default function reportJson(id, userId) {
|
||||
'Signers.Phone',
|
||||
'Signers.UserId',
|
||||
'AuditTrail',
|
||||
'Placeholders',
|
||||
],
|
||||
};
|
||||
// In progess report
|
||||
@@ -75,7 +77,7 @@ export default function reportJson(id, userId) {
|
||||
reportName: 'In-progress documents',
|
||||
params: {
|
||||
Type: { $ne: 'Folder' },
|
||||
Signers: { $exists: true, $ne: [] },
|
||||
SignedUrl: { $ne: null },
|
||||
Placeholders: { $ne: null },
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
@@ -101,6 +103,8 @@ export default function reportJson(id, userId) {
|
||||
'AuditTrail',
|
||||
'AuditTrail.UserPtr',
|
||||
'ExpiryDate',
|
||||
'SendMail',
|
||||
'Placeholders',
|
||||
],
|
||||
};
|
||||
// completed documents report
|
||||
@@ -129,6 +133,7 @@ export default function reportJson(id, userId) {
|
||||
'Signers.Email',
|
||||
'Signers.Phone',
|
||||
'TimeToCompleteDays',
|
||||
'Placeholders',
|
||||
],
|
||||
};
|
||||
|
||||
@@ -156,6 +161,7 @@ export default function reportJson(id, userId) {
|
||||
'Signers.Name',
|
||||
'Signers.Email',
|
||||
'Signers.Phone',
|
||||
'Placeholders',
|
||||
],
|
||||
};
|
||||
// Expired Documents report
|
||||
@@ -186,6 +192,7 @@ export default function reportJson(id, userId) {
|
||||
'Signers.Name',
|
||||
'Signers.Email',
|
||||
'Signers.Phone',
|
||||
'Placeholders',
|
||||
],
|
||||
};
|
||||
// Recently sent for signatures report show on dashboard
|
||||
@@ -194,7 +201,7 @@ export default function reportJson(id, userId) {
|
||||
reportName: 'Recently sent for signatures',
|
||||
params: {
|
||||
Type: { $ne: 'Folder' },
|
||||
Signers: { $exists: true, $ne: [] },
|
||||
SignedUrl: { $ne: null },
|
||||
Placeholders: { $ne: null },
|
||||
IsCompleted: { $ne: true },
|
||||
IsDeclined: { $ne: true },
|
||||
@@ -216,6 +223,10 @@ export default function reportJson(id, userId) {
|
||||
'Signers.Name',
|
||||
'Signers.Email',
|
||||
'Signers.Phone',
|
||||
'AuditTrail',
|
||||
'AuditTrail.UserPtr',
|
||||
'ExpiryDate',
|
||||
'Placeholders',
|
||||
],
|
||||
};
|
||||
// Recent signature requests report show on dashboard
|
||||
@@ -253,6 +264,7 @@ export default function reportJson(id, userId) {
|
||||
'AuditTrail',
|
||||
'Signers.Email',
|
||||
'Signers.Phone',
|
||||
'Placeholders',
|
||||
],
|
||||
};
|
||||
// Drafts report show on dashboard
|
||||
@@ -280,6 +292,7 @@ export default function reportJson(id, userId) {
|
||||
'Signers.Name',
|
||||
'Signers.Email',
|
||||
'Signers.Phone',
|
||||
'Placeholders',
|
||||
],
|
||||
};
|
||||
// contact book report
|
||||
@@ -320,6 +333,8 @@ export default function reportJson(id, userId) {
|
||||
'Signers.Name',
|
||||
'Signers.Email',
|
||||
'Signers.Phone',
|
||||
'Placeholders',
|
||||
'IsPublic',
|
||||
],
|
||||
};
|
||||
default:
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
import axios from 'axios';
|
||||
|
||||
const serverUrl = process.env.SERVER_URL;
|
||||
const APPID = process.env.APP_ID;
|
||||
const masterKEY = process.env.MASTER_KEY;
|
||||
const clientUrl = process.env.PUBLIC_URL;
|
||||
const ssoApiUrl = process.env.SSO_API_URL || 'https://sso.opensignlabs.com/api'; //'https://osl-jacksonv2.vercel.app/api';
|
||||
/**
|
||||
* ssoSign is function which is used to sign up/sign in with SSO
|
||||
* @param code It is code return by jackson using authorize endpoint
|
||||
* @param email It is user's email with user sign in/sign up
|
||||
* @returns if success {email, name, phone message, sessiontoken} else on reject error {code, message}
|
||||
*/
|
||||
|
||||
export default async function ssoSignin(request) {
|
||||
const code = request.params.code;
|
||||
const userEmail = request.params.email;
|
||||
try {
|
||||
const headers = { 'content-type': 'application/x-www-form-urlencoded' };
|
||||
const axiosRes = await axios.post(
|
||||
ssoApiUrl + '/oauth/token',
|
||||
{
|
||||
grant_type: 'authorization_code',
|
||||
client_id: 'dummy',
|
||||
tenant: 'Okta-dev-nxglabs-in',
|
||||
product: 'OpenSign',
|
||||
client_secret: 'dummy',
|
||||
redirect_uri: clientUrl + '/sso',
|
||||
code: code,
|
||||
},
|
||||
{ headers: headers }
|
||||
);
|
||||
const ssoAccessToken = axiosRes.data && axiosRes.data.access_token;
|
||||
const authData = { sso: { id: userEmail, access_token: ssoAccessToken } };
|
||||
const userQuery = new Parse.Query(Parse.User);
|
||||
userQuery.equalTo('username', userEmail);
|
||||
const res = await userQuery.first({ useMasterKey: true });
|
||||
if (res) {
|
||||
try {
|
||||
const SignIn = await axios.put(
|
||||
serverUrl + '/users/' + res.id,
|
||||
{ authData: authData },
|
||||
{
|
||||
headers: {
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Master-key': masterKEY,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (SignIn.data) {
|
||||
const response = await axios.get(ssoApiUrl + '/oauth/userinfo', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${ssoAccessToken}`,
|
||||
},
|
||||
});
|
||||
const sessiontoken = SignIn.data.sessionToken;
|
||||
// console.log('sso sessiontoken', sessiontoken);
|
||||
const payload = {
|
||||
email: userEmail,
|
||||
name: response.data?.firstName + ' ' + response.data?.lastName,
|
||||
phone: response?.data?.phone || '',
|
||||
message: 'User Sign In',
|
||||
sessiontoken: sessiontoken,
|
||||
};
|
||||
return payload;
|
||||
}
|
||||
} catch (err) {
|
||||
const errCode = err?.response?.data?.code || err?.response?.status || err?.code || 400;
|
||||
const message =
|
||||
err?.response?.data?.error ||
|
||||
err?.response?.data ||
|
||||
err?.message ||
|
||||
'Internal server error.';
|
||||
console.log('err in user sso sign in', errCode, message);
|
||||
throw new Parse.Error(errCode, message);
|
||||
}
|
||||
} else {
|
||||
// console.log("in sign up condition");
|
||||
const response = await axios.get(ssoApiUrl + '/oauth/userinfo', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${ssoAccessToken}`,
|
||||
},
|
||||
});
|
||||
if (response.data && response.data.id) {
|
||||
try {
|
||||
const SignUp = await axios.post(
|
||||
serverUrl + '/users',
|
||||
{
|
||||
authData: authData,
|
||||
username: response.data.email,
|
||||
email: response.data.email,
|
||||
phone: response.data?.phone,
|
||||
name: response.data?.firstName + ' ' + response.data?.lastName,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Revocable-Session': '1',
|
||||
},
|
||||
}
|
||||
);
|
||||
if (SignUp.data) {
|
||||
const sessiontoken = SignUp.data.sessionToken;
|
||||
const payload = {
|
||||
email: userEmail,
|
||||
name: SignUp?.data?.name,
|
||||
phone: SignUp?.data?.phone || '',
|
||||
message: 'User Sign Up',
|
||||
sessiontoken: sessiontoken,
|
||||
};
|
||||
return payload;
|
||||
}
|
||||
} catch (err) {
|
||||
const errCode = err?.response?.data?.code || err?.response?.status || err?.code || 400;
|
||||
const message =
|
||||
err?.response?.data?.error ||
|
||||
err?.response?.data ||
|
||||
err?.message ||
|
||||
'Internal server error.';
|
||||
console.log('err in user sso sign up', errCode, message);
|
||||
throw new Parse.Error(errCode, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const errCode = err?.response?.status || err?.code || 400;
|
||||
const message = err?.response?.data || err?.message || 'Internal server error.';
|
||||
console.log('err in ssoSign', errCode, message);
|
||||
throw new Parse.Error(errCode, message);
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,9 @@ async function saveUser(userDetails) {
|
||||
user.set('username', userDetails.email);
|
||||
user.set('password', userDetails.password);
|
||||
user.set('email', userDetails.email);
|
||||
user.set('phone', userDetails.phone);
|
||||
if (userDetails?.phone) {
|
||||
user.set('phone', userDetails.phone);
|
||||
}
|
||||
user.set('name', userDetails.name);
|
||||
|
||||
const res = await user.signUp();
|
||||
@@ -77,7 +79,9 @@ export default async function usersignup(request) {
|
||||
objectId: user.id,
|
||||
});
|
||||
|
||||
partnerQuery.set('ContactNumber', userDetails.phone);
|
||||
if (userDetails?.phone) {
|
||||
partnerQuery.set('ContactNumber', userDetails.phone);
|
||||
}
|
||||
partnerQuery.set('TenantName', userDetails.name);
|
||||
partnerQuery.set('EmailAddress', userDetails.email);
|
||||
partnerQuery.set('IsActive', true);
|
||||
@@ -113,7 +117,9 @@ export default async function usersignup(request) {
|
||||
newObj.set('UserRole', userDetails.role);
|
||||
newObj.set('Email', userDetails.email);
|
||||
newObj.set('Name', userDetails.name);
|
||||
newObj.set('Phone', userDetails.phone);
|
||||
if (userDetails?.phone) {
|
||||
newObj.set('Phone', userDetails?.phone);
|
||||
}
|
||||
newObj.set('TenantId', {
|
||||
__type: 'Pointer',
|
||||
className: 'partners_Tenant',
|
||||
@@ -126,7 +132,9 @@ export default async function usersignup(request) {
|
||||
newObj.set('JobTitle', userDetails.jobTitle);
|
||||
}
|
||||
const extRes = await newObj.save(null, { useMasterKey: true });
|
||||
await saveSubscription(extRes.id, user.id, tenantRes.id, subscription);
|
||||
if (subscription) {
|
||||
await saveSubscription(extRes.id, user.id, tenantRes.id, subscription);
|
||||
}
|
||||
return { message: 'User sign up', sessionToken: user.sessionToken };
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user