Merged in release/2026-06-05 (pull request #3266)
release/2026-06-05 - Fix Documenso
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -157,3 +157,4 @@ docker_data
|
||||
.terraform
|
||||
|
||||
terraform.tfvars
|
||||
terraform.exe
|
||||
|
||||
2
documenso/terraform/.terraform.lock.hcl
generated
2
documenso/terraform/.terraform.lock.hcl
generated
@@ -5,6 +5,7 @@ provider "registry.terraform.io/hashicorp/aws" {
|
||||
version = "6.38.0"
|
||||
constraints = "~> 6.0"
|
||||
hashes = [
|
||||
"h1:IMf41BcW9huOeVcrt6XjQqadYR2xD8zkUpGLLERJ4NM=",
|
||||
"h1:RDoKIzXmt7H1mNFcNIyRT+nA/gTJyO3+iW9QGN5I2eQ=",
|
||||
"zh:143f118ae71059a7a7026c6b950da23fef04a06e2362ffa688bef75e43e869ed",
|
||||
"zh:29ee220a017306effd877e1280f8b2934dc957e16e0e72ca0222e5514d0db522",
|
||||
@@ -28,6 +29,7 @@ provider "registry.terraform.io/hashicorp/random" {
|
||||
version = "3.8.1"
|
||||
constraints = "~> 3.6"
|
||||
hashes = [
|
||||
"h1:osH3aBqEARwOz3VBJKdpFKJJCNIdgRC6k8vPojkLmlY=",
|
||||
"h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=",
|
||||
"zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4",
|
||||
"zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 4,
|
||||
"terraform_version": "1.14.3",
|
||||
"serial": 105,
|
||||
"terraform_version": "1.15.4",
|
||||
"serial": 111,
|
||||
"lineage": "2b49a6da-17c7-01da-d62f-9a13def4b683",
|
||||
"outputs": {
|
||||
"application_url": {
|
||||
@@ -21,7 +21,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"postgres_engine_version": {
|
||||
"value": "17.9",
|
||||
"value": "17.10",
|
||||
"type": "string"
|
||||
},
|
||||
"secrets_manager_secret_name": {
|
||||
@@ -118,7 +118,7 @@
|
||||
"filter": null,
|
||||
"has_major_target": null,
|
||||
"has_minor_target": null,
|
||||
"id": "17.9",
|
||||
"id": "17.10",
|
||||
"include_all": null,
|
||||
"latest": true,
|
||||
"parameter_group_family": "postgres17",
|
||||
@@ -144,15 +144,15 @@
|
||||
"supports_parallel_query": false,
|
||||
"supports_read_replica": true,
|
||||
"valid_major_targets": [
|
||||
"18.3"
|
||||
"18.4"
|
||||
],
|
||||
"valid_minor_targets": [],
|
||||
"valid_upgrade_targets": [
|
||||
"18.3"
|
||||
"18.4"
|
||||
],
|
||||
"version": "17.9",
|
||||
"version_actual": "17.9",
|
||||
"version_description": "PostgreSQL 17.9-R1"
|
||||
"version": "17.10",
|
||||
"version_actual": "17.10",
|
||||
"version_description": "PostgreSQL 17.10-R1"
|
||||
},
|
||||
"sensitive_attributes": [],
|
||||
"identity_schema_version": 0
|
||||
@@ -1085,7 +1085,7 @@
|
||||
"endpoint": "documenso-postgres.cfo5pnykioqq.ca-central-1.rds.amazonaws.com:5432",
|
||||
"engine": "postgres",
|
||||
"engine_lifecycle_support": "open-source-rds-extended-support",
|
||||
"engine_version": "17.9",
|
||||
"engine_version": "17.10",
|
||||
"engine_version_actual": "17.9",
|
||||
"final_snapshot_identifier": "documenso-final-03443461",
|
||||
"hosted_zone_id": "Z1JG78A3UK1DU3",
|
||||
@@ -1096,7 +1096,7 @@
|
||||
"instance_class": "db.t4g.micro",
|
||||
"iops": 3000,
|
||||
"kms_key_id": "arn:aws:kms:ca-central-1:714144183158:key/1237b672-91b3-4d23-958d-1877c5d22eb9",
|
||||
"latest_restorable_time": "2026-05-01T17:49:36Z",
|
||||
"latest_restorable_time": "2026-05-25T20:16:55Z",
|
||||
"license_model": "postgresql-license",
|
||||
"listener_endpoint": [],
|
||||
"maintenance_window": "tue:03:10-tue:03:40",
|
||||
@@ -1384,7 +1384,7 @@
|
||||
"Application": "documenso",
|
||||
"ManagedBy": "Terraform"
|
||||
},
|
||||
"task_definition": "arn:aws:ecs:ca-central-1:714144183158:task-definition/documenso-task:8",
|
||||
"task_definition": "arn:aws:ecs:ca-central-1:714144183158:task-definition/documenso-task:9",
|
||||
"timeouts": null,
|
||||
"triggers": {},
|
||||
"volume_configuration": [],
|
||||
@@ -1451,9 +1451,9 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"attributes": {
|
||||
"arn": "arn:aws:ecs:ca-central-1:714144183158:task-definition/documenso-task:8",
|
||||
"arn": "arn:aws:ecs:ca-central-1:714144183158:task-definition/documenso-task:9",
|
||||
"arn_without_revision": "arn:aws:ecs:ca-central-1:714144183158:task-definition/documenso-task",
|
||||
"container_definitions": "[{\"environment\":[{\"name\":\"NEXT_PRIVATE_INTERNAL_WEBAPP_URL\",\"value\":\"http://127.0.0.1:3000\"},{\"name\":\"NEXT_PRIVATE_SMTP_HOST\",\"value\":\"email-smtp.ca-central-1.amazonaws.com\"},{\"name\":\"NEXT_PRIVATE_SMTP_PORT\",\"value\":\"587\"},{\"name\":\"NEXT_PRIVATE_SMTP_SECURE\",\"value\":\"false\"},{\"name\":\"NEXT_PRIVATE_SMTP_TRANSPORT\",\"value\":\"smtp-auth\"},{\"name\":\"NEXT_PRIVATE_SMTP_UNSAFE_IGNORE_TLS\",\"value\":\"false\"},{\"name\":\"NEXT_PRIVATE_UPLOAD_BUCKET\",\"value\":\"documenso-714144183158-ca-central-1\"},{\"name\":\"NEXT_PRIVATE_UPLOAD_REGION\",\"value\":\"ca-central-1\"},{\"name\":\"NEXT_PUBLIC_DISABLE_SIGNUP\",\"value\":\"true\"},{\"name\":\"NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT\",\"value\":\"10\"},{\"name\":\"NEXT_PUBLIC_UPLOAD_TRANSPORT\",\"value\":\"s3\"},{\"name\":\"NEXT_PUBLIC_WEBAPP_URL\",\"value\":\"https://sign.imex.online\"},{\"name\":\"PORT\",\"value\":\"3000\"}],\"essential\":true,\"image\":\"documenso/documenso:2.10.0\",\"logConfiguration\":{\"logDriver\":\"awslogs\",\"options\":{\"awslogs-group\":\"/ecs/documenso\",\"awslogs-region\":\"ca-central-1\",\"awslogs-stream-prefix\":\"documenso\"}},\"mountPoints\":[],\"name\":\"documenso\",\"portMappings\":[{\"containerPort\":3000,\"hostPort\":3000,\"protocol\":\"tcp\"}],\"secrets\":[{\"name\":\"NEXTAUTH_SECRET\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXTAUTH_SECRET::\"},{\"name\":\"NEXT_PRIVATE_ALLOWED_SIGNUP_DOMAINS\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_ALLOWED_SIGNUP_DOMAINS::\"},{\"name\":\"NEXT_PRIVATE_DATABASE_URL\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_DATABASE_URL::\"},{\"name\":\"NEXT_PRIVATE_DIRECT_DATABASE_URL\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_DIRECT_DATABASE_URL::\"},{\"name\":\"NEXT_PRIVATE_DOCUMENSO_LICENSE_KEY\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_DOCUMENSO_LICENSE_KEY::\"},{\"name\":\"NEXT_PRIVATE_ENCRYPTION_KEY\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_ENCRYPTION_KEY::\"},{\"name\":\"NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY::\"},{\"name\":\"NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS::\"},{\"name\":\"NEXT_PRIVATE_SIGNING_PASSPHRASE\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SIGNING_PASSPHRASE::\"},{\"name\":\"NEXT_PRIVATE_SMTP_FROM_ADDRESS\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SMTP_FROM_ADDRESS::\"},{\"name\":\"NEXT_PRIVATE_SMTP_FROM_NAME\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SMTP_FROM_NAME::\"},{\"name\":\"NEXT_PRIVATE_SMTP_PASSWORD\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SMTP_PASSWORD::\"},{\"name\":\"NEXT_PRIVATE_SMTP_USERNAME\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SMTP_USERNAME::\"},{\"name\":\"NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID::\"},{\"name\":\"NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY::\"}],\"systemControls\":[],\"volumesFrom\":[]}]",
|
||||
"container_definitions": "[{\"environment\":[{\"name\":\"NEXT_PRIVATE_INTERNAL_WEBAPP_URL\",\"value\":\"http://127.0.0.1:3000\"},{\"name\":\"NEXT_PRIVATE_SMTP_HOST\",\"value\":\"email-smtp.ca-central-1.amazonaws.com\"},{\"name\":\"NEXT_PRIVATE_SMTP_PORT\",\"value\":\"587\"},{\"name\":\"NEXT_PRIVATE_SMTP_SECURE\",\"value\":\"false\"},{\"name\":\"NEXT_PRIVATE_SMTP_TRANSPORT\",\"value\":\"smtp-auth\"},{\"name\":\"NEXT_PRIVATE_SMTP_UNSAFE_IGNORE_TLS\",\"value\":\"false\"},{\"name\":\"NEXT_PRIVATE_UPLOAD_BUCKET\",\"value\":\"documenso-714144183158-ca-central-1\"},{\"name\":\"NEXT_PRIVATE_UPLOAD_REGION\",\"value\":\"ca-central-1\"},{\"name\":\"NEXT_PUBLIC_DISABLE_SIGNUP\",\"value\":\"true\"},{\"name\":\"NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT\",\"value\":\"10\"},{\"name\":\"NEXT_PUBLIC_UPLOAD_TRANSPORT\",\"value\":\"s3\"},{\"name\":\"NEXT_PUBLIC_WEBAPP_URL\",\"value\":\"https://sign.imex.online\"},{\"name\":\"PORT\",\"value\":\"3000\"}],\"essential\":true,\"image\":\"documenso/documenso:2.11.0\",\"logConfiguration\":{\"logDriver\":\"awslogs\",\"options\":{\"awslogs-group\":\"/ecs/documenso\",\"awslogs-region\":\"ca-central-1\",\"awslogs-stream-prefix\":\"documenso\"}},\"mountPoints\":[],\"name\":\"documenso\",\"portMappings\":[{\"containerPort\":3000,\"hostPort\":3000,\"protocol\":\"tcp\"}],\"secrets\":[{\"name\":\"NEXTAUTH_SECRET\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXTAUTH_SECRET::\"},{\"name\":\"NEXT_PRIVATE_ALLOWED_SIGNUP_DOMAINS\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_ALLOWED_SIGNUP_DOMAINS::\"},{\"name\":\"NEXT_PRIVATE_DATABASE_URL\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_DATABASE_URL::\"},{\"name\":\"NEXT_PRIVATE_DIRECT_DATABASE_URL\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_DIRECT_DATABASE_URL::\"},{\"name\":\"NEXT_PRIVATE_DOCUMENSO_LICENSE_KEY\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_DOCUMENSO_LICENSE_KEY::\"},{\"name\":\"NEXT_PRIVATE_ENCRYPTION_KEY\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_ENCRYPTION_KEY::\"},{\"name\":\"NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY::\"},{\"name\":\"NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS::\"},{\"name\":\"NEXT_PRIVATE_SIGNING_PASSPHRASE\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SIGNING_PASSPHRASE::\"},{\"name\":\"NEXT_PRIVATE_SMTP_FROM_ADDRESS\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SMTP_FROM_ADDRESS::\"},{\"name\":\"NEXT_PRIVATE_SMTP_FROM_NAME\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SMTP_FROM_NAME::\"},{\"name\":\"NEXT_PRIVATE_SMTP_PASSWORD\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SMTP_PASSWORD::\"},{\"name\":\"NEXT_PRIVATE_SMTP_USERNAME\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_SMTP_USERNAME::\"},{\"name\":\"NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID::\"},{\"name\":\"NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY\",\"valueFrom\":\"arn:aws:secretsmanager:ca-central-1:714144183158:secret:documenso/sign-imex-online/app-DNl1NE:NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY::\"}],\"systemControls\":[],\"volumesFrom\":[]}]",
|
||||
"cpu": "512",
|
||||
"enable_fault_injection": false,
|
||||
"ephemeral_storage": [],
|
||||
@@ -1470,7 +1470,7 @@
|
||||
"requires_compatibilities": [
|
||||
"FARGATE"
|
||||
],
|
||||
"revision": 8,
|
||||
"revision": 9,
|
||||
"runtime_platform": [],
|
||||
"skip_destroy": false,
|
||||
"tags": {
|
||||
@@ -1498,7 +1498,7 @@
|
||||
"account_id": "714144183158",
|
||||
"family": "documenso-task",
|
||||
"region": "ca-central-1",
|
||||
"revision": 8
|
||||
"revision": 9
|
||||
},
|
||||
"private": "eyJzY2hlbWFfdmVyc2lvbiI6IjEifQ==",
|
||||
"dependencies": [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 4,
|
||||
"terraform_version": "1.14.3",
|
||||
"serial": 101,
|
||||
"terraform_version": "1.15.4",
|
||||
"serial": 105,
|
||||
"lineage": "2b49a6da-17c7-01da-d62f-9a13def4b683",
|
||||
"outputs": {
|
||||
"application_url": {
|
||||
@@ -1096,7 +1096,7 @@
|
||||
"instance_class": "db.t4g.micro",
|
||||
"iops": 3000,
|
||||
"kms_key_id": "arn:aws:kms:ca-central-1:714144183158:key/1237b672-91b3-4d23-958d-1877c5d22eb9",
|
||||
"latest_restorable_time": "2026-05-01T15:49:30Z",
|
||||
"latest_restorable_time": "2026-05-01T17:49:36Z",
|
||||
"license_model": "postgresql-license",
|
||||
"listener_endpoint": [],
|
||||
"maintenance_window": "tue:03:10-tue:03:40",
|
||||
@@ -3551,7 +3551,7 @@
|
||||
],
|
||||
"description": "WAF protection for Documenso",
|
||||
"id": "04577153-2a1a-462c-94b8-b0a1804755bb",
|
||||
"lock_token": "e71f2816-492c-4afc-acc2-3700795c2657",
|
||||
"lock_token": "417061f1-deea-4ac2-b932-9bea49265444",
|
||||
"name": "documenso-web-acl",
|
||||
"name_prefix": "",
|
||||
"region": "ca-central-1",
|
||||
@@ -3693,7 +3693,24 @@
|
||||
{
|
||||
"managed_rule_group_configs": [],
|
||||
"name": "AWSManagedRulesCommonRuleSet",
|
||||
"rule_action_override": [],
|
||||
"rule_action_override": [
|
||||
{
|
||||
"action_to_use": [
|
||||
{
|
||||
"allow": [],
|
||||
"block": [],
|
||||
"captcha": [],
|
||||
"challenge": [],
|
||||
"count": [
|
||||
{
|
||||
"custom_request_handling": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"name": "SizeRestrictions_BODY"
|
||||
}
|
||||
],
|
||||
"scope_down_statement": [],
|
||||
"vendor_name": "AWS",
|
||||
"version": ""
|
||||
|
||||
@@ -1,488 +1,526 @@
|
||||
|
||||
const { Documenso } = require("@documenso/sdk-typescript");
|
||||
const axios = require("axios");
|
||||
const { jsrAuthString } = require("../utils/utils");
|
||||
const logger = require("../utils/logger");
|
||||
//Need to pull the key dynamically to send documents.
|
||||
//Need to pull the key dynamically to send documents.
|
||||
const JSR_SERVER = process.env.JSR_URL || "https://reports.imex.online";
|
||||
const DOCUMENSO_SERVER_URL = process.env.DOCUMENSO_SERVER_URL || "https://sign.imex.online/api/v2";
|
||||
const jsreport = require("@jsreport/nodejs-client");
|
||||
const { QUERY_JOB_FOR_SIGNATURE, INSERT_ESIGNATURE_DOCUMENT, DISTRIBUTE_ESIGNATURE_DOCUMENT, QUERY_ESIGNATURE_BY_EXTERNAL_ID, UPDATE_ESIGNATURE_DOCUMENT, QUERY_DOCUMENSO_KEY, INSERT_ESIG_AUDIT_TRAIL } = require("../graphql-client/queries");
|
||||
const {
|
||||
QUERY_JOB_FOR_SIGNATURE,
|
||||
INSERT_ESIGNATURE_DOCUMENT,
|
||||
DISTRIBUTE_ESIGNATURE_DOCUMENT,
|
||||
QUERY_ESIGNATURE_BY_EXTERNAL_ID,
|
||||
UPDATE_ESIGNATURE_DOCUMENT,
|
||||
QUERY_DOCUMENSO_KEY,
|
||||
INSERT_ESIG_AUDIT_TRAIL
|
||||
} = require("../graphql-client/queries");
|
||||
const _ = require("lodash");
|
||||
|
||||
function parseJsonField(value, fallback = null) {
|
||||
if (value === undefined || value === null) {
|
||||
return fallback;
|
||||
}
|
||||
if (value === undefined || value === null) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
if (typeof value !== "string") {
|
||||
return value;
|
||||
}
|
||||
if (typeof value !== "string") {
|
||||
return value;
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultEsignData({ esigData, bodyshop, fileName }) {
|
||||
const fallbackTitle = fileName || `Esign request from ${bodyshop.shopname}`;
|
||||
const fallbackTitle = fileName || `Esign request from ${bodyshop.shopname}`;
|
||||
|
||||
return {
|
||||
...esigData,
|
||||
title: esigData?.title || fallbackTitle,
|
||||
subject: esigData?.subject || `Esign request from ${bodyshop.shopname}`,
|
||||
message: esigData?.message || `Please review and sign the document from ${bodyshop.shopname}.`
|
||||
};
|
||||
return {
|
||||
...esigData,
|
||||
title: esigData?.title || fallbackTitle,
|
||||
subject: esigData?.subject || `Esign request from ${bodyshop.shopname}`,
|
||||
message: esigData?.message || `Please review and sign the document from ${bodyshop.shopname}.`
|
||||
};
|
||||
}
|
||||
|
||||
function createClientError(message, statusCode = 400) {
|
||||
const error = new Error(message);
|
||||
error.statusCode = statusCode;
|
||||
return error;
|
||||
const error = new Error(message);
|
||||
error.statusCode = statusCode;
|
||||
return error;
|
||||
}
|
||||
|
||||
function isValidEmail(email) {
|
||||
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
||||
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
||||
}
|
||||
|
||||
function getJobOwnerName(jobData, email) {
|
||||
const ownerName = [jobData?.ownr_fn, jobData?.ownr_ln].filter(Boolean).join(" ").trim();
|
||||
return ownerName || jobData?.ownr_co_nm || email;
|
||||
const ownerName = [jobData?.ownr_fn, jobData?.ownr_ln].filter(Boolean).join(" ").trim();
|
||||
return ownerName || jobData?.ownr_co_nm || email;
|
||||
}
|
||||
|
||||
function getJobOwnerRecipients(jobData) {
|
||||
const ownerEmail = jobData?.ownr_ea?.trim();
|
||||
const ownerEmail = jobData?.ownr_ea?.trim();
|
||||
|
||||
if (!ownerEmail) {
|
||||
throw createClientError("Job owner email is required before sending an e-signature request.");
|
||||
if (!ownerEmail) {
|
||||
throw createClientError("Job owner email is required before sending an e-signature request.");
|
||||
}
|
||||
|
||||
if (!isValidEmail(ownerEmail)) {
|
||||
throw createClientError(`Job owner email "${ownerEmail}" is not valid.`);
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
email: ownerEmail,
|
||||
name: getJobOwnerName(jobData, ownerEmail),
|
||||
role: "SIGNER"
|
||||
}
|
||||
|
||||
if (!isValidEmail(ownerEmail)) {
|
||||
throw createClientError(`Job owner email "${ownerEmail}" is not valid.`);
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
email: ownerEmail,
|
||||
name: getJobOwnerName(jobData, ownerEmail),
|
||||
role: "SIGNER"
|
||||
}
|
||||
];
|
||||
];
|
||||
}
|
||||
|
||||
async function getDocumensoClient({ bodyshopid, req }) {
|
||||
const client = req.userGraphQLClient;
|
||||
const { bodyshops_by_pk: { documenso_api_key } } = await client.request(QUERY_DOCUMENSO_KEY, { bodyshopid });
|
||||
return new Documenso({
|
||||
apiKey: documenso_api_key,//Done on a by team basis,
|
||||
serverURL: "https://sign.imex.online/api/v2",
|
||||
});
|
||||
const { apiKey } = await getDocumensoConfig({ bodyshopid, req });
|
||||
return new Documenso({
|
||||
apiKey,
|
||||
serverURL: DOCUMENSO_SERVER_URL
|
||||
});
|
||||
}
|
||||
|
||||
async function getDocumensoConfig({ bodyshopid, req }) {
|
||||
const client = req.userGraphQLClient;
|
||||
const {
|
||||
bodyshops_by_pk: { documenso_api_key }
|
||||
} = await client.request(QUERY_DOCUMENSO_KEY, { bodyshopid });
|
||||
|
||||
return {
|
||||
apiKey: documenso_api_key,
|
||||
serverURL: DOCUMENSO_SERVER_URL
|
||||
};
|
||||
}
|
||||
|
||||
async function getDocumensoDocument({ apiKey, documentId }) {
|
||||
const { data } = await axios.get(`${DOCUMENSO_SERVER_URL}/document/${encodeURIComponent(documentId)}`, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
Authorization: apiKey
|
||||
}
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async function createEsignDocumentFromPdf({ req, bodyshop, pdfBuffer, esigData, fileName }) {
|
||||
const resolvedEsigData = getDefaultEsignData({ esigData, bodyshop, fileName });
|
||||
const fileBlob = new Blob([pdfBuffer], { type: "application/pdf" });
|
||||
const jobid = req.body.jobid;
|
||||
const client = req.userGraphQLClient;
|
||||
const resolvedEsigData = getDefaultEsignData({ esigData, bodyshop, fileName });
|
||||
const fileBlob = new Blob([pdfBuffer], { type: "application/pdf" });
|
||||
const jobid = req.body.jobid;
|
||||
const client = req.userGraphQLClient;
|
||||
|
||||
const { jobs_by_pk: jobData } = await client.request(QUERY_JOB_FOR_SIGNATURE, { jobid });
|
||||
const recipients = getJobOwnerRecipients(jobData);
|
||||
const { jobs_by_pk: jobData } = await client.request(QUERY_JOB_FOR_SIGNATURE, { jobid });
|
||||
const recipients = getJobOwnerRecipients(jobData);
|
||||
|
||||
const documenso = await getDocumensoClient({ bodyshopid: bodyshop.id, req })
|
||||
const documensoConfig = await getDocumensoConfig({ bodyshopid: bodyshop.id, req });
|
||||
const documenso = new Documenso({
|
||||
apiKey: documensoConfig.apiKey,
|
||||
serverURL: documensoConfig.serverURL
|
||||
});
|
||||
|
||||
const createDocumentResponse = await documenso.documents.create({
|
||||
payload: {
|
||||
title: resolvedEsigData.title,
|
||||
externalId: `${jobid}|${req.user?.email}`,
|
||||
recipients,
|
||||
meta: {
|
||||
timezone: bodyshop.timezone,
|
||||
dateFormat: "MM/dd/yyyy hh:mm a",
|
||||
language: "en",
|
||||
subject: resolvedEsigData.subject,
|
||||
message: resolvedEsigData.message,
|
||||
}
|
||||
},
|
||||
file: fileBlob
|
||||
});
|
||||
const createDocumentResponse = await documenso.documents.create({
|
||||
payload: {
|
||||
title: resolvedEsigData.title,
|
||||
externalId: `${jobid}|${req.user?.email}`,
|
||||
recipients,
|
||||
meta: {
|
||||
timezone: bodyshop.timezone,
|
||||
dateFormat: "MM/dd/yyyy hh:mm a",
|
||||
language: "en",
|
||||
subject: resolvedEsigData.subject,
|
||||
message: resolvedEsigData.message
|
||||
}
|
||||
},
|
||||
file: fileBlob
|
||||
});
|
||||
|
||||
const documentResult = await documenso.documents.get({
|
||||
documentId: createDocumentResponse.id,
|
||||
});
|
||||
const documentResult = await getDocumensoDocument({
|
||||
apiKey: documensoConfig.apiKey,
|
||||
documentId: createDocumentResponse.id
|
||||
});
|
||||
|
||||
if (resolvedEsigData?.fields && resolvedEsigData.fields.length > 0) {
|
||||
try {
|
||||
await documenso.envelopes.fields.createMany({
|
||||
envelopeId: createDocumentResponse.envelopeId,
|
||||
data: resolvedEsigData.fields.map(sigField => ({ ...sigField, recipientId: documentResult.recipients[0].id, }))
|
||||
});
|
||||
} catch (error) {
|
||||
logger.log(`esig-new-fields-error`, "ERROR", "esig", "api", {
|
||||
message: error.message, stack: error.stack,
|
||||
body: req.body
|
||||
});
|
||||
}
|
||||
if (resolvedEsigData?.fields && resolvedEsigData.fields.length > 0) {
|
||||
try {
|
||||
await documenso.envelopes.fields.createMany({
|
||||
envelopeId: createDocumentResponse.envelopeId,
|
||||
data: resolvedEsigData.fields.map((sigField) => ({ ...sigField, recipientId: documentResult.recipients[0].id }))
|
||||
});
|
||||
} catch (error) {
|
||||
logger.log(`esig-new-fields-error`, "ERROR", "esig", "api", {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
body: req.body
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const presignToken = await documenso.embedding.embeddingPresignCreateEmbeddingPresignToken({});
|
||||
const presignToken = await documenso.embedding.embeddingPresignCreateEmbeddingPresignToken({});
|
||||
|
||||
await client.request(INSERT_ESIGNATURE_DOCUMENT, {
|
||||
audit: {
|
||||
jobid,
|
||||
bodyshopid: bodyshop.id,
|
||||
operation: `Esignature document created. Subject: ${resolvedEsigData.subject || "No subject"}, Message: ${resolvedEsigData.message || "No message"}. Document ID: ${createDocumentResponse.id} Envlope ID: ${createDocumentResponse.envelopeId}`,
|
||||
useremail: req.user?.email,
|
||||
type: 'esig-create'
|
||||
},
|
||||
esig: {
|
||||
jobid,
|
||||
external_document_id: createDocumentResponse.id.toString(),
|
||||
subject: resolvedEsigData.subject || "No subject",
|
||||
message: resolvedEsigData.message || "No message",
|
||||
title: resolvedEsigData.title || "No title",
|
||||
status: "DRAFT",
|
||||
recipients: recipients,
|
||||
}
|
||||
});
|
||||
await client.request(INSERT_ESIGNATURE_DOCUMENT, {
|
||||
audit: {
|
||||
jobid,
|
||||
bodyshopid: bodyshop.id,
|
||||
operation: `Esignature document created. Subject: ${resolvedEsigData.subject || "No subject"}, Message: ${resolvedEsigData.message || "No message"}. Document ID: ${createDocumentResponse.id} Envlope ID: ${createDocumentResponse.envelopeId}`,
|
||||
useremail: req.user?.email,
|
||||
type: "esig-create"
|
||||
},
|
||||
esig: {
|
||||
jobid,
|
||||
external_document_id: createDocumentResponse.id.toString(),
|
||||
subject: resolvedEsigData.subject || "No subject",
|
||||
message: resolvedEsigData.message || "No message",
|
||||
title: resolvedEsigData.title || "No title",
|
||||
status: "DRAFT",
|
||||
recipients: recipients
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
token: presignToken.token,
|
||||
documentId: createDocumentResponse.id,
|
||||
envelopeId: createDocumentResponse.envelopeId
|
||||
};
|
||||
return {
|
||||
token: presignToken.token,
|
||||
documentId: createDocumentResponse.id,
|
||||
envelopeId: createDocumentResponse.envelopeId
|
||||
};
|
||||
}
|
||||
|
||||
async function distributeDocument(req, res) {
|
||||
try {
|
||||
const client = req.userGraphQLClient;
|
||||
try {
|
||||
const client = req.userGraphQLClient;
|
||||
|
||||
const { documentId, bodyshopid } = req.body;
|
||||
const documenso = await getDocumensoClient({ bodyshopid, req })
|
||||
const { documentId, bodyshopid } = req.body;
|
||||
const documenso = await getDocumensoClient({ bodyshopid, req });
|
||||
|
||||
const distributeResult = await documenso.documents.distribute({
|
||||
documentId,
|
||||
});
|
||||
const distributeResult = await documenso.documents.distribute({
|
||||
documentId
|
||||
});
|
||||
|
||||
await client.request(DISTRIBUTE_ESIGNATURE_DOCUMENT, {
|
||||
external_document_id: documentId.toString(),
|
||||
esig_update: {
|
||||
status: "SENT"
|
||||
},
|
||||
audit: {
|
||||
jobid: req.body.jobid,
|
||||
bodyshopid: req.body.bodyshopid,
|
||||
operation: `Esignature document with title ${distributeResult.title} (ID: ${documentId}) distributed to recipients.`,
|
||||
useremail: req.user?.email,
|
||||
type: 'esig-distribute'
|
||||
}
|
||||
})
|
||||
await client.request(DISTRIBUTE_ESIGNATURE_DOCUMENT, {
|
||||
external_document_id: documentId.toString(),
|
||||
esig_update: {
|
||||
status: "SENT"
|
||||
},
|
||||
audit: {
|
||||
jobid: req.body.jobid,
|
||||
bodyshopid: req.body.bodyshopid,
|
||||
operation: `Esignature document with title ${distributeResult.title} (ID: ${documentId}) distributed to recipients.`,
|
||||
useremail: req.user?.email,
|
||||
type: "esig-distribute"
|
||||
}
|
||||
});
|
||||
|
||||
res.json({ success: true, distributeResult });
|
||||
} catch (error) {
|
||||
|
||||
logger.log(`esig-distribute-error`, "ERROR", "esig", "api", {
|
||||
message: error.message, stack: error.stack,
|
||||
body: req.body
|
||||
});
|
||||
res.status(500).json({ error: "An error occurred while distributing the document.", message: error.message });
|
||||
}
|
||||
res.json({ success: true, distributeResult });
|
||||
} catch (error) {
|
||||
logger.log(`esig-distribute-error`, "ERROR", "esig", "api", {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
body: req.body
|
||||
});
|
||||
res.status(500).json({ error: "An error occurred while distributing the document.", message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
async function redistributeDocument(req, res) {
|
||||
try {
|
||||
const client = req.userGraphQLClient;
|
||||
try {
|
||||
const client = req.userGraphQLClient;
|
||||
|
||||
const { documentId, bodyshopid } = req.body;
|
||||
const documenso = await getDocumensoClient({ bodyshopid, req })
|
||||
const { documentId, bodyshopid } = req.body;
|
||||
const documensoConfig = await getDocumensoConfig({ bodyshopid, req });
|
||||
const documenso = new Documenso({
|
||||
apiKey: documensoConfig.apiKey,
|
||||
serverURL: documensoConfig.serverURL
|
||||
});
|
||||
|
||||
const document = await getDocumensoDocument({
|
||||
apiKey: documensoConfig.apiKey,
|
||||
documentId: parseInt(documentId)
|
||||
});
|
||||
|
||||
const document = await documenso.documents.get({
|
||||
documentId: parseInt(documentId)
|
||||
});
|
||||
const distributeResult = await documenso.documents.redistribute({
|
||||
documentId: parseInt(documentId),
|
||||
recipients: document.recipients.filter((r) => r.signingStatus === "NOT_SIGNED").map((r) => r.id)
|
||||
});
|
||||
|
||||
const distributeResult = await documenso.documents.redistribute({
|
||||
documentId: parseInt(documentId),
|
||||
recipients: document.recipients.filter(r => r.signingStatus === "NOT_SIGNED").map(r => r.id)
|
||||
});
|
||||
await client.request(INSERT_ESIG_AUDIT_TRAIL, {
|
||||
obj: {
|
||||
jobid: req.body.jobid,
|
||||
bodyshopid: req.body.bodyshopid,
|
||||
operation: `Esignature document with title ${distributeResult.title} (ID: ${documentId}) redistributed to recipients.`,
|
||||
useremail: req.user?.email,
|
||||
type: "esig-redistribute"
|
||||
}
|
||||
});
|
||||
|
||||
await client.request(INSERT_ESIG_AUDIT_TRAIL, {
|
||||
obj: {
|
||||
jobid: req.body.jobid,
|
||||
bodyshopid: req.body.bodyshopid,
|
||||
operation: `Esignature document with title ${distributeResult.title} (ID: ${documentId}) redistributed to recipients.`,
|
||||
useremail: req.user?.email,
|
||||
type: 'esig-redistribute'
|
||||
}
|
||||
})
|
||||
|
||||
res.json({ success: true, distributeResult });
|
||||
} catch (error) {
|
||||
|
||||
logger.log(`esig-redistribute-error`, "ERROR", "esig", "api", {
|
||||
message: error.message, stack: error.stack,
|
||||
body: req.body
|
||||
});
|
||||
res.status(500).json({ error: "An error occurred while redistributing the document.", message: error.message });
|
||||
}
|
||||
res.json({ success: true, distributeResult });
|
||||
} catch (error) {
|
||||
logger.log(`esig-redistribute-error`, "ERROR", "esig", "api", {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
body: req.body
|
||||
});
|
||||
res.status(500).json({ error: "An error occurred while redistributing the document.", message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteDocument(req, res) {
|
||||
try {
|
||||
const client = req.userGraphQLClient;
|
||||
try {
|
||||
const client = req.userGraphQLClient;
|
||||
|
||||
const { documentId, bodyshopid } = req.body;
|
||||
const { esignature_documents } = await client.request(QUERY_ESIGNATURE_BY_EXTERNAL_ID, { external_document_id: documentId.toString() });
|
||||
const { documentId, bodyshopid } = req.body;
|
||||
const { esignature_documents } = await client.request(QUERY_ESIGNATURE_BY_EXTERNAL_ID, {
|
||||
external_document_id: documentId.toString()
|
||||
});
|
||||
|
||||
if (!esignature_documents || esignature_documents.length === 0) {
|
||||
//return res.status(404).json({ error: "Document not found" });
|
||||
}
|
||||
const documenso = await getDocumensoClient({ bodyshopid, req })
|
||||
|
||||
const deleteResult = await documenso.documents.delete({
|
||||
documentId: (documentId)
|
||||
});
|
||||
|
||||
await client.request(UPDATE_ESIGNATURE_DOCUMENT, {
|
||||
external_document_id: documentId.toString(),
|
||||
esig_update: {
|
||||
status: "DELETED"
|
||||
}
|
||||
})
|
||||
res.json({ success: true, deleteResult });
|
||||
} catch (error) {
|
||||
|
||||
logger.log(`esig-delete-error`, "ERROR", "esig", "api", {
|
||||
message: error.message, stack: error.stack,
|
||||
body: req.body
|
||||
});
|
||||
res.status(500).json({ error: "An error occurred while deleting the document." });
|
||||
if (!esignature_documents || esignature_documents.length === 0) {
|
||||
//return res.status(404).json({ error: "Document not found" });
|
||||
}
|
||||
const documenso = await getDocumensoClient({ bodyshopid, req });
|
||||
|
||||
const deleteResult = await documenso.documents.delete({
|
||||
documentId: documentId
|
||||
});
|
||||
|
||||
await client.request(UPDATE_ESIGNATURE_DOCUMENT, {
|
||||
external_document_id: documentId.toString(),
|
||||
esig_update: {
|
||||
status: "DELETED"
|
||||
}
|
||||
});
|
||||
res.json({ success: true, deleteResult });
|
||||
} catch (error) {
|
||||
logger.log(`esig-delete-error`, "ERROR", "esig", "api", {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
body: req.body
|
||||
});
|
||||
res.status(500).json({ error: "An error occurred while deleting the document." });
|
||||
}
|
||||
}
|
||||
|
||||
async function viewDocument(req, res) {
|
||||
try {
|
||||
const { documentId, bodyshopid } = req.body;
|
||||
const documenso = await getDocumensoClient({ bodyshopid, req })
|
||||
try {
|
||||
const { documentId, bodyshopid } = req.body;
|
||||
const documenso = await getDocumensoClient({ bodyshopid, req });
|
||||
|
||||
const document = await documenso.document.documentDownload({
|
||||
documentId: parseInt(documentId)
|
||||
});
|
||||
res.json({ success: true, document });
|
||||
} catch (error) {
|
||||
|
||||
logger.log(`esig-view-error`, "ERROR", "esig", "api", {
|
||||
message: error.message, stack: error.stack,
|
||||
body: req.body
|
||||
});
|
||||
res.status(500).json({ error: "An error occurred while retrieving the document.", message: error.message });
|
||||
}
|
||||
const document = await documenso.document.documentDownload({
|
||||
documentId: parseInt(documentId)
|
||||
});
|
||||
res.json({ success: true, document });
|
||||
} catch (error) {
|
||||
logger.log(`esig-view-error`, "ERROR", "esig", "api", {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
body: req.body
|
||||
});
|
||||
res.status(500).json({ error: "An error occurred while retrieving the document.", message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
async function newEsignDocument(req, res) {
|
||||
try {
|
||||
const client = req.userGraphQLClient;
|
||||
const { bodyshop } = req.body;
|
||||
const { pdf: fileBuffer, esigData } = await RenderTemplate({ client, req });
|
||||
const result = await createEsignDocumentFromPdf({
|
||||
req,
|
||||
bodyshop,
|
||||
pdfBuffer: fileBuffer,
|
||||
esigData
|
||||
});
|
||||
try {
|
||||
const client = req.userGraphQLClient;
|
||||
const { bodyshop } = req.body;
|
||||
const { pdf: fileBuffer, esigData } = await RenderTemplate({ client, req });
|
||||
const result = await createEsignDocumentFromPdf({
|
||||
req,
|
||||
bodyshop,
|
||||
pdfBuffer: fileBuffer,
|
||||
esigData
|
||||
});
|
||||
|
||||
res.json(result);
|
||||
}
|
||||
catch (error) {
|
||||
logger.log(`esig-new-error`, "ERROR", "esig", "api", {
|
||||
message: error.message, stack: error.stack,
|
||||
body: _.omit(req.body, ["bodyshop"]) // bodyshop can be large, so we omit it from the logs
|
||||
});
|
||||
res.status(error.statusCode || 500).json({ error: "An error occurred while creating the e-sign document.", message: error.message });
|
||||
}
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
logger.log(`esig-new-error`, "ERROR", "esig", "api", {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
body: _.omit(req.body, ["bodyshop"]) // bodyshop can be large, so we omit it from the logs
|
||||
});
|
||||
res
|
||||
.status(error.statusCode || 500)
|
||||
.json({ error: "An error occurred while creating the e-sign document.", message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
async function newCustomEsignDocument(req, res) {
|
||||
try {
|
||||
const bodyshop = parseJsonField(req.body.bodyshop, req.body.bodyshop);
|
||||
const esigData = parseJsonField(req.body.esigData, {});
|
||||
const uploadedDocument = req.file;
|
||||
try {
|
||||
const bodyshop = parseJsonField(req.body.bodyshop, req.body.bodyshop);
|
||||
const esigData = parseJsonField(req.body.esigData, {});
|
||||
const uploadedDocument = req.file;
|
||||
|
||||
if (!uploadedDocument?.buffer) {
|
||||
return res.status(400).json({ error: "A PDF document is required." });
|
||||
}
|
||||
|
||||
if (uploadedDocument.mimetype !== "application/pdf") {
|
||||
return res.status(400).json({ error: "Only PDF documents can be used for e-signature." });
|
||||
}
|
||||
|
||||
req.body.bodyshop = bodyshop;
|
||||
|
||||
const fileName = uploadedDocument.originalname?.replace(/\.[^.]+$/, "") || undefined;
|
||||
const result = await createEsignDocumentFromPdf({
|
||||
req,
|
||||
bodyshop,
|
||||
pdfBuffer: uploadedDocument.buffer,
|
||||
esigData,
|
||||
fileName
|
||||
});
|
||||
res.json(result);
|
||||
if (!uploadedDocument?.buffer) {
|
||||
return res.status(400).json({ error: "A PDF document is required." });
|
||||
}
|
||||
catch (error) {
|
||||
logger.log(`esig-new-custom-error`, "ERROR", "esig", "api", {
|
||||
message: error.message, stack: error.stack,
|
||||
body: _.omit(req.body, ["bodyshop"]) // bodyshop can be large, so we omit it from the logs
|
||||
});
|
||||
res.status(error.statusCode || 500).json({ error: "An error occurred while creating the custom e-sign document.", message: error.message });
|
||||
|
||||
if (uploadedDocument.mimetype !== "application/pdf") {
|
||||
return res.status(400).json({ error: "Only PDF documents can be used for e-signature." });
|
||||
}
|
||||
|
||||
req.body.bodyshop = bodyshop;
|
||||
|
||||
const fileName = uploadedDocument.originalname?.replace(/\.[^.]+$/, "") || undefined;
|
||||
const result = await createEsignDocumentFromPdf({
|
||||
req,
|
||||
bodyshop,
|
||||
pdfBuffer: uploadedDocument.buffer,
|
||||
esigData,
|
||||
fileName
|
||||
});
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
logger.log(`esig-new-custom-error`, "ERROR", "esig", "api", {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
body: _.omit(req.body, ["bodyshop"]) // bodyshop can be large, so we omit it from the logs
|
||||
});
|
||||
res
|
||||
.status(error.statusCode || 500)
|
||||
.json({ error: "An error occurred while creating the custom e-sign document.", message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
async function RenderTemplate({ req }) {
|
||||
const jsrAuth = jsrAuthString()
|
||||
const jsreportClient = new jsreport(JSR_SERVER, process.env.JSR_USER, process.env.JSR_PASSWORD);
|
||||
const { templateObject, bodyshop } = req.body;
|
||||
let { contextData, useShopSpecificTemplate, shopSpecificFolder, esigData } = await fetchContextData({ templateObject, jsrAuth, req });
|
||||
const jsrAuth = jsrAuthString();
|
||||
const jsreportClient = new jsreport(JSR_SERVER, process.env.JSR_USER, process.env.JSR_PASSWORD);
|
||||
const { templateObject, bodyshop } = req.body;
|
||||
let { contextData, useShopSpecificTemplate, shopSpecificFolder, esigData } = await fetchContextData({
|
||||
templateObject,
|
||||
jsrAuth,
|
||||
req
|
||||
});
|
||||
|
||||
const { ignoreCustomMargins } = { ignoreCustomMargins: false }// Templates[templateObject.name];
|
||||
let reportRequest = {
|
||||
template: {
|
||||
name: useShopSpecificTemplate ? `/${bodyshop.imexshopid}/${templateObject.name}` : `/${templateObject.name}`,
|
||||
const { ignoreCustomMargins } = { ignoreCustomMargins: false }; // Templates[templateObject.name];
|
||||
let reportRequest = {
|
||||
template: {
|
||||
name: useShopSpecificTemplate ? `/${bodyshop.imexshopid}/${templateObject.name}` : `/${templateObject.name}`,
|
||||
|
||||
recipe: "chrome-pdf",
|
||||
...(!ignoreCustomMargins && {
|
||||
chrome: {
|
||||
marginTop:
|
||||
bodyshop.logo_img_path &&
|
||||
bodyshop.logo_img_path.headerMargin &&
|
||||
bodyshop.logo_img_path.headerMargin > 36
|
||||
? bodyshop.logo_img_path.headerMargin
|
||||
: "36px",
|
||||
marginBottom:
|
||||
bodyshop.logo_img_path &&
|
||||
bodyshop.logo_img_path.footerMargin &&
|
||||
bodyshop.logo_img_path.footerMargin > 50
|
||||
? bodyshop.logo_img_path.footerMargin
|
||||
: "50px"
|
||||
}
|
||||
}),
|
||||
},
|
||||
data: {
|
||||
...contextData,
|
||||
...templateObject.variables,
|
||||
...templateObject.context,
|
||||
headerpath: shopSpecificFolder ? `/${bodyshop.imexshopid}/header.html` : `/GENERIC/header.html`,
|
||||
footerpath: shopSpecificFolder ? `/${bodyshop.imexshopid}/footer.html` : `/GENERIC/footer.html`,
|
||||
bodyshop: bodyshop,
|
||||
esignature: true,
|
||||
filters: templateObject?.filters,
|
||||
sorters: templateObject?.sorters,
|
||||
offset: bodyshop.timezone, //dayjs().utcOffset(),
|
||||
defaultSorters: templateObject?.defaultSorters
|
||||
recipe: "chrome-pdf",
|
||||
...(!ignoreCustomMargins && {
|
||||
chrome: {
|
||||
marginTop:
|
||||
bodyshop.logo_img_path && bodyshop.logo_img_path.headerMargin && bodyshop.logo_img_path.headerMargin > 36
|
||||
? bodyshop.logo_img_path.headerMargin
|
||||
: "36px",
|
||||
marginBottom:
|
||||
bodyshop.logo_img_path && bodyshop.logo_img_path.footerMargin && bodyshop.logo_img_path.footerMargin > 50
|
||||
? bodyshop.logo_img_path.footerMargin
|
||||
: "50px"
|
||||
}
|
||||
};
|
||||
const render = await jsreportClient.render(reportRequest);
|
||||
})
|
||||
},
|
||||
data: {
|
||||
...contextData,
|
||||
...templateObject.variables,
|
||||
...templateObject.context,
|
||||
headerpath: shopSpecificFolder ? `/${bodyshop.imexshopid}/header.html` : `/GENERIC/header.html`,
|
||||
footerpath: shopSpecificFolder ? `/${bodyshop.imexshopid}/footer.html` : `/GENERIC/footer.html`,
|
||||
bodyshop: bodyshop,
|
||||
esignature: true,
|
||||
filters: templateObject?.filters,
|
||||
sorters: templateObject?.sorters,
|
||||
offset: bodyshop.timezone, //dayjs().utcOffset(),
|
||||
defaultSorters: templateObject?.defaultSorters
|
||||
}
|
||||
};
|
||||
const render = await jsreportClient.render(reportRequest);
|
||||
|
||||
//Check render object and download. It should be the PDF?
|
||||
const pdfBuffer = await render.body()
|
||||
return { pdf: pdfBuffer, esigData }
|
||||
//Check render object and download. It should be the PDF?
|
||||
const pdfBuffer = await render.body();
|
||||
return { pdf: pdfBuffer, esigData };
|
||||
}
|
||||
|
||||
const fetchContextData = async ({ templateObject, jsrAuth, req, }) => {
|
||||
const { bodyshop } = req.body
|
||||
const fetchContextData = async ({ templateObject, jsrAuth, req }) => {
|
||||
const { bodyshop } = req.body;
|
||||
|
||||
const folders = await axios.get(`${JSR_SERVER}/odata/folders`, {
|
||||
headers: { Authorization: jsrAuth }
|
||||
});
|
||||
const shopSpecificFolder = folders.data.value.find((f) => f.name === bodyshop.imexshopid);
|
||||
|
||||
const folders = await axios.get(`${JSR_SERVER}/odata/folders`, {
|
||||
headers: { Authorization: jsrAuth }
|
||||
const jsReportQueries = await axios.get(`${JSR_SERVER}/odata/assets?$filter=name eq '${templateObject.name}.query'`, {
|
||||
headers: { Authorization: jsrAuth }
|
||||
});
|
||||
const jsReportEsig = await axios.get(`${JSR_SERVER}/odata/assets?$filter=name eq '${templateObject.name}.esig'`, {
|
||||
headers: { Authorization: jsrAuth }
|
||||
});
|
||||
|
||||
let templateQueryToExecute;
|
||||
let esigData;
|
||||
let useShopSpecificTemplate = false;
|
||||
// let shopSpecificTemplate;
|
||||
|
||||
if (shopSpecificFolder) {
|
||||
let shopSpecificTemplate = jsReportQueries.data.value.find(
|
||||
(f) => f?.folder?.shortid === shopSpecificFolder.shortid
|
||||
);
|
||||
if (shopSpecificTemplate) {
|
||||
useShopSpecificTemplate = true;
|
||||
templateQueryToExecute = atob(shopSpecificTemplate.content);
|
||||
}
|
||||
let shopSpecificEsig = jsReportEsig.data.value.find((f) => f?.folder?.shortid === shopSpecificFolder.shortid);
|
||||
if (shopSpecificEsig) {
|
||||
esigData = atob(shopSpecificEsig.content);
|
||||
}
|
||||
}
|
||||
|
||||
if (!templateQueryToExecute) {
|
||||
const generalTemplate = jsReportQueries.data.value.find((f) => !f.folder);
|
||||
useShopSpecificTemplate = false;
|
||||
templateQueryToExecute = atob(generalTemplate.content);
|
||||
}
|
||||
if (!esigData) {
|
||||
const generalTemplate = jsReportEsig.data.value.find((f) => !f.folder);
|
||||
useShopSpecificTemplate = false;
|
||||
if (generalTemplate && generalTemplate.content) {
|
||||
esigData = atob(generalTemplate?.content);
|
||||
}
|
||||
}
|
||||
|
||||
const client = req.userGraphQLClient;
|
||||
|
||||
// In the print center, we will never have sorters or filters.
|
||||
// We have no template filters or sorters, so we can just execute the query and return the data
|
||||
// if (!hasFilters && !hasSorters && !hasDefaultSorters) {
|
||||
let contextData = {};
|
||||
if (templateQueryToExecute) {
|
||||
const data = await client.request(templateQueryToExecute, templateObject.variables);
|
||||
contextData = data;
|
||||
}
|
||||
|
||||
let parsedEsigData;
|
||||
try {
|
||||
parsedEsigData = esigData ? JSON.parse(esigData) : null;
|
||||
} catch (error) {
|
||||
logger.log(`esig-data-parse-error`, "ERROR", "esig", "api", {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
esigData,
|
||||
body: req.body
|
||||
});
|
||||
const shopSpecificFolder = folders.data.value.find((f) => f.name === bodyshop.imexshopid);
|
||||
parsedEsigData = {};
|
||||
}
|
||||
|
||||
const jsReportQueries = await axios.get(
|
||||
`${JSR_SERVER}/odata/assets?$filter=name eq '${templateObject.name}.query'`,
|
||||
{ headers: { Authorization: jsrAuth } }
|
||||
);
|
||||
const jsReportEsig = await axios.get(
|
||||
`${JSR_SERVER}/odata/assets?$filter=name eq '${templateObject.name}.esig'`,
|
||||
{ headers: { Authorization: jsrAuth } }
|
||||
);
|
||||
return {
|
||||
contextData,
|
||||
useShopSpecificTemplate,
|
||||
shopSpecificFolder,
|
||||
esigData: parsedEsigData
|
||||
};
|
||||
// }
|
||||
|
||||
let templateQueryToExecute;
|
||||
let esigData;
|
||||
let useShopSpecificTemplate = false;
|
||||
// let shopSpecificTemplate;
|
||||
|
||||
if (shopSpecificFolder) {
|
||||
let shopSpecificTemplate = jsReportQueries.data.value.find(
|
||||
(f) => f?.folder?.shortid === shopSpecificFolder.shortid
|
||||
);
|
||||
if (shopSpecificTemplate) {
|
||||
useShopSpecificTemplate = true;
|
||||
templateQueryToExecute = atob(shopSpecificTemplate.content);
|
||||
}
|
||||
let shopSpecificEsig = jsReportEsig.data.value.find(
|
||||
(f) => f?.folder?.shortid === shopSpecificFolder.shortid
|
||||
);
|
||||
if (shopSpecificEsig) {
|
||||
esigData = (atob(shopSpecificEsig.content));
|
||||
}
|
||||
}
|
||||
|
||||
if (!templateQueryToExecute) {
|
||||
const generalTemplate = jsReportQueries.data.value.find((f) => !f.folder);
|
||||
useShopSpecificTemplate = false;
|
||||
templateQueryToExecute = atob(generalTemplate.content);
|
||||
}
|
||||
if (!esigData) {
|
||||
const generalTemplate = jsReportEsig.data.value.find((f) => !f.folder);
|
||||
useShopSpecificTemplate = false;
|
||||
if (generalTemplate && generalTemplate.content) {
|
||||
esigData = atob(generalTemplate?.content);
|
||||
}
|
||||
}
|
||||
|
||||
const client = req.userGraphQLClient;
|
||||
|
||||
|
||||
// In the print center, we will never have sorters or filters.
|
||||
// We have no template filters or sorters, so we can just execute the query and return the data
|
||||
// if (!hasFilters && !hasSorters && !hasDefaultSorters) {
|
||||
let contextData = {};
|
||||
if (templateQueryToExecute) {
|
||||
const data = await client.request(
|
||||
templateQueryToExecute,
|
||||
templateObject.variables,
|
||||
);
|
||||
contextData = data;
|
||||
}
|
||||
|
||||
let parsedEsigData
|
||||
try {
|
||||
parsedEsigData = esigData ? JSON.parse(esigData) : null;
|
||||
} catch (error) {
|
||||
logger.log(`esig-data-parse-error`, "ERROR", "esig", "api", {
|
||||
message: error.message, stack: error.stack,
|
||||
esigData,
|
||||
body: req.body
|
||||
});
|
||||
parsedEsigData = {}
|
||||
}
|
||||
|
||||
return {
|
||||
contextData,
|
||||
useShopSpecificTemplate,
|
||||
shopSpecificFolder,
|
||||
esigData: parsedEsigData
|
||||
};
|
||||
// }
|
||||
|
||||
// return await generateTemplate(templateQueryToExecute, templateObject, useShopSpecificTemplate, shopSpecificFolder);
|
||||
// return await generateTemplate(templateQueryToExecute, templateObject, useShopSpecificTemplate, shopSpecificFolder);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
newEsignDocument,
|
||||
newCustomEsignDocument,
|
||||
distributeDocument,
|
||||
redistributeDocument,
|
||||
deleteDocument,
|
||||
viewDocument,
|
||||
getDocumensoClient
|
||||
}
|
||||
newEsignDocument,
|
||||
newCustomEsignDocument,
|
||||
distributeDocument,
|
||||
redistributeDocument,
|
||||
deleteDocument,
|
||||
viewDocument,
|
||||
getDocumensoClient
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user