@webiny/webhooks 6.4.0-beta.2 → 6.4.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/WebhookRoutes.js +21 -3
- package/admin/WebhookRoutes.js.map +1 -1
- package/admin/Webhooks.js +11 -0
- package/admin/Webhooks.js.map +1 -1
- package/admin/features/getWebhookSettings/GetWebhookSettingsGateway.d.ts +12 -0
- package/admin/features/getWebhookSettings/GetWebhookSettingsGateway.js +40 -0
- package/admin/features/getWebhookSettings/GetWebhookSettingsGateway.js.map +1 -0
- package/admin/features/getWebhookSettings/GetWebhookSettingsUseCase.d.ts +11 -0
- package/admin/features/getWebhookSettings/GetWebhookSettingsUseCase.js +18 -0
- package/admin/features/getWebhookSettings/GetWebhookSettingsUseCase.js.map +1 -0
- package/admin/features/getWebhookSettings/abstractions.d.ts +15 -0
- package/admin/features/getWebhookSettings/abstractions.js +6 -0
- package/admin/features/getWebhookSettings/abstractions.js.map +1 -0
- package/admin/features/getWebhookSettings/feature.d.ts +3 -0
- package/admin/features/getWebhookSettings/feature.js +19 -0
- package/admin/features/getWebhookSettings/feature.js.map +1 -0
- package/admin/features/getWebhookSettings/index.d.ts +2 -0
- package/admin/features/getWebhookSettings/index.js +2 -0
- package/admin/features/updateWebhookSettings/UpdateWebhookSettingsGateway.d.ts +12 -0
- package/admin/features/updateWebhookSettings/UpdateWebhookSettingsGateway.js +43 -0
- package/admin/features/updateWebhookSettings/UpdateWebhookSettingsGateway.js.map +1 -0
- package/admin/features/updateWebhookSettings/UpdateWebhookSettingsUseCase.d.ts +11 -0
- package/admin/features/updateWebhookSettings/UpdateWebhookSettingsUseCase.js +18 -0
- package/admin/features/updateWebhookSettings/UpdateWebhookSettingsUseCase.js.map +1 -0
- package/admin/features/updateWebhookSettings/abstractions.d.ts +18 -0
- package/admin/features/updateWebhookSettings/abstractions.js +6 -0
- package/admin/features/updateWebhookSettings/abstractions.js.map +1 -0
- package/admin/features/updateWebhookSettings/feature.d.ts +3 -0
- package/admin/features/updateWebhookSettings/feature.js +19 -0
- package/admin/features/updateWebhookSettings/feature.js.map +1 -0
- package/admin/features/updateWebhookSettings/index.d.ts +2 -0
- package/admin/features/updateWebhookSettings/index.js +2 -0
- package/admin/presentation/WebhookForm/WebhookFormPresenter.d.ts +6 -2
- package/admin/presentation/WebhookForm/WebhookFormPresenter.js +87 -14
- package/admin/presentation/WebhookForm/WebhookFormPresenter.js.map +1 -1
- package/admin/presentation/WebhookForm/abstractions.d.ts +0 -4
- package/admin/presentation/WebhookForm/abstractions.js.map +1 -1
- package/admin/presentation/WebhookForm/components/WebhookFormView.js +5 -11
- package/admin/presentation/WebhookForm/components/WebhookFormView.js.map +1 -1
- package/admin/presentation/WebhookList/components/WebhookListView.js +28 -21
- package/admin/presentation/WebhookList/components/WebhookListView.js.map +1 -1
- package/admin/presentation/WebhookSettings/WebhookSettingsPresenter.d.ts +21 -0
- package/admin/presentation/WebhookSettings/WebhookSettingsPresenter.js +83 -0
- package/admin/presentation/WebhookSettings/WebhookSettingsPresenter.js.map +1 -0
- package/admin/presentation/WebhookSettings/abstractions.d.ts +16 -0
- package/admin/presentation/WebhookSettings/abstractions.js +5 -0
- package/admin/presentation/WebhookSettings/abstractions.js.map +1 -0
- package/admin/presentation/WebhookSettings/components/WebhookSettingsView.d.ts +2 -0
- package/admin/presentation/WebhookSettings/components/WebhookSettingsView.js +56 -0
- package/admin/presentation/WebhookSettings/components/WebhookSettingsView.js.map +1 -0
- package/admin/presentation/WebhookSettings/feature.d.ts +3 -0
- package/admin/presentation/WebhookSettings/feature.js +17 -0
- package/admin/presentation/WebhookSettings/feature.js.map +1 -0
- package/admin/presentation/WebhookSettings/index.d.ts +2 -0
- package/admin/presentation/WebhookSettings/index.js +2 -0
- package/admin/routes.d.ts +1 -0
- package/admin/routes.js +4 -0
- package/admin/routes.js.map +1 -1
- package/admin/shared/types.d.ts +3 -0
- package/api/WebhooksFeature.js +10 -0
- package/api/WebhooksFeature.js.map +1 -1
- package/api/domain/WebhookSettings.d.ts +3 -0
- package/api/domain/WebhookSettings.js +0 -0
- package/api/domain/constants.d.ts +1 -0
- package/api/domain/constants.js +2 -1
- package/api/domain/constants.js.map +1 -1
- package/api/domain/errors.d.ts +7 -2
- package/api/domain/errors.js +16 -3
- package/api/domain/errors.js.map +1 -1
- package/api/features/CreateWebhook/CreateWebhookUseCase.d.ts +3 -3
- package/api/features/CreateWebhook/CreateWebhookUseCase.js +10 -19
- package/api/features/CreateWebhook/CreateWebhookUseCase.js.map +1 -1
- package/api/features/CreateWebhook/abstractions.d.ts +1 -1
- package/api/features/CreateWebhook/abstractions.js.map +1 -1
- package/api/features/CreateWebhook/schema.d.ts +10 -0
- package/api/features/CreateWebhook/schema.js +16 -0
- package/api/features/CreateWebhook/schema.js.map +1 -0
- package/api/features/DeleteWebhook/DeleteWebhookUseCase.d.ts +3 -3
- package/api/features/DeleteWebhook/DeleteWebhookUseCase.js +8 -3
- package/api/features/DeleteWebhook/DeleteWebhookUseCase.js.map +1 -1
- package/api/features/DeleteWebhook/abstractions.d.ts +2 -2
- package/api/features/DeleteWebhook/abstractions.js.map +1 -1
- package/api/features/DeleteWebhook/schema.d.ts +4 -0
- package/api/features/DeleteWebhook/schema.js +7 -0
- package/api/features/DeleteWebhook/schema.js.map +1 -0
- package/api/features/GetWebhook/GetWebhookUseCase.d.ts +2 -2
- package/api/features/GetWebhook/GetWebhookUseCase.js +7 -2
- package/api/features/GetWebhook/GetWebhookUseCase.js.map +1 -1
- package/api/features/GetWebhook/abstractions.d.ts +2 -2
- package/api/features/GetWebhook/abstractions.js.map +1 -1
- package/api/features/GetWebhook/schema.d.ts +4 -0
- package/api/features/GetWebhook/schema.js +7 -0
- package/api/features/GetWebhook/schema.js.map +1 -0
- package/api/features/GetWebhookDelivery/GetWebhookDeliveryUseCase.d.ts +2 -2
- package/api/features/GetWebhookDelivery/GetWebhookDeliveryUseCase.js +7 -2
- package/api/features/GetWebhookDelivery/GetWebhookDeliveryUseCase.js.map +1 -1
- package/api/features/GetWebhookDelivery/abstractions.d.ts +2 -2
- package/api/features/GetWebhookDelivery/abstractions.js.map +1 -1
- package/api/features/GetWebhookDelivery/schema.d.ts +4 -0
- package/api/features/GetWebhookDelivery/schema.js +7 -0
- package/api/features/GetWebhookDelivery/schema.js.map +1 -0
- package/api/features/GetWebhookSettings/GetWebhookSettingsRepository.d.ts +19 -0
- package/api/features/GetWebhookSettings/GetWebhookSettingsRepository.js +55 -0
- package/api/features/GetWebhookSettings/GetWebhookSettingsRepository.js.map +1 -0
- package/api/features/GetWebhookSettings/abstractions.d.ts +13 -0
- package/api/features/GetWebhookSettings/abstractions.js +5 -0
- package/api/features/GetWebhookSettings/abstractions.js.map +1 -0
- package/api/features/GetWebhookSettings/feature.d.ts +4 -0
- package/api/features/GetWebhookSettings/feature.js +11 -0
- package/api/features/GetWebhookSettings/feature.js.map +1 -0
- package/api/features/ListWebhookDeliveries/ListWebhookDeliveriesUseCase.d.ts +2 -2
- package/api/features/ListWebhookDeliveries/ListWebhookDeliveriesUseCase.js +4 -1
- package/api/features/ListWebhookDeliveries/ListWebhookDeliveriesUseCase.js.map +1 -1
- package/api/features/ListWebhookDeliveries/abstractions.d.ts +2 -2
- package/api/features/ListWebhookDeliveries/abstractions.js.map +1 -1
- package/api/features/ListWebhookDeliveries/schema.d.ts +7 -0
- package/api/features/ListWebhookDeliveries/schema.js +10 -0
- package/api/features/ListWebhookDeliveries/schema.js.map +1 -0
- package/api/features/ListWebhooks/ListWebhooksUseCase.d.ts +2 -2
- package/api/features/ListWebhooks/ListWebhooksUseCase.js +4 -1
- package/api/features/ListWebhooks/ListWebhooksUseCase.js.map +1 -1
- package/api/features/ListWebhooks/abstractions.d.ts +2 -2
- package/api/features/ListWebhooks/abstractions.js.map +1 -1
- package/api/features/ListWebhooks/schema.d.ts +7 -0
- package/api/features/ListWebhooks/schema.js +10 -0
- package/api/features/ListWebhooks/schema.js.map +1 -0
- package/api/features/ResendWebhookDelivery/ResendWebhookDeliveryUseCase.d.ts +5 -5
- package/api/features/ResendWebhookDelivery/ResendWebhookDeliveryUseCase.js +7 -2
- package/api/features/ResendWebhookDelivery/ResendWebhookDeliveryUseCase.js.map +1 -1
- package/api/features/ResendWebhookDelivery/abstractions.d.ts +2 -2
- package/api/features/ResendWebhookDelivery/abstractions.js.map +1 -1
- package/api/features/ResendWebhookDelivery/schema.d.ts +4 -0
- package/api/features/ResendWebhookDelivery/schema.js +7 -0
- package/api/features/ResendWebhookDelivery/schema.js.map +1 -0
- package/api/features/SendWebhookTask/SendWebhookTask.d.ts +6 -2
- package/api/features/SendWebhookTask/SendWebhookTask.js +45 -33
- package/api/features/SendWebhookTask/SendWebhookTask.js.map +1 -1
- package/api/features/SendWebhookTask/types.d.ts +1 -0
- package/api/features/TriggerWebhook/TriggerWebhookUseCase.js +8 -2
- package/api/features/TriggerWebhook/TriggerWebhookUseCase.js.map +1 -1
- package/api/features/TriggerWebhook/abstractions.d.ts +2 -2
- package/api/features/TriggerWebhook/abstractions.js.map +1 -1
- package/api/features/TriggerWebhook/schema.d.ts +5 -0
- package/api/features/TriggerWebhook/schema.js +8 -0
- package/api/features/TriggerWebhook/schema.js.map +1 -0
- package/api/features/UpdateWebhook/UpdateWebhookUseCase.d.ts +4 -4
- package/api/features/UpdateWebhook/UpdateWebhookUseCase.js +9 -33
- package/api/features/UpdateWebhook/UpdateWebhookUseCase.js.map +1 -1
- package/api/features/UpdateWebhook/abstractions.d.ts +0 -1
- package/api/features/UpdateWebhook/abstractions.js.map +1 -1
- package/api/features/UpdateWebhook/schema.d.ts +9 -0
- package/api/features/UpdateWebhook/schema.js +15 -0
- package/api/features/UpdateWebhook/schema.js.map +1 -0
- package/api/features/UpdateWebhookSettings/UpdateWebhookSettingsRepository.d.ts +21 -0
- package/api/features/UpdateWebhookSettings/UpdateWebhookSettingsRepository.js +60 -0
- package/api/features/UpdateWebhookSettings/UpdateWebhookSettingsRepository.js.map +1 -0
- package/api/features/UpdateWebhookSettings/UpdateWebhookSettingsUseCase.d.ts +14 -0
- package/api/features/UpdateWebhookSettings/UpdateWebhookSettingsUseCase.js +27 -0
- package/api/features/UpdateWebhookSettings/UpdateWebhookSettingsUseCase.js.map +1 -0
- package/api/features/UpdateWebhookSettings/abstractions.d.ts +26 -0
- package/api/features/UpdateWebhookSettings/abstractions.js +6 -0
- package/api/features/UpdateWebhookSettings/abstractions.js.map +1 -0
- package/api/features/UpdateWebhookSettings/feature.d.ts +4 -0
- package/api/features/UpdateWebhookSettings/feature.js +13 -0
- package/api/features/UpdateWebhookSettings/feature.js.map +1 -0
- package/api/features/UpdateWebhookSettings/schema.d.ts +4 -0
- package/api/features/UpdateWebhookSettings/schema.js +7 -0
- package/api/features/UpdateWebhookSettings/schema.js.map +1 -0
- package/api/features/WebhookDeliver/WebhookDeliver.d.ts +13 -0
- package/api/features/WebhookDeliver/WebhookDeliver.js +79 -0
- package/api/features/WebhookDeliver/WebhookDeliver.js.map +1 -0
- package/api/features/WebhookDeliver/abstractions.d.ts +24 -0
- package/api/features/WebhookDeliver/abstractions.js +5 -0
- package/api/features/WebhookDeliver/abstractions.js.map +1 -0
- package/api/features/WebhookDeliver/feature.d.ts +4 -0
- package/api/features/WebhookDeliver/feature.js +11 -0
- package/api/features/WebhookDeliver/feature.js.map +1 -0
- package/api/features/WebhookDeliver/index.d.ts +2 -0
- package/api/features/WebhookDeliver/index.js +2 -0
- package/api/features/WebhookSignPayload/WebhookSignPayload.d.ts +1 -0
- package/api/features/WebhookSignPayload/WebhookSignPayload.js +7 -1
- package/api/features/WebhookSignPayload/WebhookSignPayload.js.map +1 -1
- package/api/graphql/WebhookCrudSchema.js +1 -2
- package/api/graphql/WebhookCrudSchema.js.map +1 -1
- package/api/graphql/WebhookEventSchema.js +1 -0
- package/api/graphql/WebhookEventSchema.js.map +1 -1
- package/api/graphql/WebhookSettingsSchema.d.ts +8 -0
- package/api/graphql/WebhookSettingsSchema.js +60 -0
- package/api/graphql/WebhookSettingsSchema.js.map +1 -0
- package/api/models/WebhookDeliveryModel.js +4 -4
- package/api/models/WebhookDeliveryModel.js.map +1 -1
- package/api/models/WebhookModel.js +1 -1
- package/api/models/WebhookModel.js.map +1 -1
- package/api/models/WebhookSettingsModel.d.ts +8 -0
- package/api/models/WebhookSettingsModel.js +27 -0
- package/api/models/WebhookSettingsModel.js.map +1 -0
- package/api/utils/isValidEndpointUrl.d.ts +1 -0
- package/api/utils/isValidEndpointUrl.js +13 -0
- package/api/utils/isValidEndpointUrl.js.map +1 -0
- package/exports/api/webhooks.d.ts +0 -1
- package/exports/api/webhooks.js +0 -1
- package/package.json +22 -20
- package/admin/SecurityPermission.d.ts +0 -2
- package/admin/SecurityPermission.js +0 -15
- package/admin/SecurityPermission.js.map +0 -1
- package/admin/presentation/WebhookForm/components/EventsSelector.d.ts +0 -12
- package/admin/presentation/WebhookForm/components/EventsSelector.js +0 -44
- package/admin/presentation/WebhookForm/components/EventsSelector.js.map +0 -1
|
@@ -6,11 +6,11 @@ import { CreateWebhookDeliveryRepository } from "../../../api/features/CreateWeb
|
|
|
6
6
|
import { WebhookPermissions } from "../../../api/features/WebhookPermissions/abstractions.js";
|
|
7
7
|
import { TaskService } from "@webiny/api-core/exports/api/tasks.js";
|
|
8
8
|
declare class ResendWebhookDeliveryUseCaseImpl implements UseCaseAbstraction.Interface {
|
|
9
|
-
private permissions;
|
|
10
|
-
private getDeliveryRepository;
|
|
11
|
-
private getWebhookRepository;
|
|
12
|
-
private createDeliveryRepository;
|
|
13
|
-
private taskService;
|
|
9
|
+
private readonly permissions;
|
|
10
|
+
private readonly getDeliveryRepository;
|
|
11
|
+
private readonly getWebhookRepository;
|
|
12
|
+
private readonly createDeliveryRepository;
|
|
13
|
+
private readonly taskService;
|
|
14
14
|
constructor(permissions: WebhookPermissions.Interface, getDeliveryRepository: GetWebhookDeliveryRepository.Interface, getWebhookRepository: GetWebhookRepository.Interface, createDeliveryRepository: CreateWebhookDeliveryRepository.Interface, taskService: TaskService.Interface);
|
|
15
15
|
execute(deliveryId: string): Promise<Result<boolean, UseCaseAbstraction.Error>>;
|
|
16
16
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { ResendWebhookDeliveryUseCase } from "./abstractions.js";
|
|
3
|
+
import { ResendWebhookDeliveryInputSchema } from "./schema.js";
|
|
3
4
|
import { GetWebhookDeliveryRepository } from "../GetWebhookDelivery/abstractions.js";
|
|
4
5
|
import { GetWebhookRepository } from "../GetWebhook/abstractions.js";
|
|
5
6
|
import { CreateWebhookDeliveryRepository } from "../CreateWebhookDelivery/abstractions.js";
|
|
6
7
|
import { WebhookPermissions } from "../WebhookPermissions/abstractions.js";
|
|
7
|
-
import { WebhookNotAuthorizedError } from "../../domain/errors.js";
|
|
8
|
+
import { WebhookNotAuthorizedError, WebhookValidationError } from "../../domain/errors.js";
|
|
8
9
|
import { TaskService } from "@webiny/api-core/exports/api/tasks.js";
|
|
9
10
|
import { SEND_WEBHOOK_TASK, WEBHOOK_DELIVERY_RETENTION_DAYS } from "../../domain/constants.js";
|
|
10
11
|
class ResendWebhookDeliveryUseCaseImpl {
|
|
@@ -17,7 +18,11 @@ class ResendWebhookDeliveryUseCaseImpl {
|
|
|
17
18
|
}
|
|
18
19
|
async execute(deliveryId) {
|
|
19
20
|
if (!await this.permissions.canEdit("webhook")) return Result.fail(new WebhookNotAuthorizedError());
|
|
20
|
-
const
|
|
21
|
+
const parsed = ResendWebhookDeliveryInputSchema.safeParse({
|
|
22
|
+
deliveryId
|
|
23
|
+
});
|
|
24
|
+
if (!parsed.success) return Result.fail(new WebhookValidationError(parsed.error));
|
|
25
|
+
const deliveryResult = await this.getDeliveryRepository.execute(parsed.data.deliveryId);
|
|
21
26
|
if (deliveryResult.isFail()) return Result.fail(deliveryResult.error);
|
|
22
27
|
const delivery = deliveryResult.value;
|
|
23
28
|
const webhookResult = await this.getWebhookRepository.execute(delivery.webhookId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/features/ResendWebhookDelivery/ResendWebhookDeliveryUseCase.js","sources":["../../../../src/api/features/ResendWebhookDelivery/ResendWebhookDeliveryUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { ResendWebhookDeliveryUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { GetWebhookDeliveryRepository } from \"~/api/features/GetWebhookDelivery/abstractions.js\";\nimport { GetWebhookRepository } from \"~/api/features/GetWebhook/abstractions.js\";\nimport { CreateWebhookDeliveryRepository } from \"~/api/features/CreateWebhookDelivery/abstractions.js\";\nimport { WebhookPermissions } from \"~/api/features/WebhookPermissions/abstractions.js\";\nimport { WebhookNotAuthorizedError } from \"~/api/domain/errors.js\";\nimport { TaskService } from \"@webiny/api-core/exports/api/tasks.js\";\nimport { SEND_WEBHOOK_TASK, WEBHOOK_DELIVERY_RETENTION_DAYS } from \"~/api/domain/constants.js\";\nimport type { IWebhookPayload } from \"~/api/features/SendWebhookTask/types.js\";\n\nclass ResendWebhookDeliveryUseCaseImpl implements UseCaseAbstraction.Interface {\n constructor(\n private permissions: WebhookPermissions.Interface,\n private getDeliveryRepository: GetWebhookDeliveryRepository.Interface,\n private getWebhookRepository: GetWebhookRepository.Interface,\n private createDeliveryRepository: CreateWebhookDeliveryRepository.Interface,\n private taskService: TaskService.Interface\n ) {}\n\n async execute(deliveryId: string): Promise<Result<boolean, UseCaseAbstraction.Error>> {\n if (!(await this.permissions.canEdit(\"webhook\"))) {\n return Result.fail(new WebhookNotAuthorizedError());\n }\n\n const deliveryResult = await this.getDeliveryRepository.execute(deliveryId);\n if (deliveryResult.isFail()) {\n return Result.fail(deliveryResult.error);\n }\n\n const delivery = deliveryResult.value;\n\n const webhookResult = await this.getWebhookRepository.execute(delivery.webhookId);\n if (webhookResult.isFail()) {\n return Result.fail(webhookResult.error);\n }\n\n const originalPayload = delivery.payload as IWebhookPayload | null;\n const data = originalPayload?.data ?? {};\n\n const expiresAt = new Date(\n Date.now() + WEBHOOK_DELIVERY_RETENTION_DAYS * 24 * 60 * 60 * 1000\n ).toISOString();\n\n const newDeliveryResult = await this.createDeliveryRepository.execute({\n webhookId: delivery.webhookId,\n eventType: delivery.eventType,\n status: \"pending\",\n payload: data as Record<string, unknown>,\n expiresAt\n });\n\n if (newDeliveryResult.isFail()) {\n return Result.fail(newDeliveryResult.error);\n }\n\n await this.taskService.trigger({\n definition: SEND_WEBHOOK_TASK,\n name: `Resend webhook: ${delivery.eventType}`,\n input: {\n webhookId: delivery.webhookId,\n eventName: delivery.eventType,\n deliveryId: newDeliveryResult.value.id\n }\n });\n\n return Result.ok(true);\n }\n}\n\nexport const ResendWebhookDeliveryUseCase = UseCaseAbstraction.createImplementation({\n implementation: ResendWebhookDeliveryUseCaseImpl,\n dependencies: [\n WebhookPermissions,\n GetWebhookDeliveryRepository,\n GetWebhookRepository,\n CreateWebhookDeliveryRepository,\n TaskService\n ]\n});\n"],"names":["ResendWebhookDeliveryUseCaseImpl","permissions","getDeliveryRepository","getWebhookRepository","createDeliveryRepository","taskService","deliveryId","Result","WebhookNotAuthorizedError","deliveryResult","delivery","webhookResult","originalPayload","data","expiresAt","Date","WEBHOOK_DELIVERY_RETENTION_DAYS","newDeliveryResult","SEND_WEBHOOK_TASK","ResendWebhookDeliveryUseCase","UseCaseAbstraction","WebhookPermissions","GetWebhookDeliveryRepository","GetWebhookRepository","CreateWebhookDeliveryRepository","TaskService"],"mappings":"
|
|
1
|
+
{"version":3,"file":"api/features/ResendWebhookDelivery/ResendWebhookDeliveryUseCase.js","sources":["../../../../src/api/features/ResendWebhookDelivery/ResendWebhookDeliveryUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { ResendWebhookDeliveryUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { ResendWebhookDeliveryInputSchema } from \"./schema.js\";\nimport { GetWebhookDeliveryRepository } from \"~/api/features/GetWebhookDelivery/abstractions.js\";\nimport { GetWebhookRepository } from \"~/api/features/GetWebhook/abstractions.js\";\nimport { CreateWebhookDeliveryRepository } from \"~/api/features/CreateWebhookDelivery/abstractions.js\";\nimport { WebhookPermissions } from \"~/api/features/WebhookPermissions/abstractions.js\";\nimport { WebhookNotAuthorizedError, WebhookValidationError } from \"~/api/domain/errors.js\";\nimport { TaskService } from \"@webiny/api-core/exports/api/tasks.js\";\nimport { SEND_WEBHOOK_TASK, WEBHOOK_DELIVERY_RETENTION_DAYS } from \"~/api/domain/constants.js\";\nimport type { IWebhookPayload } from \"~/api/features/SendWebhookTask/types.js\";\n\nclass ResendWebhookDeliveryUseCaseImpl implements UseCaseAbstraction.Interface {\n constructor(\n private readonly permissions: WebhookPermissions.Interface,\n private readonly getDeliveryRepository: GetWebhookDeliveryRepository.Interface,\n private readonly getWebhookRepository: GetWebhookRepository.Interface,\n private readonly createDeliveryRepository: CreateWebhookDeliveryRepository.Interface,\n private readonly taskService: TaskService.Interface\n ) {}\n\n async execute(deliveryId: string): Promise<Result<boolean, UseCaseAbstraction.Error>> {\n if (!(await this.permissions.canEdit(\"webhook\"))) {\n return Result.fail(new WebhookNotAuthorizedError());\n }\n\n const parsed = ResendWebhookDeliveryInputSchema.safeParse({ deliveryId });\n if (!parsed.success) {\n return Result.fail(new WebhookValidationError(parsed.error));\n }\n\n const deliveryResult = await this.getDeliveryRepository.execute(parsed.data.deliveryId);\n if (deliveryResult.isFail()) {\n return Result.fail(deliveryResult.error);\n }\n\n const delivery = deliveryResult.value;\n\n const webhookResult = await this.getWebhookRepository.execute(delivery.webhookId);\n if (webhookResult.isFail()) {\n return Result.fail(webhookResult.error);\n }\n\n const originalPayload = delivery.payload as IWebhookPayload | null;\n const data = originalPayload?.data ?? {};\n\n const expiresAt = new Date(\n Date.now() + WEBHOOK_DELIVERY_RETENTION_DAYS * 24 * 60 * 60 * 1000\n ).toISOString();\n\n const newDeliveryResult = await this.createDeliveryRepository.execute({\n webhookId: delivery.webhookId,\n eventType: delivery.eventType,\n status: \"pending\",\n payload: data as Record<string, unknown>,\n expiresAt\n });\n\n if (newDeliveryResult.isFail()) {\n return Result.fail(newDeliveryResult.error);\n }\n\n await this.taskService.trigger({\n definition: SEND_WEBHOOK_TASK,\n name: `Resend webhook: ${delivery.eventType}`,\n input: {\n webhookId: delivery.webhookId,\n eventName: delivery.eventType,\n deliveryId: newDeliveryResult.value.id\n }\n });\n\n return Result.ok(true);\n }\n}\n\nexport const ResendWebhookDeliveryUseCase = UseCaseAbstraction.createImplementation({\n implementation: ResendWebhookDeliveryUseCaseImpl,\n dependencies: [\n WebhookPermissions,\n GetWebhookDeliveryRepository,\n GetWebhookRepository,\n CreateWebhookDeliveryRepository,\n TaskService\n ]\n});\n"],"names":["ResendWebhookDeliveryUseCaseImpl","permissions","getDeliveryRepository","getWebhookRepository","createDeliveryRepository","taskService","deliveryId","Result","WebhookNotAuthorizedError","parsed","ResendWebhookDeliveryInputSchema","WebhookValidationError","deliveryResult","delivery","webhookResult","originalPayload","data","expiresAt","Date","WEBHOOK_DELIVERY_RETENTION_DAYS","newDeliveryResult","SEND_WEBHOOK_TASK","ResendWebhookDeliveryUseCase","UseCaseAbstraction","WebhookPermissions","GetWebhookDeliveryRepository","GetWebhookRepository","CreateWebhookDeliveryRepository","TaskService"],"mappings":";;;;;;;;;;AAYA,MAAMA;IACF,YACqBC,WAAyC,EACzCC,qBAA6D,EAC7DC,oBAAoD,EACpDC,wBAAmE,EACnEC,WAAkC,CACrD;aALmBJ,WAAW,GAAXA;aACAC,qBAAqB,GAArBA;aACAC,oBAAoB,GAApBA;aACAC,wBAAwB,GAAxBA;aACAC,WAAW,GAAXA;IAClB;IAEH,MAAM,QAAQC,UAAkB,EAAsD;QAClF,IAAI,CAAE,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,YACjC,OAAOC,OAAO,IAAI,CAAC,IAAIC;QAG3B,MAAMC,SAASC,iCAAiC,SAAS,CAAC;YAAEJ;QAAW;QACvE,IAAI,CAACG,OAAO,OAAO,EACf,OAAOF,OAAO,IAAI,CAAC,IAAII,uBAAuBF,OAAO,KAAK;QAG9D,MAAMG,iBAAiB,MAAM,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAACH,OAAO,IAAI,CAAC,UAAU;QACtF,IAAIG,eAAe,MAAM,IACrB,OAAOL,OAAO,IAAI,CAACK,eAAe,KAAK;QAG3C,MAAMC,WAAWD,eAAe,KAAK;QAErC,MAAME,gBAAgB,MAAM,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAACD,SAAS,SAAS;QAChF,IAAIC,cAAc,MAAM,IACpB,OAAOP,OAAO,IAAI,CAACO,cAAc,KAAK;QAG1C,MAAMC,kBAAkBF,SAAS,OAAO;QACxC,MAAMG,OAAOD,iBAAiB,QAAQ,CAAC;QAEvC,MAAME,YAAY,IAAIC,KAClBA,KAAK,GAAG,KAAKC,AAAkC,KAAlCA,kCAAAA,SACf,WAAW;QAEb,MAAMC,oBAAoB,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC;YAClE,WAAWP,SAAS,SAAS;YAC7B,WAAWA,SAAS,SAAS;YAC7B,QAAQ;YACR,SAASG;YACTC;QACJ;QAEA,IAAIG,kBAAkB,MAAM,IACxB,OAAOb,OAAO,IAAI,CAACa,kBAAkB,KAAK;QAG9C,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;YAC3B,YAAYC;YACZ,MAAM,CAAC,gBAAgB,EAAER,SAAS,SAAS,EAAE;YAC7C,OAAO;gBACH,WAAWA,SAAS,SAAS;gBAC7B,WAAWA,SAAS,SAAS;gBAC7B,YAAYO,kBAAkB,KAAK,CAAC,EAAE;YAC1C;QACJ;QAEA,OAAOb,OAAO,EAAE,CAAC;IACrB;AACJ;AAEO,MAAMe,4DAA+BC,6BAAAA,oBAAuC,CAAC;IAChF,gBAAgBvB;IAChB,cAAc;QACVwB;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Result } from "@webiny/feature/api";
|
|
2
|
-
import type { WebhookDeliveryNotFoundError, WebhookNotFoundError, WebhookPersistenceError, WebhookModelNotFoundError, WebhookNotAuthorizedError } from "../../../api/domain/errors.js";
|
|
3
|
-
type IError = WebhookDeliveryNotFoundError | WebhookNotFoundError | WebhookPersistenceError | WebhookModelNotFoundError | WebhookNotAuthorizedError;
|
|
2
|
+
import type { WebhookDeliveryNotFoundError, WebhookNotFoundError, WebhookPersistenceError, WebhookModelNotFoundError, WebhookNotAuthorizedError, WebhookValidationError } from "../../../api/domain/errors.js";
|
|
3
|
+
type IError = WebhookDeliveryNotFoundError | WebhookNotFoundError | WebhookPersistenceError | WebhookModelNotFoundError | WebhookNotAuthorizedError | WebhookValidationError;
|
|
4
4
|
export interface IResendWebhookDeliveryUseCase {
|
|
5
5
|
execute(deliveryId: string): Promise<Result<boolean, IError>>;
|
|
6
6
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/features/ResendWebhookDelivery/abstractions.js","sources":["../../../../src/api/features/ResendWebhookDelivery/abstractions.ts"],"sourcesContent":["import { createAbstraction, type Result } from \"@webiny/feature/api\";\nimport type {\n WebhookDeliveryNotFoundError,\n WebhookNotFoundError,\n WebhookPersistenceError,\n WebhookModelNotFoundError,\n WebhookNotAuthorizedError\n} from \"~/api/domain/errors.js\";\n\ntype IError =\n | WebhookDeliveryNotFoundError\n | WebhookNotFoundError\n | WebhookPersistenceError\n | WebhookModelNotFoundError\n | WebhookNotAuthorizedError;\n\nexport interface IResendWebhookDeliveryUseCase {\n execute(deliveryId: string): Promise<Result<boolean, IError>>;\n}\n\nexport const ResendWebhookDeliveryUseCase = createAbstraction<IResendWebhookDeliveryUseCase>(\n \"Webhooks/ResendWebhookDeliveryUseCase\"\n);\n\nexport namespace ResendWebhookDeliveryUseCase {\n export type Interface = IResendWebhookDeliveryUseCase;\n export type Error = IError;\n}\n"],"names":["ResendWebhookDeliveryUseCase","createAbstraction"],"mappings":";
|
|
1
|
+
{"version":3,"file":"api/features/ResendWebhookDelivery/abstractions.js","sources":["../../../../src/api/features/ResendWebhookDelivery/abstractions.ts"],"sourcesContent":["import { createAbstraction, type Result } from \"@webiny/feature/api\";\nimport type {\n WebhookDeliveryNotFoundError,\n WebhookNotFoundError,\n WebhookPersistenceError,\n WebhookModelNotFoundError,\n WebhookNotAuthorizedError,\n WebhookValidationError\n} from \"~/api/domain/errors.js\";\n\ntype IError =\n | WebhookDeliveryNotFoundError\n | WebhookNotFoundError\n | WebhookPersistenceError\n | WebhookModelNotFoundError\n | WebhookNotAuthorizedError\n | WebhookValidationError;\n\nexport interface IResendWebhookDeliveryUseCase {\n execute(deliveryId: string): Promise<Result<boolean, IError>>;\n}\n\nexport const ResendWebhookDeliveryUseCase = createAbstraction<IResendWebhookDeliveryUseCase>(\n \"Webhooks/ResendWebhookDeliveryUseCase\"\n);\n\nexport namespace ResendWebhookDeliveryUseCase {\n export type Interface = IResendWebhookDeliveryUseCase;\n export type Error = IError;\n}\n"],"names":["ResendWebhookDeliveryUseCase","createAbstraction"],"mappings":";AAsBO,MAAMA,+BAA+BC,kBACxC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/ResendWebhookDelivery/schema.js","sources":["../../../../src/api/features/ResendWebhookDelivery/schema.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const ResendWebhookDeliveryInputSchema = z.object({\n deliveryId: z.string().min(1, \"Delivery ID is required.\")\n});\n"],"names":["ResendWebhookDeliveryInputSchema","z"],"mappings":";AAEO,MAAMA,mCAAmCC,EAAE,MAAM,CAAC;IACrD,YAAYA,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG;AAClC"}
|
|
@@ -5,6 +5,8 @@ import { WebhookSignPayload } from "@webiny/api-core/features/webhooks/index.js"
|
|
|
5
5
|
import { GetWebhookRepository } from "../../../api/features/GetWebhook/abstractions.js";
|
|
6
6
|
import { GetWebhookDeliveryRepository } from "../../../api/features/GetWebhookDelivery/abstractions.js";
|
|
7
7
|
import { UpdateWebhookDeliveryRepository } from "../../../api/features/UpdateWebhookDelivery/abstractions.js";
|
|
8
|
+
import { GetWebhookSettingsRepository } from "../../../api/features/GetWebhookSettings/abstractions.js";
|
|
9
|
+
import { WebhookDeliver } from "../../../api/features/WebhookDeliver/abstractions.js";
|
|
8
10
|
import type { ISendWebhookTaskInput, ISendWebhookTaskOutput } from "./types.js";
|
|
9
11
|
type IRunParams = TaskDefinition.RunParams<ISendWebhookTaskInput, ISendWebhookTaskOutput>;
|
|
10
12
|
declare class SendWebhookTaskDefinition implements TaskDefinition.Interface<ISendWebhookTaskInput, ISendWebhookTaskOutput> {
|
|
@@ -13,14 +15,16 @@ declare class SendWebhookTaskDefinition implements TaskDefinition.Interface<ISen
|
|
|
13
15
|
private readonly updateDeliveryRepository;
|
|
14
16
|
private readonly signPayload;
|
|
15
17
|
private readonly tenantContext;
|
|
18
|
+
private readonly getWebhookSettingsRepository;
|
|
19
|
+
private readonly deliver;
|
|
16
20
|
readonly id = "sendWebhook";
|
|
17
21
|
readonly title = "Send Webhook";
|
|
18
22
|
readonly maxIterations = 1;
|
|
19
23
|
readonly isPrivate = true;
|
|
20
24
|
readonly databaseLogs = false;
|
|
21
25
|
readonly description = "POST a signed event payload to a webhook endpoint and log the delivery.";
|
|
22
|
-
readonly selfCleanup
|
|
23
|
-
constructor(getWebhookRepository: GetWebhookRepository.Interface, getWebhookDeliveryRepository: GetWebhookDeliveryRepository.Interface, updateDeliveryRepository: UpdateWebhookDeliveryRepository.Interface, signPayload: WebhookSignPayload.Interface, tenantContext: TenantContext.Interface);
|
|
26
|
+
readonly selfCleanup = "always";
|
|
27
|
+
constructor(getWebhookRepository: GetWebhookRepository.Interface, getWebhookDeliveryRepository: GetWebhookDeliveryRepository.Interface, updateDeliveryRepository: UpdateWebhookDeliveryRepository.Interface, signPayload: WebhookSignPayload.Interface, tenantContext: TenantContext.Interface, getWebhookSettingsRepository: GetWebhookSettingsRepository.Interface, deliver: WebhookDeliver.Interface);
|
|
24
28
|
run(params: IRunParams): Promise<import("@webiny/api-core/features/task/TaskDefinition/abstractions.js").ITaskResultError | TaskDefinition.ResultDone<ISendWebhookTaskOutput>>;
|
|
25
29
|
}
|
|
26
30
|
export declare const SendWebhookTask: typeof SendWebhookTaskDefinition & {
|
|
@@ -5,30 +5,31 @@ import { WebhookSignPayload } from "@webiny/api-core/features/webhooks/index.js"
|
|
|
5
5
|
import { GetWebhookRepository } from "../GetWebhook/abstractions.js";
|
|
6
6
|
import { GetWebhookDeliveryRepository } from "../GetWebhookDelivery/abstractions.js";
|
|
7
7
|
import { UpdateWebhookDeliveryRepository } from "../UpdateWebhookDelivery/abstractions.js";
|
|
8
|
+
import { GetWebhookSettingsRepository } from "../GetWebhookSettings/abstractions.js";
|
|
9
|
+
import { WebhookDeliver } from "../WebhookDeliver/abstractions.js";
|
|
8
10
|
import { SEND_WEBHOOK_TASK } from "../../domain/constants.js";
|
|
9
11
|
class SendWebhookTaskDefinition {
|
|
10
|
-
constructor(getWebhookRepository, getWebhookDeliveryRepository, updateDeliveryRepository, signPayload, tenantContext){
|
|
12
|
+
constructor(getWebhookRepository, getWebhookDeliveryRepository, updateDeliveryRepository, signPayload, tenantContext, getWebhookSettingsRepository, deliver){
|
|
11
13
|
this.getWebhookRepository = getWebhookRepository;
|
|
12
14
|
this.getWebhookDeliveryRepository = getWebhookDeliveryRepository;
|
|
13
15
|
this.updateDeliveryRepository = updateDeliveryRepository;
|
|
14
16
|
this.signPayload = signPayload;
|
|
15
17
|
this.tenantContext = tenantContext;
|
|
18
|
+
this.getWebhookSettingsRepository = getWebhookSettingsRepository;
|
|
19
|
+
this.deliver = deliver;
|
|
16
20
|
this.id = SEND_WEBHOOK_TASK;
|
|
17
21
|
this.title = "Send Webhook";
|
|
18
22
|
this.maxIterations = 1;
|
|
19
23
|
this.isPrivate = true;
|
|
20
24
|
this.databaseLogs = false;
|
|
21
25
|
this.description = "POST a signed event payload to a webhook endpoint and log the delivery.";
|
|
22
|
-
this.selfCleanup =
|
|
23
|
-
"onSuccess",
|
|
24
|
-
"onAbort"
|
|
25
|
-
];
|
|
26
|
+
this.selfCleanup = "always";
|
|
26
27
|
}
|
|
27
28
|
async run(params) {
|
|
28
|
-
const { input } = params;
|
|
29
|
-
const taskId =
|
|
29
|
+
const { input, controller } = params;
|
|
30
|
+
const taskId = controller.state.getTask().id;
|
|
30
31
|
const delivery = await this.getWebhookDeliveryRepository.execute(input.deliveryId);
|
|
31
|
-
if (delivery.isFail()) return
|
|
32
|
+
if (delivery.isFail()) return controller.response.error(delivery.error);
|
|
32
33
|
await this.updateDeliveryRepository.execute(input.deliveryId, {
|
|
33
34
|
backgroundTaskId: taskId,
|
|
34
35
|
status: "delivering"
|
|
@@ -38,7 +39,7 @@ class SendWebhookTaskDefinition {
|
|
|
38
39
|
await this.updateDeliveryRepository.execute(input.deliveryId, {
|
|
39
40
|
status: "failed"
|
|
40
41
|
});
|
|
41
|
-
return
|
|
42
|
+
return controller.response.error(webhookResult.error);
|
|
42
43
|
}
|
|
43
44
|
const webhook = webhookResult.value;
|
|
44
45
|
const now = new Date();
|
|
@@ -47,41 +48,50 @@ class SendWebhookTaskDefinition {
|
|
|
47
48
|
event: input.eventName,
|
|
48
49
|
timestamp: now.toISOString(),
|
|
49
50
|
webhookId: input.webhookId,
|
|
51
|
+
deliveryId: input.deliveryId,
|
|
50
52
|
tenant: this.tenantContext.getTenant().id,
|
|
51
53
|
data: delivery.value.payload
|
|
52
54
|
};
|
|
53
55
|
const rawBody = JSON.stringify(payload);
|
|
54
|
-
|
|
56
|
+
let signHeaders;
|
|
57
|
+
const settingsResult = await this.getWebhookSettingsRepository.execute();
|
|
58
|
+
if (settingsResult.isFail()) {
|
|
59
|
+
await this.updateDeliveryRepository.execute(input.deliveryId, {
|
|
60
|
+
status: "failed"
|
|
61
|
+
});
|
|
62
|
+
return controller.response.error(settingsResult.error);
|
|
63
|
+
}
|
|
64
|
+
const signingSecret = webhook.signingSecret || settingsResult.value.signingSecret || "";
|
|
65
|
+
try {
|
|
66
|
+
signHeaders = await this.signPayload.sign(taskId, now, rawBody, signingSecret);
|
|
67
|
+
} catch (ex) {
|
|
68
|
+
await this.updateDeliveryRepository.execute(input.deliveryId, {
|
|
69
|
+
status: "failed"
|
|
70
|
+
});
|
|
71
|
+
return controller.response.error(ex);
|
|
72
|
+
}
|
|
55
73
|
const requestHeaders = {
|
|
56
74
|
"Content-Type": "application/json",
|
|
57
75
|
...signHeaders
|
|
58
76
|
};
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
});
|
|
69
|
-
responseStatus = response.status;
|
|
70
|
-
responseBody = await response.text();
|
|
71
|
-
} catch (error) {
|
|
72
|
-
responseStatus = 0;
|
|
73
|
-
responseBody = error.message;
|
|
74
|
-
}
|
|
75
|
-
const responseTime = Date.now() - startTime;
|
|
77
|
+
const result = await this.deliver.execute({
|
|
78
|
+
url: webhook.endpointUrl,
|
|
79
|
+
headers: requestHeaders,
|
|
80
|
+
body: rawBody,
|
|
81
|
+
timeout: 600000,
|
|
82
|
+
maxRetries: 3,
|
|
83
|
+
initialDelay: 1000,
|
|
84
|
+
maxDelay: 30000
|
|
85
|
+
});
|
|
76
86
|
await this.updateDeliveryRepository.execute(input.deliveryId, {
|
|
77
87
|
payload,
|
|
78
88
|
requestHeaders,
|
|
79
|
-
responseTime,
|
|
80
|
-
responseStatus,
|
|
81
|
-
responseBody,
|
|
82
|
-
status:
|
|
89
|
+
responseTime: result.responseTime,
|
|
90
|
+
responseStatus: result.status,
|
|
91
|
+
responseBody: result.body,
|
|
92
|
+
status: result.status > 0 ? "delivered" : "failed"
|
|
83
93
|
});
|
|
84
|
-
return
|
|
94
|
+
return controller.response.done();
|
|
85
95
|
}
|
|
86
96
|
}
|
|
87
97
|
const SendWebhookTask = TaskDefinition.createImplementation({
|
|
@@ -91,7 +101,9 @@ const SendWebhookTask = TaskDefinition.createImplementation({
|
|
|
91
101
|
GetWebhookDeliveryRepository,
|
|
92
102
|
UpdateWebhookDeliveryRepository,
|
|
93
103
|
WebhookSignPayload,
|
|
94
|
-
TenantContext
|
|
104
|
+
TenantContext,
|
|
105
|
+
GetWebhookSettingsRepository,
|
|
106
|
+
WebhookDeliver
|
|
95
107
|
]
|
|
96
108
|
});
|
|
97
109
|
export { SendWebhookTask };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/features/SendWebhookTask/SendWebhookTask.js","sources":["../../../../src/api/features/SendWebhookTask/SendWebhookTask.ts"],"sourcesContent":["import \"@webiny/tasks/types.js\";\nimport { TaskDefinition } from \"@webiny/api-core/exports/api/tasks.js\";\nimport { TenantContext } from \"@webiny/api-core/exports/api/tenancy.js\";\nimport { WebhookSignPayload } from \"@webiny/api-core/features/webhooks/index.js\";\nimport { GetWebhookRepository } from \"~/api/features/GetWebhook/abstractions.js\";\nimport { GetWebhookDeliveryRepository } from \"~/api/features/GetWebhookDelivery/abstractions.js\";\nimport { UpdateWebhookDeliveryRepository } from \"~/api/features/UpdateWebhookDelivery/abstractions.js\";\nimport { SEND_WEBHOOK_TASK } from \"~/api/domain/constants.js\";\nimport type { ISendWebhookTaskInput, ISendWebhookTaskOutput, IWebhookPayload } from \"./types.js\";\n\ntype IRunParams = TaskDefinition.RunParams<ISendWebhookTaskInput, ISendWebhookTaskOutput>;\n\nclass SendWebhookTaskDefinition implements TaskDefinition.Interface<\n ISendWebhookTaskInput,\n ISendWebhookTaskOutput\n> {\n public readonly id = SEND_WEBHOOK_TASK;\n public readonly title = \"Send Webhook\";\n public readonly maxIterations = 1;\n public readonly isPrivate = true;\n public readonly databaseLogs = false;\n public readonly description =\n \"POST a signed event payload to a webhook endpoint and log the delivery.\";\n public readonly selfCleanup =
|
|
1
|
+
{"version":3,"file":"api/features/SendWebhookTask/SendWebhookTask.js","sources":["../../../../src/api/features/SendWebhookTask/SendWebhookTask.ts"],"sourcesContent":["import \"@webiny/tasks/types.js\";\nimport { TaskDefinition } from \"@webiny/api-core/exports/api/tasks.js\";\nimport { TenantContext } from \"@webiny/api-core/exports/api/tenancy.js\";\nimport { WebhookSignPayload } from \"@webiny/api-core/features/webhooks/index.js\";\nimport { GetWebhookRepository } from \"~/api/features/GetWebhook/abstractions.js\";\nimport { GetWebhookDeliveryRepository } from \"~/api/features/GetWebhookDelivery/abstractions.js\";\nimport { UpdateWebhookDeliveryRepository } from \"~/api/features/UpdateWebhookDelivery/abstractions.js\";\nimport { GetWebhookSettingsRepository } from \"~/api/features/GetWebhookSettings/abstractions.js\";\nimport { WebhookDeliver } from \"~/api/features/WebhookDeliver/abstractions.js\";\nimport { SEND_WEBHOOK_TASK } from \"~/api/domain/constants.js\";\nimport type { ISendWebhookTaskInput, ISendWebhookTaskOutput, IWebhookPayload } from \"./types.js\";\nimport type { IWebhookSignPayloadHeaders } from \"@webiny/api-core/features/webhooks/WebhookSignPayload/abstractions.js\";\n\ntype IRunParams = TaskDefinition.RunParams<ISendWebhookTaskInput, ISendWebhookTaskOutput>;\n\nclass SendWebhookTaskDefinition implements TaskDefinition.Interface<\n ISendWebhookTaskInput,\n ISendWebhookTaskOutput\n> {\n public readonly id = SEND_WEBHOOK_TASK;\n public readonly title = \"Send Webhook\";\n public readonly maxIterations = 1;\n public readonly isPrivate = true;\n public readonly databaseLogs = false;\n public readonly description =\n \"POST a signed event payload to a webhook endpoint and log the delivery.\";\n public readonly selfCleanup = \"always\";\n\n public constructor(\n private readonly getWebhookRepository: GetWebhookRepository.Interface,\n private readonly getWebhookDeliveryRepository: GetWebhookDeliveryRepository.Interface,\n private readonly updateDeliveryRepository: UpdateWebhookDeliveryRepository.Interface,\n private readonly signPayload: WebhookSignPayload.Interface,\n private readonly tenantContext: TenantContext.Interface,\n private readonly getWebhookSettingsRepository: GetWebhookSettingsRepository.Interface,\n private readonly deliver: WebhookDeliver.Interface\n ) {}\n\n public async run(params: IRunParams) {\n const { input, controller } = params;\n const taskId = controller.state.getTask().id;\n\n const delivery = await this.getWebhookDeliveryRepository.execute(input.deliveryId);\n if (delivery.isFail()) {\n return controller.response.error(delivery.error);\n }\n\n await this.updateDeliveryRepository.execute(input.deliveryId, {\n backgroundTaskId: taskId,\n status: \"delivering\"\n });\n\n const webhookResult = await this.getWebhookRepository.execute(input.webhookId);\n if (webhookResult.isFail()) {\n await this.updateDeliveryRepository.execute(input.deliveryId, { status: \"failed\" });\n return controller.response.error(webhookResult.error);\n }\n const webhook = webhookResult.value;\n\n const now = new Date();\n const payload: IWebhookPayload = {\n id: taskId,\n event: input.eventName,\n timestamp: now.toISOString(),\n webhookId: input.webhookId,\n deliveryId: input.deliveryId,\n tenant: this.tenantContext.getTenant().id,\n data: delivery.value.payload\n };\n const rawBody = JSON.stringify(payload);\n let signHeaders: IWebhookSignPayloadHeaders;\n\n const settingsResult = await this.getWebhookSettingsRepository.execute();\n if (settingsResult.isFail()) {\n await this.updateDeliveryRepository.execute(input.deliveryId, { status: \"failed\" });\n return controller.response.error(settingsResult.error);\n }\n const signingSecret = webhook.signingSecret || settingsResult.value.signingSecret || \"\";\n\n try {\n signHeaders = await this.signPayload.sign(taskId, now, rawBody, signingSecret);\n } catch (ex) {\n await this.updateDeliveryRepository.execute(input.deliveryId, { status: \"failed\" });\n return controller.response.error(ex);\n }\n\n const requestHeaders: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...signHeaders\n };\n\n const result = await this.deliver.execute({\n url: webhook.endpointUrl,\n headers: requestHeaders,\n body: rawBody,\n timeout: 600_000,\n maxRetries: 3,\n initialDelay: 1000,\n maxDelay: 30_000\n });\n\n await this.updateDeliveryRepository.execute(input.deliveryId, {\n payload,\n requestHeaders,\n responseTime: result.responseTime,\n responseStatus: result.status,\n responseBody: result.body,\n status: result.status > 0 ? \"delivered\" : \"failed\"\n });\n\n return controller.response.done();\n }\n}\n\nexport const SendWebhookTask = TaskDefinition.createImplementation({\n implementation: SendWebhookTaskDefinition,\n dependencies: [\n GetWebhookRepository,\n GetWebhookDeliveryRepository,\n UpdateWebhookDeliveryRepository,\n WebhookSignPayload,\n TenantContext,\n GetWebhookSettingsRepository,\n WebhookDeliver\n ]\n});\n"],"names":["SendWebhookTaskDefinition","getWebhookRepository","getWebhookDeliveryRepository","updateDeliveryRepository","signPayload","tenantContext","getWebhookSettingsRepository","deliver","SEND_WEBHOOK_TASK","params","input","controller","taskId","delivery","webhookResult","webhook","now","Date","payload","rawBody","JSON","signHeaders","settingsResult","signingSecret","ex","requestHeaders","result","SendWebhookTask","TaskDefinition","GetWebhookRepository","GetWebhookDeliveryRepository","UpdateWebhookDeliveryRepository","WebhookSignPayload","TenantContext","GetWebhookSettingsRepository","WebhookDeliver"],"mappings":";;;;;;;;;;AAeA,MAAMA;IAaF,YACqBC,oBAAoD,EACpDC,4BAAoE,EACpEC,wBAAmE,EACnEC,WAAyC,EACzCC,aAAsC,EACtCC,4BAAoE,EACpEC,OAAiC,CACpD;aAPmBN,oBAAoB,GAApBA;aACAC,4BAA4B,GAA5BA;aACAC,wBAAwB,GAAxBA;aACAC,WAAW,GAAXA;aACAC,aAAa,GAAbA;aACAC,4BAA4B,GAA5BA;aACAC,OAAO,GAAPA;aAhBL,EAAE,GAAGC;aACL,KAAK,GAAG;aACR,aAAa,GAAG;aAChB,SAAS,GAAG;aACZ,YAAY,GAAG;aACf,WAAW,GACvB;aACY,WAAW,GAAG;IAU3B;IAEH,MAAa,IAAIC,MAAkB,EAAE;QACjC,MAAM,EAAEC,KAAK,EAAEC,UAAU,EAAE,GAAGF;QAC9B,MAAMG,SAASD,WAAW,KAAK,CAAC,OAAO,GAAG,EAAE;QAE5C,MAAME,WAAW,MAAM,IAAI,CAAC,4BAA4B,CAAC,OAAO,CAACH,MAAM,UAAU;QACjF,IAAIG,SAAS,MAAM,IACf,OAAOF,WAAW,QAAQ,CAAC,KAAK,CAACE,SAAS,KAAK;QAGnD,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAACH,MAAM,UAAU,EAAE;YAC1D,kBAAkBE;YAClB,QAAQ;QACZ;QAEA,MAAME,gBAAgB,MAAM,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAACJ,MAAM,SAAS;QAC7E,IAAII,cAAc,MAAM,IAAI;YACxB,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAACJ,MAAM,UAAU,EAAE;gBAAE,QAAQ;YAAS;YACjF,OAAOC,WAAW,QAAQ,CAAC,KAAK,CAACG,cAAc,KAAK;QACxD;QACA,MAAMC,UAAUD,cAAc,KAAK;QAEnC,MAAME,MAAM,IAAIC;QAChB,MAAMC,UAA2B;YAC7B,IAAIN;YACJ,OAAOF,MAAM,SAAS;YACtB,WAAWM,IAAI,WAAW;YAC1B,WAAWN,MAAM,SAAS;YAC1B,YAAYA,MAAM,UAAU;YAC5B,QAAQ,IAAI,CAAC,aAAa,CAAC,SAAS,GAAG,EAAE;YACzC,MAAMG,SAAS,KAAK,CAAC,OAAO;QAChC;QACA,MAAMM,UAAUC,KAAK,SAAS,CAACF;QAC/B,IAAIG;QAEJ,MAAMC,iBAAiB,MAAM,IAAI,CAAC,4BAA4B,CAAC,OAAO;QACtE,IAAIA,eAAe,MAAM,IAAI;YACzB,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAACZ,MAAM,UAAU,EAAE;gBAAE,QAAQ;YAAS;YACjF,OAAOC,WAAW,QAAQ,CAAC,KAAK,CAACW,eAAe,KAAK;QACzD;QACA,MAAMC,gBAAgBR,QAAQ,aAAa,IAAIO,eAAe,KAAK,CAAC,aAAa,IAAI;QAErF,IAAI;YACAD,cAAc,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAACT,QAAQI,KAAKG,SAASI;QACpE,EAAE,OAAOC,IAAI;YACT,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAACd,MAAM,UAAU,EAAE;gBAAE,QAAQ;YAAS;YACjF,OAAOC,WAAW,QAAQ,CAAC,KAAK,CAACa;QACrC;QAEA,MAAMC,iBAAyC;YAC3C,gBAAgB;YAChB,GAAGJ,WAAW;QAClB;QAEA,MAAMK,SAAS,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YACtC,KAAKX,QAAQ,WAAW;YACxB,SAASU;YACT,MAAMN;YACN,SAAS;YACT,YAAY;YACZ,cAAc;YACd,UAAU;QACd;QAEA,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAACT,MAAM,UAAU,EAAE;YAC1DQ;YACAO;YACA,cAAcC,OAAO,YAAY;YACjC,gBAAgBA,OAAO,MAAM;YAC7B,cAAcA,OAAO,IAAI;YACzB,QAAQA,OAAO,MAAM,GAAG,IAAI,cAAc;QAC9C;QAEA,OAAOf,WAAW,QAAQ,CAAC,IAAI;IACnC;AACJ;AAEO,MAAMgB,kBAAkBC,eAAe,oBAAoB,CAAC;IAC/D,gBAAgB5B;IAChB,cAAc;QACV6B;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { TaskService } from "@webiny/api-core/exports/api/tasks.js";
|
|
3
3
|
import { TriggerWebhookUseCase } from "./abstractions.js";
|
|
4
|
+
import { TriggerWebhookInputSchema } from "./schema.js";
|
|
4
5
|
import { GetWebhookRepository } from "../GetWebhook/abstractions.js";
|
|
5
6
|
import { CreateWebhookDeliveryRepository } from "../CreateWebhookDelivery/abstractions.js";
|
|
6
7
|
import { WebhookPermissions } from "../WebhookPermissions/abstractions.js";
|
|
7
|
-
import { WebhookNotAuthorizedError } from "../../domain/errors.js";
|
|
8
|
+
import { WebhookNotAuthorizedError, WebhookValidationError } from "../../domain/errors.js";
|
|
8
9
|
import { SEND_WEBHOOK_TASK, WEBHOOK_DELIVERY_RETENTION_DAYS } from "../../domain/constants.js";
|
|
9
10
|
class TriggerWebhookUseCaseImpl {
|
|
10
11
|
constructor(permissions, getWebhookRepository, createDeliveryRepository, taskService){
|
|
@@ -15,7 +16,12 @@ class TriggerWebhookUseCaseImpl {
|
|
|
15
16
|
}
|
|
16
17
|
async execute(webhookId, payload) {
|
|
17
18
|
if (!await this.permissions.canEdit("webhook")) return Result.fail(new WebhookNotAuthorizedError());
|
|
18
|
-
const
|
|
19
|
+
const parsed = TriggerWebhookInputSchema.safeParse({
|
|
20
|
+
webhookId,
|
|
21
|
+
payload
|
|
22
|
+
});
|
|
23
|
+
if (!parsed.success) return Result.fail(new WebhookValidationError(parsed.error));
|
|
24
|
+
const webhookResult = await this.getWebhookRepository.execute(parsed.data.webhookId);
|
|
19
25
|
if (webhookResult.isFail()) return Result.fail(webhookResult.error);
|
|
20
26
|
const webhook = webhookResult.value;
|
|
21
27
|
const expiresAt = new Date(Date.now() + 24 * WEBHOOK_DELIVERY_RETENTION_DAYS * 3600000).toISOString();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/features/TriggerWebhook/TriggerWebhookUseCase.js","sources":["../../../../src/api/features/TriggerWebhook/TriggerWebhookUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { TaskService } from \"@webiny/api-core/exports/api/tasks.js\";\nimport { TriggerWebhookUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { GetWebhookRepository } from \"~/api/features/GetWebhook/abstractions.js\";\nimport { CreateWebhookDeliveryRepository } from \"~/api/features/CreateWebhookDelivery/abstractions.js\";\nimport { WebhookPermissions } from \"~/api/features/WebhookPermissions/abstractions.js\";\nimport { WebhookNotAuthorizedError } from \"~/api/domain/errors.js\";\nimport { SEND_WEBHOOK_TASK, WEBHOOK_DELIVERY_RETENTION_DAYS } from \"~/api/domain/constants.js\";\nimport type { ISendWebhookTaskInput } from \"~/api/features/SendWebhookTask/types.js\";\nimport type { WebhookDelivery } from \"~/api/domain/WebhookDelivery.js\";\n\nclass TriggerWebhookUseCaseImpl implements UseCaseAbstraction.Interface {\n constructor(\n private readonly permissions: WebhookPermissions.Interface,\n private readonly getWebhookRepository: GetWebhookRepository.Interface,\n private readonly createDeliveryRepository: CreateWebhookDeliveryRepository.Interface,\n private readonly taskService: TaskService.Interface\n ) {}\n\n async execute(\n webhookId: string,\n payload: Record<string, unknown>\n ): Promise<Result<WebhookDelivery, UseCaseAbstraction.Error>> {\n if (!(await this.permissions.canEdit(\"webhook\"))) {\n return Result.fail(new WebhookNotAuthorizedError());\n }\n\n const webhookResult = await this.getWebhookRepository.execute(webhookId);\n if (webhookResult.isFail()) {\n return Result.fail(webhookResult.error);\n }\n\n const webhook = webhookResult.value;\n\n const expiresAt = new Date(\n Date.now() + WEBHOOK_DELIVERY_RETENTION_DAYS * 24 * 60 * 60 * 1000\n ).toISOString();\n\n const deliveryResult = await this.createDeliveryRepository.execute({\n webhookId: webhook.id,\n eventType: \"webhook.test\",\n status: \"pending\",\n payload,\n expiresAt\n });\n\n if (deliveryResult.isFail()) {\n return Result.fail(deliveryResult.error);\n }\n\n const delivery = deliveryResult.value;\n\n await this.taskService.trigger<ISendWebhookTaskInput>({\n definition: SEND_WEBHOOK_TASK,\n name: `Test webhook: ${webhook.slug}`,\n input: {\n webhookId: webhook.id,\n eventName: \"webhook.test\",\n deliveryId: delivery.id\n }\n });\n\n return Result.ok(delivery);\n }\n}\n\nexport const TriggerWebhookUseCase = UseCaseAbstraction.createImplementation({\n implementation: TriggerWebhookUseCaseImpl,\n dependencies: [\n WebhookPermissions,\n GetWebhookRepository,\n CreateWebhookDeliveryRepository,\n TaskService\n ]\n});\n"],"names":["TriggerWebhookUseCaseImpl","permissions","getWebhookRepository","createDeliveryRepository","taskService","webhookId","payload","Result","WebhookNotAuthorizedError","webhookResult","webhook","expiresAt","Date","WEBHOOK_DELIVERY_RETENTION_DAYS","deliveryResult","delivery","SEND_WEBHOOK_TASK","TriggerWebhookUseCase","UseCaseAbstraction","WebhookPermissions","GetWebhookRepository","CreateWebhookDeliveryRepository","TaskService"],"mappings":"
|
|
1
|
+
{"version":3,"file":"api/features/TriggerWebhook/TriggerWebhookUseCase.js","sources":["../../../../src/api/features/TriggerWebhook/TriggerWebhookUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { TaskService } from \"@webiny/api-core/exports/api/tasks.js\";\nimport { TriggerWebhookUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { TriggerWebhookInputSchema } from \"./schema.js\";\nimport { GetWebhookRepository } from \"~/api/features/GetWebhook/abstractions.js\";\nimport { CreateWebhookDeliveryRepository } from \"~/api/features/CreateWebhookDelivery/abstractions.js\";\nimport { WebhookPermissions } from \"~/api/features/WebhookPermissions/abstractions.js\";\nimport { WebhookNotAuthorizedError, WebhookValidationError } from \"~/api/domain/errors.js\";\nimport { SEND_WEBHOOK_TASK, WEBHOOK_DELIVERY_RETENTION_DAYS } from \"~/api/domain/constants.js\";\nimport type { ISendWebhookTaskInput } from \"~/api/features/SendWebhookTask/types.js\";\nimport type { WebhookDelivery } from \"~/api/domain/WebhookDelivery.js\";\n\nclass TriggerWebhookUseCaseImpl implements UseCaseAbstraction.Interface {\n constructor(\n private readonly permissions: WebhookPermissions.Interface,\n private readonly getWebhookRepository: GetWebhookRepository.Interface,\n private readonly createDeliveryRepository: CreateWebhookDeliveryRepository.Interface,\n private readonly taskService: TaskService.Interface\n ) {}\n\n async execute(\n webhookId: string,\n payload: Record<string, unknown>\n ): Promise<Result<WebhookDelivery, UseCaseAbstraction.Error>> {\n if (!(await this.permissions.canEdit(\"webhook\"))) {\n return Result.fail(new WebhookNotAuthorizedError());\n }\n\n const parsed = TriggerWebhookInputSchema.safeParse({ webhookId, payload });\n if (!parsed.success) {\n return Result.fail(new WebhookValidationError(parsed.error));\n }\n\n const webhookResult = await this.getWebhookRepository.execute(parsed.data.webhookId);\n if (webhookResult.isFail()) {\n return Result.fail(webhookResult.error);\n }\n\n const webhook = webhookResult.value;\n\n const expiresAt = new Date(\n Date.now() + WEBHOOK_DELIVERY_RETENTION_DAYS * 24 * 60 * 60 * 1000\n ).toISOString();\n\n const deliveryResult = await this.createDeliveryRepository.execute({\n webhookId: webhook.id,\n eventType: \"webhook.test\",\n status: \"pending\",\n payload,\n expiresAt\n });\n\n if (deliveryResult.isFail()) {\n return Result.fail(deliveryResult.error);\n }\n\n const delivery = deliveryResult.value;\n\n await this.taskService.trigger<ISendWebhookTaskInput>({\n definition: SEND_WEBHOOK_TASK,\n name: `Test webhook: ${webhook.slug}`,\n input: {\n webhookId: webhook.id,\n eventName: \"webhook.test\",\n deliveryId: delivery.id\n }\n });\n\n return Result.ok(delivery);\n }\n}\n\nexport const TriggerWebhookUseCase = UseCaseAbstraction.createImplementation({\n implementation: TriggerWebhookUseCaseImpl,\n dependencies: [\n WebhookPermissions,\n GetWebhookRepository,\n CreateWebhookDeliveryRepository,\n TaskService\n ]\n});\n"],"names":["TriggerWebhookUseCaseImpl","permissions","getWebhookRepository","createDeliveryRepository","taskService","webhookId","payload","Result","WebhookNotAuthorizedError","parsed","TriggerWebhookInputSchema","WebhookValidationError","webhookResult","webhook","expiresAt","Date","WEBHOOK_DELIVERY_RETENTION_DAYS","deliveryResult","delivery","SEND_WEBHOOK_TASK","TriggerWebhookUseCase","UseCaseAbstraction","WebhookPermissions","GetWebhookRepository","CreateWebhookDeliveryRepository","TaskService"],"mappings":";;;;;;;;;AAYA,MAAMA;IACF,YACqBC,WAAyC,EACzCC,oBAAoD,EACpDC,wBAAmE,EACnEC,WAAkC,CACrD;aAJmBH,WAAW,GAAXA;aACAC,oBAAoB,GAApBA;aACAC,wBAAwB,GAAxBA;aACAC,WAAW,GAAXA;IAClB;IAEH,MAAM,QACFC,SAAiB,EACjBC,OAAgC,EAC0B;QAC1D,IAAI,CAAE,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,YACjC,OAAOC,OAAO,IAAI,CAAC,IAAIC;QAG3B,MAAMC,SAASC,0BAA0B,SAAS,CAAC;YAAEL;YAAWC;QAAQ;QACxE,IAAI,CAACG,OAAO,OAAO,EACf,OAAOF,OAAO,IAAI,CAAC,IAAII,uBAAuBF,OAAO,KAAK;QAG9D,MAAMG,gBAAgB,MAAM,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAACH,OAAO,IAAI,CAAC,SAAS;QACnF,IAAIG,cAAc,MAAM,IACpB,OAAOL,OAAO,IAAI,CAACK,cAAc,KAAK;QAG1C,MAAMC,UAAUD,cAAc,KAAK;QAEnC,MAAME,YAAY,IAAIC,KAClBA,KAAK,GAAG,KAAKC,AAAkC,KAAlCA,kCAAAA,SACf,WAAW;QAEb,MAAMC,iBAAiB,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC;YAC/D,WAAWJ,QAAQ,EAAE;YACrB,WAAW;YACX,QAAQ;YACRP;YACAQ;QACJ;QAEA,IAAIG,eAAe,MAAM,IACrB,OAAOV,OAAO,IAAI,CAACU,eAAe,KAAK;QAG3C,MAAMC,WAAWD,eAAe,KAAK;QAErC,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAwB;YAClD,YAAYE;YACZ,MAAM,CAAC,cAAc,EAAEN,QAAQ,IAAI,EAAE;YACrC,OAAO;gBACH,WAAWA,QAAQ,EAAE;gBACrB,WAAW;gBACX,YAAYK,SAAS,EAAE;YAC3B;QACJ;QAEA,OAAOX,OAAO,EAAE,CAACW;IACrB;AACJ;AAEO,MAAME,8CAAwBC,sBAAAA,oBAAuC,CAAC;IACzE,gBAAgBrB;IAChB,cAAc;QACVsB;QACAC;QACAC;QACAC;KACH;AACL"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Result } from "@webiny/feature/api";
|
|
2
2
|
import type { WebhookDelivery } from "../../../api/domain/WebhookDelivery.js";
|
|
3
|
-
import type { WebhookNotFoundError, WebhookPersistenceError, WebhookModelNotFoundError, WebhookNotAuthorizedError } from "../../../api/domain/errors.js";
|
|
4
|
-
type IError = WebhookNotFoundError | WebhookPersistenceError | WebhookModelNotFoundError | WebhookNotAuthorizedError;
|
|
3
|
+
import type { WebhookNotFoundError, WebhookPersistenceError, WebhookModelNotFoundError, WebhookNotAuthorizedError, WebhookValidationError } from "../../../api/domain/errors.js";
|
|
4
|
+
type IError = WebhookNotFoundError | WebhookPersistenceError | WebhookModelNotFoundError | WebhookNotAuthorizedError | WebhookValidationError;
|
|
5
5
|
export interface ITriggerWebhookUseCase {
|
|
6
6
|
execute(webhookId: string, payload: Record<string, unknown>): Promise<Result<WebhookDelivery, IError>>;
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/features/TriggerWebhook/abstractions.js","sources":["../../../../src/api/features/TriggerWebhook/abstractions.ts"],"sourcesContent":["import { createAbstraction, type Result } from \"@webiny/feature/api\";\nimport type { WebhookDelivery } from \"~/api/domain/WebhookDelivery.js\";\nimport type {\n WebhookNotFoundError,\n WebhookPersistenceError,\n WebhookModelNotFoundError,\n WebhookNotAuthorizedError\n} from \"~/api/domain/errors.js\";\n\ntype IError =\n | WebhookNotFoundError\n | WebhookPersistenceError\n | WebhookModelNotFoundError\n | WebhookNotAuthorizedError;\n\nexport interface ITriggerWebhookUseCase {\n execute(\n webhookId: string,\n payload: Record<string, unknown>\n ): Promise<Result<WebhookDelivery, IError>>;\n}\n\nexport const TriggerWebhookUseCase = createAbstraction<ITriggerWebhookUseCase>(\n \"Webhooks/TriggerWebhookUseCase\"\n);\n\nexport namespace TriggerWebhookUseCase {\n export type Interface = ITriggerWebhookUseCase;\n export type Error = IError;\n}\n"],"names":["TriggerWebhookUseCase","createAbstraction"],"mappings":";
|
|
1
|
+
{"version":3,"file":"api/features/TriggerWebhook/abstractions.js","sources":["../../../../src/api/features/TriggerWebhook/abstractions.ts"],"sourcesContent":["import { createAbstraction, type Result } from \"@webiny/feature/api\";\nimport type { WebhookDelivery } from \"~/api/domain/WebhookDelivery.js\";\nimport type {\n WebhookNotFoundError,\n WebhookPersistenceError,\n WebhookModelNotFoundError,\n WebhookNotAuthorizedError,\n WebhookValidationError\n} from \"~/api/domain/errors.js\";\n\ntype IError =\n | WebhookNotFoundError\n | WebhookPersistenceError\n | WebhookModelNotFoundError\n | WebhookNotAuthorizedError\n | WebhookValidationError;\n\nexport interface ITriggerWebhookUseCase {\n execute(\n webhookId: string,\n payload: Record<string, unknown>\n ): Promise<Result<WebhookDelivery, IError>>;\n}\n\nexport const TriggerWebhookUseCase = createAbstraction<ITriggerWebhookUseCase>(\n \"Webhooks/TriggerWebhookUseCase\"\n);\n\nexport namespace TriggerWebhookUseCase {\n export type Interface = ITriggerWebhookUseCase;\n export type Error = IError;\n}\n"],"names":["TriggerWebhookUseCase","createAbstraction"],"mappings":";AAwBO,MAAMA,wBAAwBC,kBACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/TriggerWebhook/schema.js","sources":["../../../../src/api/features/TriggerWebhook/schema.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const TriggerWebhookInputSchema = z.object({\n webhookId: z.string().min(1, \"Webhook ID is required.\"),\n payload: z.record(z.string(), z.unknown())\n});\n"],"names":["TriggerWebhookInputSchema","z"],"mappings":";AAEO,MAAMA,4BAA4BC,EAAE,MAAM,CAAC;IAC9C,WAAWA,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG;IAC7B,SAASA,EAAE,MAAM,CAACA,EAAE,MAAM,IAAIA,EAAE,OAAO;AAC3C"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
|
-
import { UpdateWebhookUseCase as UseCaseAbstraction
|
|
2
|
+
import { UpdateWebhookRepository, UpdateWebhookUseCase as UseCaseAbstraction } from "./abstractions.js";
|
|
3
3
|
import { GetWebhookRepository } from "../../../api/features/GetWebhook/abstractions.js";
|
|
4
4
|
import { WebhookPermissions } from "../../../api/features/WebhookPermissions/abstractions.js";
|
|
5
5
|
import type { Webhook } from "../../../api/domain/Webhook.js";
|
|
6
6
|
declare class UpdateWebhookUseCaseImpl implements UseCaseAbstraction.Interface {
|
|
7
|
-
private permissions;
|
|
8
|
-
private getWebhookRepository;
|
|
9
|
-
private updateRepository;
|
|
7
|
+
private readonly permissions;
|
|
8
|
+
private readonly getWebhookRepository;
|
|
9
|
+
private readonly updateRepository;
|
|
10
10
|
constructor(permissions: WebhookPermissions.Interface, getWebhookRepository: GetWebhookRepository.Interface, updateRepository: UpdateWebhookRepository.Interface);
|
|
11
11
|
execute(id: string, input: UseCaseAbstraction.Input): Promise<Result<Webhook, UseCaseAbstraction.Error>>;
|
|
12
12
|
}
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { UpdateWebhookRepository, UpdateWebhookUseCase } from "./abstractions.js";
|
|
3
|
+
import { UpdateWebhookInputSchema } from "./schema.js";
|
|
3
4
|
import { GetWebhookRepository } from "../GetWebhook/abstractions.js";
|
|
4
5
|
import { WebhookPermissions } from "../WebhookPermissions/abstractions.js";
|
|
5
6
|
import { WebhookNotAuthorizedError, WebhookValidationError } from "../../domain/errors.js";
|
|
6
|
-
const isValidEndpointUrl = (url)=>{
|
|
7
|
-
try {
|
|
8
|
-
const parsed = new URL(url);
|
|
9
|
-
if ("https:" === parsed.protocol) return true;
|
|
10
|
-
if ("http:" === parsed.protocol && ("localhost" === parsed.hostname || "127.0.0.1" === parsed.hostname)) return true;
|
|
11
|
-
return false;
|
|
12
|
-
} catch {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
7
|
class UpdateWebhookUseCaseImpl {
|
|
17
8
|
constructor(permissions, getWebhookRepository, updateRepository){
|
|
18
9
|
this.permissions = permissions;
|
|
@@ -21,34 +12,19 @@ class UpdateWebhookUseCaseImpl {
|
|
|
21
12
|
}
|
|
22
13
|
async execute(id, input) {
|
|
23
14
|
if (!await this.permissions.canEdit("webhook")) return Result.fail(new WebhookNotAuthorizedError());
|
|
15
|
+
const parsed = UpdateWebhookInputSchema.safeParse(input);
|
|
16
|
+
if (!parsed.success) return Result.fail(new WebhookValidationError(parsed.error));
|
|
24
17
|
const getResult = await this.getWebhookRepository.execute(id);
|
|
25
18
|
if (getResult.isFail()) return Result.fail(getResult.error);
|
|
26
19
|
const existing = getResult.value;
|
|
27
|
-
if (input.endpointUrl && !isValidEndpointUrl(input.endpointUrl)) return Result.fail(new WebhookValidationError("Endpoint URL must use HTTPS. HTTP is only allowed for localhost."));
|
|
28
|
-
if (void 0 !== input.events && 0 === input.events.length) return Result.fail(new WebhookValidationError("At least one event must be selected."));
|
|
29
20
|
const updated = {
|
|
30
21
|
...existing,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
...void 0 !== input.endpointUrl ? {
|
|
38
|
-
endpointUrl: input.endpointUrl
|
|
39
|
-
} : {},
|
|
40
|
-
...void 0 !== input.description ? {
|
|
41
|
-
description: input.description
|
|
42
|
-
} : {},
|
|
43
|
-
...void 0 !== input.enabled ? {
|
|
44
|
-
enabled: input.enabled
|
|
45
|
-
} : {},
|
|
46
|
-
...void 0 !== input.events ? {
|
|
47
|
-
events: input.events
|
|
48
|
-
} : {},
|
|
49
|
-
...void 0 !== input.signingSecret ? {
|
|
50
|
-
signingSecret: input.signingSecret
|
|
51
|
-
} : {}
|
|
22
|
+
name: parsed.data.name ?? existing.name,
|
|
23
|
+
endpointUrl: parsed.data.endpointUrl ?? existing.endpointUrl,
|
|
24
|
+
description: parsed.data.description ?? existing.description,
|
|
25
|
+
enabled: parsed.data.enabled ?? existing.enabled,
|
|
26
|
+
events: parsed.data.events ?? existing.events,
|
|
27
|
+
signingSecret: parsed.data.signingSecret ?? existing.signingSecret
|
|
52
28
|
};
|
|
53
29
|
return this.updateRepository.execute(updated);
|
|
54
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/features/UpdateWebhook/UpdateWebhookUseCase.js","sources":["../../../../src/api/features/UpdateWebhook/UpdateWebhookUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport {\n UpdateWebhookUseCase as UseCaseAbstraction
|
|
1
|
+
{"version":3,"file":"api/features/UpdateWebhook/UpdateWebhookUseCase.js","sources":["../../../../src/api/features/UpdateWebhook/UpdateWebhookUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport {\n UpdateWebhookRepository,\n UpdateWebhookUseCase as UseCaseAbstraction\n} from \"./abstractions.js\";\nimport { UpdateWebhookInputSchema } from \"./schema.js\";\nimport { GetWebhookRepository } from \"~/api/features/GetWebhook/abstractions.js\";\nimport { WebhookPermissions } from \"~/api/features/WebhookPermissions/abstractions.js\";\nimport { WebhookNotAuthorizedError, WebhookValidationError } from \"~/api/domain/errors.js\";\nimport type { Webhook } from \"~/api/domain/Webhook.js\";\n\nclass UpdateWebhookUseCaseImpl implements UseCaseAbstraction.Interface {\n constructor(\n private readonly permissions: WebhookPermissions.Interface,\n private readonly getWebhookRepository: GetWebhookRepository.Interface,\n private readonly updateRepository: UpdateWebhookRepository.Interface\n ) {}\n\n async execute(\n id: string,\n input: UseCaseAbstraction.Input\n ): Promise<Result<Webhook, UseCaseAbstraction.Error>> {\n if (!(await this.permissions.canEdit(\"webhook\"))) {\n return Result.fail(new WebhookNotAuthorizedError());\n }\n\n const parsed = UpdateWebhookInputSchema.safeParse(input);\n if (!parsed.success) {\n return Result.fail(new WebhookValidationError(parsed.error));\n }\n\n const getResult = await this.getWebhookRepository.execute(id);\n if (getResult.isFail()) {\n return Result.fail(getResult.error);\n }\n\n const existing = getResult.value;\n\n const updated: Webhook = {\n ...existing,\n name: parsed.data.name ?? existing.name,\n endpointUrl: parsed.data.endpointUrl ?? existing.endpointUrl,\n description: parsed.data.description ?? existing.description,\n enabled: parsed.data.enabled ?? existing.enabled,\n events: parsed.data.events ?? existing.events,\n signingSecret: parsed.data.signingSecret ?? existing.signingSecret\n };\n\n return this.updateRepository.execute(updated);\n }\n}\n\nexport const UpdateWebhookUseCase = UseCaseAbstraction.createImplementation({\n implementation: UpdateWebhookUseCaseImpl,\n dependencies: [WebhookPermissions, GetWebhookRepository, UpdateWebhookRepository]\n});\n"],"names":["UpdateWebhookUseCaseImpl","permissions","getWebhookRepository","updateRepository","id","input","Result","WebhookNotAuthorizedError","parsed","UpdateWebhookInputSchema","WebhookValidationError","getResult","existing","updated","UpdateWebhookUseCase","UseCaseAbstraction","WebhookPermissions","GetWebhookRepository","UpdateWebhookRepository"],"mappings":";;;;;;AAWA,MAAMA;IACF,YACqBC,WAAyC,EACzCC,oBAAoD,EACpDC,gBAAmD,CACtE;aAHmBF,WAAW,GAAXA;aACAC,oBAAoB,GAApBA;aACAC,gBAAgB,GAAhBA;IAClB;IAEH,MAAM,QACFC,EAAU,EACVC,KAA+B,EACmB;QAClD,IAAI,CAAE,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,YACjC,OAAOC,OAAO,IAAI,CAAC,IAAIC;QAG3B,MAAMC,SAASC,yBAAyB,SAAS,CAACJ;QAClD,IAAI,CAACG,OAAO,OAAO,EACf,OAAOF,OAAO,IAAI,CAAC,IAAII,uBAAuBF,OAAO,KAAK;QAG9D,MAAMG,YAAY,MAAM,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAACP;QAC1D,IAAIO,UAAU,MAAM,IAChB,OAAOL,OAAO,IAAI,CAACK,UAAU,KAAK;QAGtC,MAAMC,WAAWD,UAAU,KAAK;QAEhC,MAAME,UAAmB;YACrB,GAAGD,QAAQ;YACX,MAAMJ,OAAO,IAAI,CAAC,IAAI,IAAII,SAAS,IAAI;YACvC,aAAaJ,OAAO,IAAI,CAAC,WAAW,IAAII,SAAS,WAAW;YAC5D,aAAaJ,OAAO,IAAI,CAAC,WAAW,IAAII,SAAS,WAAW;YAC5D,SAASJ,OAAO,IAAI,CAAC,OAAO,IAAII,SAAS,OAAO;YAChD,QAAQJ,OAAO,IAAI,CAAC,MAAM,IAAII,SAAS,MAAM;YAC7C,eAAeJ,OAAO,IAAI,CAAC,aAAa,IAAII,SAAS,aAAa;QACtE;QAEA,OAAO,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAACC;IACzC;AACJ;AAEO,MAAMC,4CAAuBC,qBAAAA,oBAAuC,CAAC;IACxE,gBAAgBf;IAChB,cAAc;QAACgB;QAAoBC;QAAsBC;KAAwB;AACrF"}
|
|
@@ -3,7 +3,6 @@ import type { Webhook } from "../../../api/domain/Webhook.js";
|
|
|
3
3
|
import type { WebhookNotFoundError, WebhookValidationError, WebhookPersistenceError, WebhookModelNotFoundError, WebhookNotAuthorizedError } from "../../../api/domain/errors.js";
|
|
4
4
|
export interface IUpdateWebhookInput {
|
|
5
5
|
name?: string;
|
|
6
|
-
slug?: string;
|
|
7
6
|
endpointUrl?: string;
|
|
8
7
|
description?: string;
|
|
9
8
|
enabled?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/features/UpdateWebhook/abstractions.js","sources":["../../../../src/api/features/UpdateWebhook/abstractions.ts"],"sourcesContent":["import { createAbstraction, type Result } from \"@webiny/feature/api\";\nimport type { Webhook } from \"~/api/domain/Webhook.js\";\nimport type {\n WebhookNotFoundError,\n WebhookValidationError,\n WebhookPersistenceError,\n WebhookModelNotFoundError,\n WebhookNotAuthorizedError\n} from \"~/api/domain/errors.js\";\n\nexport interface IUpdateWebhookInput {\n name?: string;\n
|
|
1
|
+
{"version":3,"file":"api/features/UpdateWebhook/abstractions.js","sources":["../../../../src/api/features/UpdateWebhook/abstractions.ts"],"sourcesContent":["import { createAbstraction, type Result } from \"@webiny/feature/api\";\nimport type { Webhook } from \"~/api/domain/Webhook.js\";\nimport type {\n WebhookNotFoundError,\n WebhookValidationError,\n WebhookPersistenceError,\n WebhookModelNotFoundError,\n WebhookNotAuthorizedError\n} from \"~/api/domain/errors.js\";\n\nexport interface IUpdateWebhookInput {\n name?: string;\n endpointUrl?: string;\n description?: string;\n enabled?: boolean;\n events?: string[];\n signingSecret?: string;\n}\n\ntype IError =\n | WebhookNotFoundError\n | WebhookValidationError\n | WebhookPersistenceError\n | WebhookModelNotFoundError\n | WebhookNotAuthorizedError;\n\nexport interface IUpdateWebhookUseCase {\n execute(id: string, input: IUpdateWebhookInput): Promise<Result<Webhook, IError>>;\n}\n\nexport const UpdateWebhookUseCase = createAbstraction<IUpdateWebhookUseCase>(\n \"Webhooks/UpdateWebhookUseCase\"\n);\n\nexport namespace UpdateWebhookUseCase {\n export type Interface = IUpdateWebhookUseCase;\n export type Input = IUpdateWebhookInput;\n export type Error = IError;\n}\n\nexport interface IUpdateWebhookRepository {\n execute(\n webhook: Webhook\n ): Promise<Result<Webhook, WebhookPersistenceError | WebhookModelNotFoundError>>;\n}\n\nexport const UpdateWebhookRepository = createAbstraction<IUpdateWebhookRepository>(\n \"Webhooks/UpdateWebhookRepository\"\n);\n\nexport namespace UpdateWebhookRepository {\n export type Interface = IUpdateWebhookRepository;\n export type Error = WebhookPersistenceError | WebhookModelNotFoundError;\n}\n"],"names":["UpdateWebhookUseCase","createAbstraction","UpdateWebhookRepository"],"mappings":";AA8BO,MAAMA,uBAAuBC,kBAChC;AAeG,MAAMC,0BAA0BD,kBACnC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const UpdateWebhookInputSchema: z.ZodObject<{
|
|
3
|
+
name: z.ZodOptional<z.ZodString>;
|
|
4
|
+
endpointUrl: z.ZodOptional<z.ZodString>;
|
|
5
|
+
description: z.ZodOptional<z.ZodString>;
|
|
6
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
7
|
+
events: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
8
|
+
signingSecret: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { isValidEndpointUrl } from "../../utils/isValidEndpointUrl.js";
|
|
3
|
+
const UpdateWebhookInputSchema = z.object({
|
|
4
|
+
name: z.string().min(1, "Name must not be empty.").optional(),
|
|
5
|
+
endpointUrl: z.string().refine(isValidEndpointUrl, {
|
|
6
|
+
message: "Endpoint URL must use HTTPS. HTTP is only allowed for localhost."
|
|
7
|
+
}).optional(),
|
|
8
|
+
description: z.string().optional(),
|
|
9
|
+
enabled: z.boolean().optional(),
|
|
10
|
+
events: z.array(z.string()).min(1, "At least one event must be selected.").optional(),
|
|
11
|
+
signingSecret: z.string().optional()
|
|
12
|
+
});
|
|
13
|
+
export { UpdateWebhookInputSchema };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=schema.js.map
|