feat: Add token to sendAndWait operations links to walidate in webhook (#17566)

This commit is contained in:
Michael Kret
2025-08-06 17:28:50 +03:00
committed by GitHub
parent 6495e08c79
commit 9cb5754f33
30 changed files with 277 additions and 92 deletions

View File

@@ -34,8 +34,7 @@ import { escapeHtml } from '../utilities';
export type SendAndWaitConfig = {
title: string;
message: string;
url: string;
options: Array<{ label: string; value: string; style: string }>;
options: Array<{ label: string; url: string; style: string }>;
appendAttribution?: boolean;
};
@@ -480,8 +479,6 @@ export function getSendAndWaitConfig(context: IExecuteFunctions): SendAndWaitCon
.replace(/\\n/g, '\n')
.replace(/<br>/g, '\n');
const subject = escapeHtml(context.getNodeParameter('subject', 0, '') as string);
const resumeUrl = context.evaluateExpression('{{ $execution?.resumeUrl }}', 0) as string;
const nodeId = context.evaluateExpression('{{ $nodeId }}', 0) as string;
const approvalOptions = context.getNodeParameter('approvalOptions.values', 0, {}) as {
approvalType?: 'single' | 'double';
approveLabel?: string;
@@ -495,18 +492,20 @@ export function getSendAndWaitConfig(context: IExecuteFunctions): SendAndWaitCon
const config: SendAndWaitConfig = {
title: subject,
message,
url: `${resumeUrl}/${nodeId}`,
options: [],
appendAttribution: options?.appendAttribution as boolean,
};
const responseType = context.getNodeParameter('responseType', 0, 'approval') as string;
context.setSignatureValidationRequired();
const approvedSignedResumeUrl = context.getSignedResumeUrl({ approved: 'true' });
if (responseType === 'freeText' || responseType === 'customForm') {
const label = context.getNodeParameter('options.messageButtonLabel', 0, 'Respond') as string;
config.options.push({
label,
value: 'true',
url: approvedSignedResumeUrl,
style: 'primary',
});
} else if (approvalOptions.approvalType === 'double') {
@@ -514,15 +513,16 @@ export function getSendAndWaitConfig(context: IExecuteFunctions): SendAndWaitCon
const buttonApprovalStyle = approvalOptions.buttonApprovalStyle || 'primary';
const disapproveLabel = escapeHtml(approvalOptions.disapproveLabel || 'Disapprove');
const buttonDisapprovalStyle = approvalOptions.buttonDisapprovalStyle || 'secondary';
const disapprovedSignedResumeUrl = context.getSignedResumeUrl({ approved: 'false' });
config.options.push({
label: disapproveLabel,
value: 'false',
url: disapprovedSignedResumeUrl,
style: buttonDisapprovalStyle,
});
config.options.push({
label: approveLabel,
value: 'true',
url: approvedSignedResumeUrl,
style: buttonApprovalStyle,
});
} else {
@@ -530,7 +530,7 @@ export function getSendAndWaitConfig(context: IExecuteFunctions): SendAndWaitCon
const style = approvalOptions.buttonApprovalStyle || 'primary';
config.options.push({
label,
value: 'true',
url: approvedSignedResumeUrl,
style,
});
}
@@ -538,12 +538,12 @@ export function getSendAndWaitConfig(context: IExecuteFunctions): SendAndWaitCon
return config;
}
export function createButton(url: string, label: string, approved: string, style: string) {
export function createButton(url: string, label: string, style: string) {
let buttonStyle = BUTTON_STYLE_PRIMARY;
if (style === 'secondary') {
buttonStyle = BUTTON_STYLE_SECONDARY;
}
return `<a href="${url}?approved=${approved}" target="_blank" style="${buttonStyle}">${label}</a>`;
return `<a href="${url}" target="_blank" style="${buttonStyle}">${label}</a>`;
}
export function createEmail(context: IExecuteFunctions) {
@@ -560,7 +560,7 @@ export function createEmail(context: IExecuteFunctions) {
const buttons: string[] = [];
for (const option of config.options) {
buttons.push(createButton(config.url, option.label, option.value, option.style));
buttons.push(createButton(option.url, option.label, option.style));
}
let emailBody: string;
if (config.appendAttribution !== false) {