in nodes/YouTrack/YoutrackTrigger.node.ts [147:256]
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
const req = this.getRequestObject();
const selectedEvents = this.getNodeParameter('events', []) as string[];
// Validate authentication if webhook credential is configured
try {
const webhookCredentials = await this.getCredentials('youTrackWebhookAuthApi');
if (webhookCredentials) {
const authMethod = webhookCredentials.authMethod as string;
const expectedToken = webhookCredentials.authToken as string;
let receivedToken: string | undefined;
if (authMethod === 'headerAuth') {
// Header-based authentication
const headerName = webhookCredentials.headerName as string;
receivedToken = req.headers[headerName.toLowerCase()] as string;
} else if (authMethod === 'queryAuth') {
// Query parameter authentication
const queryParamName = webhookCredentials.queryParameterName as string;
receivedToken = req.query?.[queryParamName] as string;
}
// Validate the token
if (!receivedToken || receivedToken !== expectedToken) {
return {
webhookResponse: {
message: 'Unauthorized: Invalid or missing authentication token',
statusCode: 401,
},
};
}
}
} catch (error) {
return {
webhookResponse: {
message: `Error validating authentication: ${error}`,
statusCode: 401,
},
};
}
// Parse the webhook payload safely
let body: IDataObject = {};
try {
body = req.body as IDataObject || {};
} catch (error) {
return {
webhookResponse: {
error: `Invalid payload format. ${error}`,
statusCode: 400,
},
};
}
// Determine the event type from the payload
let detectedEvent = 'unknown';
if (body && typeof body === 'object') {
// Check for the explicit 'event' field from YouTrack app workflows
if (body.event && typeof body.event === 'string') {
const eventValue = body.event as string;
// Validate against known events - automatically includes all events from YOUTRACK_EVENTS
if (EVENT_VALUES.includes(eventValue)) {
detectedEvent = eventValue;
}
}
}
// Check if this event matches our configured event filter
const acceptsAllEvents = selectedEvents && selectedEvents.length > 0 && selectedEvents.includes('*');
// If specific events are selected, verify the detected event is in the list
if (!acceptsAllEvents) {
// Ensure selectedEvents is an array and not empty
if (!selectedEvents || selectedEvents.length === 0) {
return {
webhookResponse: {
message: 'No events selected',
statusCode: 200,
},
};
}
// Check if detected event is in the selected events
if (!selectedEvents.includes(detectedEvent)) {
return {
webhookResponse: {
message: `Event type '${detectedEvent}' does not match filter. Selected events: ${selectedEvents.join(', ')}`,
statusCode: 200,
},
};
}
}
return {
workflowData: [
[
{
json: body,
},
],
],
webhookResponse: {
message: 'Webhook received successfully',
statusCode: 200,
},
};
}