@shopify/shopify-api
Version:
Shopify API Library for Node - accelerate development with support for authentication, graphql proxy, webhooks
132 lines (128 loc) • 5.47 kB
JavaScript
;
var index$1 = require('../logger/index.js');
var hmacValidator = require('../utils/hmac-validator.js');
var types = require('../utils/types.js');
var index = require('../../runtime/http/index.js');
var types$1 = require('./types.js');
var registry = require('./registry.js');
var headers = require('../../runtime/http/headers.js');
function detectWebhookType(headers$1) {
const eventsHmac = headers.getHeader(headers$1, types$1.WEBHOOK_HEADER_NAMES[types$1.WebhookType.Events].hmac);
if (eventsHmac) {
return types$1.WebhookType.Events;
}
const webhooksHmac = headers.getHeader(headers$1, types$1.WEBHOOK_HEADER_NAMES[types$1.WebhookType.Webhooks].hmac);
if (webhooksHmac) {
return types$1.WebhookType.Webhooks;
}
return types$1.WebhookType.Webhooks;
}
function validateFactory(config) {
return async function validate({ rawBody, ...adapterArgs }) {
const request = await index.abstractConvertRequest(adapterArgs);
const webhookType = detectWebhookType(request.headers);
const validHmacResult = await hmacValidator.validateHmacFromRequestFactory(config)({
type: types.HmacValidationType.Webhook,
rawBody,
webhookType,
...adapterArgs,
});
if (!validHmacResult.valid) {
if (validHmacResult.reason === types.ValidationErrorReason.InvalidHmac) {
const log = index$1.logger(config);
await log.debug("Webhook HMAC validation failed. Please note that events manually triggered from a store's Notifications settings will fail this validation. To test this, please use the CLI or trigger the actual event in a development store.");
}
return validHmacResult;
}
return checkWebhookHeaders(request.headers, webhookType);
};
}
function getRequiredHeader(headers$1, headerName, missingHeaders) {
const value = headers.getHeader(headers$1, headerName);
if (!value) {
missingHeaders.push(headerName);
}
return value;
}
function checkWebhookHeaders(headers, webhookType) {
if (webhookType === types$1.WebhookType.Webhooks) {
return checkWebhooksHeaders(headers);
}
return checkEventsHeaders(headers);
}
function checkWebhooksHeaders(headers$1) {
const headerNames = types$1.WEBHOOK_HEADER_NAMES[types$1.WebhookType.Webhooks];
const missingHeaders = [];
const hmac = getRequiredHeader(headers$1, headerNames.hmac, missingHeaders);
const topic = getRequiredHeader(headers$1, headerNames.topic, missingHeaders);
const domain = getRequiredHeader(headers$1, headerNames.domain, missingHeaders);
const apiVersion = getRequiredHeader(headers$1, headerNames.apiVersion, missingHeaders);
const webhookId = getRequiredHeader(headers$1, headerNames.webhookId, missingHeaders);
if (missingHeaders.length) {
return {
valid: false,
reason: types$1.WebhookValidationErrorReason.MissingHeaders,
missingHeaders,
};
}
const fields = {
webhookType: types$1.WebhookType.Webhooks,
hmac: hmac,
topic: registry.topicForStorage(topic),
domain: domain,
apiVersion: apiVersion,
webhookId: webhookId,
};
const subTopic = headers.getHeader(headers$1, headerNames.subTopic);
if (subTopic)
fields.subTopic = subTopic;
const name = headers.getHeader(headers$1, headerNames.name);
if (name)
fields.name = name;
const triggeredAt = headers.getHeader(headers$1, headerNames.triggeredAt);
if (triggeredAt)
fields.triggeredAt = triggeredAt;
const eventId = headers.getHeader(headers$1, headerNames.eventId);
if (eventId)
fields.eventId = eventId;
return { valid: true, ...fields };
}
function checkEventsHeaders(headers$1) {
const headerNames = types$1.WEBHOOK_HEADER_NAMES[types$1.WebhookType.Events];
const missingHeaders = [];
const hmac = getRequiredHeader(headers$1, headerNames.hmac, missingHeaders);
const topic = getRequiredHeader(headers$1, headerNames.topic, missingHeaders);
const domain = getRequiredHeader(headers$1, headerNames.domain, missingHeaders);
const apiVersion = getRequiredHeader(headers$1, headerNames.apiVersion, missingHeaders);
const eventId = getRequiredHeader(headers$1, headerNames.eventId, missingHeaders);
if (missingHeaders.length) {
return {
valid: false,
reason: types$1.WebhookValidationErrorReason.MissingHeaders,
missingHeaders,
};
}
const fields = {
webhookType: types$1.WebhookType.Events,
hmac: hmac,
topic: registry.topicForStorage(topic),
domain: domain,
apiVersion: apiVersion,
eventId: eventId,
};
const handle = headers.getHeader(headers$1, headerNames.handle);
if (handle)
fields.handle = handle;
const action = headers.getHeader(headers$1, headerNames.action);
if (action)
fields.action = action;
const resourceId = headers.getHeader(headers$1, headerNames.resourceId);
if (resourceId)
fields.resourceId = resourceId;
const triggeredAt = headers.getHeader(headers$1, headerNames.triggeredAt);
if (triggeredAt)
fields.triggeredAt = triggeredAt;
return { valid: true, ...fields };
}
exports.validateFactory = validateFactory;
//# sourceMappingURL=validate.js.map