@hed-hog/core 0.0.368 → 0.0.371
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/LICENSE.md +21 -0
- package/README.md +2 -0
- package/dist/ai/ai.service.d.ts.map +1 -1
- package/dist/ai/ai.service.js +10 -7
- package/dist/ai/ai.service.js.map +1 -1
- package/dist/app-command/app-command.module.d.ts +3 -0
- package/dist/app-command/app-command.module.d.ts.map +1 -0
- package/dist/app-command/app-command.module.js +22 -0
- package/dist/app-command/app-command.module.js.map +1 -0
- package/dist/app-command/app-command.registry.d.ts +22 -0
- package/dist/app-command/app-command.registry.d.ts.map +1 -0
- package/dist/{webhook-integration/webhook-command.registry.js → app-command/app-command.registry.js} +6 -6
- package/dist/app-command/app-command.registry.js.map +1 -0
- package/dist/auth/auth.controller.d.ts +2 -2
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +20 -7
- package/dist/auth/auth.controller.js.map +1 -1
- package/dist/auth/auth.service.d.ts +3 -3
- package/dist/auth/auth.service.d.ts.map +1 -1
- package/dist/auth/auth.service.js +10 -36
- package/dist/auth/auth.service.js.map +1 -1
- package/dist/auth/dto/forget.dto.d.ts +1 -0
- package/dist/auth/dto/forget.dto.d.ts.map +1 -1
- package/dist/auth/dto/forget.dto.js +5 -0
- package/dist/auth/dto/forget.dto.js.map +1 -1
- package/dist/auth/guards/auth.guard.d.ts.map +1 -1
- package/dist/auth/guards/auth.guard.js +4 -1
- package/dist/auth/guards/auth.guard.js.map +1 -1
- package/dist/challenge/challenge.service.d.ts +8 -7
- package/dist/challenge/challenge.service.d.ts.map +1 -1
- package/dist/challenge/challenge.service.js +27 -19
- package/dist/challenge/challenge.service.js.map +1 -1
- package/dist/file/dto/upload.dto.d.ts +3 -0
- package/dist/file/dto/upload.dto.d.ts.map +1 -1
- package/dist/file/dto/upload.dto.js +22 -0
- package/dist/file/dto/upload.dto.js.map +1 -1
- package/dist/file/file.controller.d.ts +2 -1
- package/dist/file/file.controller.d.ts.map +1 -1
- package/dist/file/file.controller.js +29 -16
- package/dist/file/file.controller.js.map +1 -1
- package/dist/file/file.service.d.ts +51 -1
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +250 -18
- package/dist/file/file.service.js.map +1 -1
- package/dist/file/image-optimization.service.d.ts +17 -4
- package/dist/file/image-optimization.service.d.ts.map +1 -1
- package/dist/file/image-optimization.service.js +101 -46
- package/dist/file/image-optimization.service.js.map +1 -1
- package/dist/file/provider/s3.provider.d.ts.map +1 -1
- package/dist/file/provider/s3.provider.js +15 -7
- package/dist/file/provider/s3.provider.js.map +1 -1
- package/dist/file/provider/spaces.provider.d.ts.map +1 -1
- package/dist/file/provider/spaces.provider.js +18 -8
- package/dist/file/provider/spaces.provider.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/integration/services/event-subscriber.registry.d.ts +5 -0
- package/dist/integration/services/event-subscriber.registry.d.ts.map +1 -1
- package/dist/integration/services/event-subscriber.registry.js +15 -0
- package/dist/integration/services/event-subscriber.registry.js.map +1 -1
- package/dist/integration/services/outbox.processor.d.ts.map +1 -1
- package/dist/integration/services/outbox.processor.js +2 -4
- package/dist/integration/services/outbox.processor.js.map +1 -1
- package/dist/integration/services/outbox.service.d.ts +4 -2
- package/dist/integration/services/outbox.service.d.ts.map +1 -1
- package/dist/integration/services/outbox.service.js +26 -15
- package/dist/integration/services/outbox.service.js.map +1 -1
- package/dist/integration-profile/integration-credential-crypto.service.d.ts +43 -0
- package/dist/integration-profile/integration-credential-crypto.service.d.ts.map +1 -0
- package/dist/integration-profile/integration-credential-crypto.service.js +142 -0
- package/dist/integration-profile/integration-credential-crypto.service.js.map +1 -0
- package/dist/integration-profile/integration-profile.controller.d.ts +6 -7
- package/dist/integration-profile/integration-profile.controller.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.controller.js +4 -3
- package/dist/integration-profile/integration-profile.controller.js.map +1 -1
- package/dist/integration-profile/integration-profile.module.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.module.js +5 -2
- package/dist/integration-profile/integration-profile.module.js.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.d.ts +16 -0
- package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -0
- package/dist/integration-profile/integration-profile.secrets.js +56 -0
- package/dist/integration-profile/integration-profile.secrets.js.map +1 -0
- package/dist/integration-profile/integration-profile.service.d.ts +125 -8
- package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.service.js +257 -68
- package/dist/integration-profile/integration-profile.service.js.map +1 -1
- package/dist/integration-profile/integration-profile.utils.d.ts +17 -0
- package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.utils.js +31 -0
- package/dist/integration-profile/integration-profile.utils.js.map +1 -1
- package/dist/language/en.json +178 -0
- package/dist/language/pt.json +178 -0
- package/dist/mail/mail.controller.d.ts.map +1 -1
- package/dist/mail/mail.controller.js +5 -28
- package/dist/mail/mail.controller.js.map +1 -1
- package/dist/mail/mail.module.js +18 -18
- package/dist/mail/mail.module.js.map +1 -1
- package/dist/mail/mail.service.d.ts +13 -2
- package/dist/mail/mail.service.d.ts.map +1 -1
- package/dist/mail/mail.service.js +25 -15
- package/dist/mail/mail.service.js.map +1 -1
- package/dist/mcp-chat/mcp-chat.service.js +6 -5
- package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
- package/dist/oauth/providers/facebook.provider.js +5 -5
- package/dist/oauth/providers/facebook.provider.js.map +1 -1
- package/dist/oauth/providers/github.provider.js +5 -5
- package/dist/oauth/providers/github.provider.js.map +1 -1
- package/dist/oauth/providers/google.provider.js +5 -5
- package/dist/oauth/providers/google.provider.js.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.js +5 -5
- package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
- package/dist/oauth/providers/microsoft.provider.js +5 -5
- package/dist/oauth/providers/microsoft.provider.js.map +1 -1
- package/dist/pdf/pdf.service.d.ts +4 -0
- package/dist/pdf/pdf.service.d.ts.map +1 -1
- package/dist/pdf/pdf.service.js +16 -9
- package/dist/pdf/pdf.service.js.map +1 -1
- package/dist/profile/profile.controller.d.ts +7 -7
- package/dist/profile/profile.controller.d.ts.map +1 -1
- package/dist/profile/profile.controller.js +28 -21
- package/dist/profile/profile.controller.js.map +1 -1
- package/dist/profile/profile.service.d.ts +7 -7
- package/dist/profile/profile.service.d.ts.map +1 -1
- package/dist/profile/profile.service.js +21 -25
- package/dist/profile/profile.service.js.map +1 -1
- package/dist/setting/setting.service.d.ts +1 -0
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +15 -2
- package/dist/setting/setting.service.js.map +1 -1
- package/dist/token/token.service.d.ts.map +1 -1
- package/dist/token/token.service.js +2 -1
- package/dist/token/token.service.js.map +1 -1
- package/dist/user/user.controller.d.ts +9 -0
- package/dist/user/user.controller.d.ts.map +1 -1
- package/dist/user/user.controller.js +13 -0
- package/dist/user/user.controller.js.map +1 -1
- package/dist/user/user.service.d.ts +7 -0
- package/dist/user/user.service.d.ts.map +1 -1
- package/dist/user/user.service.js +19 -0
- package/dist/user/user.service.js.map +1 -1
- package/dist/utils/webauthn-origin.d.ts +11 -0
- package/dist/utils/webauthn-origin.d.ts.map +1 -0
- package/dist/utils/webauthn-origin.js +37 -0
- package/dist/utils/webauthn-origin.js.map +1 -0
- package/dist/webhook-integration/webhook-integration.controller.d.ts +13 -0
- package/dist/webhook-integration/webhook-integration.controller.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-integration.controller.js +29 -0
- package/dist/webhook-integration/webhook-integration.controller.js.map +1 -1
- package/dist/webhook-integration/webhook-integration.module.js +3 -3
- package/dist/webhook-integration/webhook-integration.module.js.map +1 -1
- package/dist/webhook-integration/webhook-integration.service.d.ts +18 -2
- package/dist/webhook-integration/webhook-integration.service.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-integration.service.js +110 -6
- package/dist/webhook-integration/webhook-integration.service.js.map +1 -1
- package/hedhog/data/integration_event_catalog.yaml +118 -118
- package/hedhog/data/integration_provider.yaml +9 -0
- package/hedhog/data/integration_type.yaml +6 -0
- package/hedhog/data/menu.yaml +6 -0
- package/hedhog/data/role.yaml +7 -0
- package/hedhog/data/route.yaml +192 -207
- package/hedhog/data/setting_group.yaml +119 -13
- package/hedhog/frontend/app/access-log/page.tsx.ejs +35 -3
- package/hedhog/frontend/app/account/components/active-sessions.tsx.ejs +36 -3
- package/hedhog/frontend/app/account/components/mcp-tokens.tsx.ejs +39 -4
- package/hedhog/frontend/app/account/components/tokens.tsx.ejs +39 -4
- package/hedhog/frontend/app/ai_agent/page.tsx.ejs +35 -2
- package/hedhog/frontend/app/configurations/[slug]/components/byte-size-input.tsx.ejs +160 -0
- package/hedhog/frontend/app/configurations/[slug]/components/duration-input.tsx.ejs +157 -0
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +244 -63
- package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +33 -1
- package/hedhog/frontend/app/dashboard/management/tabs/component-roles-tab.tsx.ejs +35 -3
- package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +36 -4
- package/hedhog/frontend/app/dashboard/management/tabs/dashboard-roles-tab.tsx.ejs +35 -3
- package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +36 -4
- package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +35 -3
- package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +141 -29
- package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +118 -11
- package/hedhog/frontend/app/mail/log/page.tsx.ejs +37 -4
- package/hedhog/frontend/app/menu/page.tsx.ejs +34 -2
- package/hedhog/frontend/app/preferences/page.tsx.ejs +77 -0
- package/hedhog/frontend/app/roles/menus.tsx.ejs +35 -3
- package/hedhog/frontend/app/roles/page.tsx.ejs +34 -2
- package/hedhog/frontend/app/roles/routes.tsx.ejs +36 -4
- package/hedhog/frontend/app/roles/users.tsx.ejs +36 -4
- package/hedhog/frontend/app/routes/page.tsx.ejs +34 -2
- package/hedhog/frontend/app/setting-list/page.tsx.ejs +34 -2
- package/hedhog/frontend/app/users/page.tsx.ejs +51 -21
- package/hedhog/frontend/messages/en.json +69 -4
- package/hedhog/frontend/messages/pt.json +69 -4
- package/hedhog/table/event_webhook.yaml +55 -55
- package/hedhog/table/event_webhook_delivery_log.yaml +66 -66
- package/hedhog/table/event_webhook_event.yaml +26 -26
- package/hedhog/table/integration_event_catalog.yaml +41 -41
- package/hedhog/table/mcp_conversation.yaml +12 -12
- package/hedhog/table/mcp_conversation_message.yaml +23 -23
- package/hedhog/table/mcp_tool_call_log.yaml +22 -22
- package/hedhog/table/route.yaml +33 -33
- package/hedhog/table/setting.yaml +2 -0
- package/hedhog/table/webhook_call_log.yaml +3 -0
- package/hedhog/table/webhook_integration.yaml +43 -43
- package/package.json +9 -4
- package/src/ai/ai.service.ts +9 -6
- package/src/app-command/app-command.module.ts +9 -0
- package/src/{webhook-integration/webhook-command.registry.ts → app-command/app-command.registry.ts} +9 -9
- package/src/auth/auth.controller.ts +20 -4
- package/src/auth/auth.service.ts +10 -36
- package/src/auth/dto/forget.dto.ts +5 -1
- package/src/auth/guards/auth.guard.ts +4 -1
- package/src/challenge/challenge.service.ts +30 -19
- package/src/file/dto/upload.dto.ts +25 -1
- package/src/file/file.controller.ts +31 -18
- package/src/file/file.service.ts +341 -16
- package/src/file/image-optimization.service.ts +111 -46
- package/src/file/provider/s3.provider.ts +16 -7
- package/src/file/provider/spaces.provider.ts +15 -5
- package/src/index.ts +4 -1
- package/src/integration/services/event-subscriber.registry.ts +15 -0
- package/src/integration/services/outbox.processor.ts +2 -5
- package/src/integration/services/outbox.service.ts +35 -17
- package/src/integration/types/event.types.ts +4 -4
- package/src/integration-profile/integration-credential-crypto.service.ts +146 -0
- package/src/integration-profile/integration-profile.controller.ts +2 -0
- package/src/integration-profile/integration-profile.module.ts +5 -2
- package/src/integration-profile/integration-profile.secrets.ts +51 -0
- package/src/integration-profile/integration-profile.service.ts +335 -54
- package/src/integration-profile/integration-profile.utils.ts +56 -0
- package/src/language/en.json +5 -1
- package/src/language/pt.json +5 -1
- package/src/mail/mail.controller.ts +5 -29
- package/src/mail/mail.module.ts +5 -5
- package/src/mail/mail.service.ts +37 -13
- package/src/mcp/decorators/mcp-tool.decorator.ts +7 -7
- package/src/mcp/guards/mcp-permission.guard.ts +51 -51
- package/src/mcp/interfaces/mcp-tool-definition.interface.ts +6 -6
- package/src/mcp/mcp-server.service.ts +87 -87
- package/src/mcp/types/mcp-context.type.ts +6 -6
- package/src/mcp-chat/dto/create-conversation.dto.ts +7 -7
- package/src/mcp-chat/dto/send-message.dto.ts +7 -7
- package/src/mcp-chat/mcp-chat.service.ts +5 -5
- package/src/notification/events/notification-stale-progress-check.event.ts +5 -5
- package/src/oauth/oauth-callback-coordinator.service.spec.ts +159 -0
- package/src/oauth/providers/facebook.provider.ts +3 -3
- package/src/oauth/providers/github.provider.ts +3 -3
- package/src/oauth/providers/google.provider.ts +3 -3
- package/src/oauth/providers/microsoft-entra-id.provider.ts +3 -3
- package/src/oauth/providers/microsoft.provider.ts +3 -3
- package/src/pdf/pdf.service.ts +19 -6
- package/src/profile/profile.controller.ts +21 -14
- package/src/profile/profile.service.ts +23 -20
- package/src/route/dto/create.dto.ts +32 -32
- package/src/route/dto/update.dto.ts +31 -31
- package/src/security/security.service.spec.ts +222 -0
- package/src/setting/setting.service.ts +15 -2
- package/src/token/token.service.ts +2 -1
- package/src/user/user.controller.ts +26 -16
- package/src/user/user.service.ts +25 -0
- package/src/utils/webauthn-origin.ts +38 -0
- package/src/webhook-integration/integration-event-catalog.controller.ts +50 -50
- package/src/webhook-integration/integration-event-catalog.service.ts +117 -117
- package/src/webhook-integration/webhook-integration.controller.ts +23 -0
- package/src/webhook-integration/webhook-integration.module.ts +3 -3
- package/src/webhook-integration/webhook-integration.service.ts +115 -5
- package/dist/webhook-integration/webhook-command.registry.d.ts +0 -22
- package/dist/webhook-integration/webhook-command.registry.d.ts.map +0 -1
- package/dist/webhook-integration/webhook-command.registry.js.map +0 -1
- package/src/menu/menu.service.spec.ts +0 -247
- package/src/route/route.service.spec.ts +0 -300
- package/src/screen/screen.service.spec.ts +0 -298
- package/src/user/user.service.spec.ts +0 -294
|
@@ -1,117 +1,117 @@
|
|
|
1
|
-
import { DeleteDTO } from '@hed-hog/api';
|
|
2
|
-
import { PaginationDTO, PaginationService } from '@hed-hog/api-pagination';
|
|
3
|
-
import { PrismaService } from '@hed-hog/api-prisma';
|
|
4
|
-
import {
|
|
5
|
-
BadRequestException,
|
|
6
|
-
Injectable,
|
|
7
|
-
NotFoundException,
|
|
8
|
-
} from '@nestjs/common';
|
|
9
|
-
|
|
10
|
-
@Injectable()
|
|
11
|
-
export class IntegrationEventCatalogService {
|
|
12
|
-
constructor(
|
|
13
|
-
private readonly prisma: PrismaService,
|
|
14
|
-
private readonly pagination: PaginationService,
|
|
15
|
-
) {}
|
|
16
|
-
|
|
17
|
-
private get delegate() {
|
|
18
|
-
return (this.prisma as any).integration_event_catalog;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async list(paginationParams: PaginationDTO) {
|
|
22
|
-
const fields = ['slug', 'name', 'module', 'description', 'status'];
|
|
23
|
-
const OR = this.prisma.createInsensitiveSearch(fields, paginationParams);
|
|
24
|
-
|
|
25
|
-
return this.pagination.paginate(this.delegate, paginationParams, {
|
|
26
|
-
where: OR.length > 0 ? { OR } : {},
|
|
27
|
-
orderBy: [{ module: 'asc' }, { slug: 'asc' }],
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async options() {
|
|
32
|
-
return this.delegate.findMany({
|
|
33
|
-
where: { status: 'active' },
|
|
34
|
-
orderBy: [{ module: 'asc' }, { slug: 'asc' }],
|
|
35
|
-
select: {
|
|
36
|
-
id: true,
|
|
37
|
-
slug: true,
|
|
38
|
-
name: true,
|
|
39
|
-
module: true,
|
|
40
|
-
description: true,
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async get(id: number) {
|
|
46
|
-
const record = await this.delegate.findUnique({ where: { id } });
|
|
47
|
-
if (!record) {
|
|
48
|
-
throw new NotFoundException(`Event catalog item with id ${id} not found.`);
|
|
49
|
-
}
|
|
50
|
-
return record;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async create(data: any) {
|
|
54
|
-
await this.ensureSlugAvailable(data.slug);
|
|
55
|
-
return this.delegate.create({
|
|
56
|
-
data: this.normalize(data),
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async update(id: number, data: any) {
|
|
61
|
-
const existing = await this.get(id);
|
|
62
|
-
if (data.slug && data.slug !== existing.slug) {
|
|
63
|
-
await this.ensureSlugAvailable(data.slug);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return this.delegate.update({
|
|
67
|
-
where: { id },
|
|
68
|
-
data: this.normalize(data, true),
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async delete(data: DeleteDTO) {
|
|
73
|
-
if (!data.ids?.length) {
|
|
74
|
-
throw new BadRequestException('You must select at least one item to delete.');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return this.delegate.deleteMany({
|
|
78
|
-
where: { id: { in: data.ids } },
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
private async ensureSlugAvailable(slug: string) {
|
|
83
|
-
const existing = await this.delegate.findUnique({
|
|
84
|
-
where: { slug: String(slug || '').trim() },
|
|
85
|
-
select: { id: true },
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
if (existing) {
|
|
89
|
-
throw new BadRequestException(`Event "${slug}" already exists.`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private normalize(data: any, partial = false) {
|
|
94
|
-
const normalized: Record<string, any> = {};
|
|
95
|
-
const assign = (key: string, value: any) => {
|
|
96
|
-
if (!partial || value !== undefined) {
|
|
97
|
-
normalized[key] = value;
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
assign('slug', String(data.slug ?? '').trim());
|
|
102
|
-
assign('name', String(data.name ?? '').trim());
|
|
103
|
-
assign('module', String(data.module ?? '').trim());
|
|
104
|
-
assign(
|
|
105
|
-
'description',
|
|
106
|
-
data.description === undefined || data.description === null
|
|
107
|
-
? partial
|
|
108
|
-
? undefined
|
|
109
|
-
: null
|
|
110
|
-
: String(data.description).trim() || null,
|
|
111
|
-
);
|
|
112
|
-
assign('status', data.status === 'inactive' ? 'inactive' : 'active');
|
|
113
|
-
|
|
114
|
-
return normalized;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
1
|
+
import { DeleteDTO } from '@hed-hog/api';
|
|
2
|
+
import { PaginationDTO, PaginationService } from '@hed-hog/api-pagination';
|
|
3
|
+
import { PrismaService } from '@hed-hog/api-prisma';
|
|
4
|
+
import {
|
|
5
|
+
BadRequestException,
|
|
6
|
+
Injectable,
|
|
7
|
+
NotFoundException,
|
|
8
|
+
} from '@nestjs/common';
|
|
9
|
+
|
|
10
|
+
@Injectable()
|
|
11
|
+
export class IntegrationEventCatalogService {
|
|
12
|
+
constructor(
|
|
13
|
+
private readonly prisma: PrismaService,
|
|
14
|
+
private readonly pagination: PaginationService,
|
|
15
|
+
) {}
|
|
16
|
+
|
|
17
|
+
private get delegate() {
|
|
18
|
+
return (this.prisma as any).integration_event_catalog;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async list(paginationParams: PaginationDTO) {
|
|
22
|
+
const fields = ['slug', 'name', 'module', 'description', 'status'];
|
|
23
|
+
const OR = this.prisma.createInsensitiveSearch(fields, paginationParams);
|
|
24
|
+
|
|
25
|
+
return this.pagination.paginate(this.delegate, paginationParams, {
|
|
26
|
+
where: OR.length > 0 ? { OR } : {},
|
|
27
|
+
orderBy: [{ module: 'asc' }, { slug: 'asc' }],
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async options() {
|
|
32
|
+
return this.delegate.findMany({
|
|
33
|
+
where: { status: 'active' },
|
|
34
|
+
orderBy: [{ module: 'asc' }, { slug: 'asc' }],
|
|
35
|
+
select: {
|
|
36
|
+
id: true,
|
|
37
|
+
slug: true,
|
|
38
|
+
name: true,
|
|
39
|
+
module: true,
|
|
40
|
+
description: true,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async get(id: number) {
|
|
46
|
+
const record = await this.delegate.findUnique({ where: { id } });
|
|
47
|
+
if (!record) {
|
|
48
|
+
throw new NotFoundException(`Event catalog item with id ${id} not found.`);
|
|
49
|
+
}
|
|
50
|
+
return record;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async create(data: any) {
|
|
54
|
+
await this.ensureSlugAvailable(data.slug);
|
|
55
|
+
return this.delegate.create({
|
|
56
|
+
data: this.normalize(data),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async update(id: number, data: any) {
|
|
61
|
+
const existing = await this.get(id);
|
|
62
|
+
if (data.slug && data.slug !== existing.slug) {
|
|
63
|
+
await this.ensureSlugAvailable(data.slug);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return this.delegate.update({
|
|
67
|
+
where: { id },
|
|
68
|
+
data: this.normalize(data, true),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async delete(data: DeleteDTO) {
|
|
73
|
+
if (!data.ids?.length) {
|
|
74
|
+
throw new BadRequestException('You must select at least one item to delete.');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return this.delegate.deleteMany({
|
|
78
|
+
where: { id: { in: data.ids } },
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private async ensureSlugAvailable(slug: string) {
|
|
83
|
+
const existing = await this.delegate.findUnique({
|
|
84
|
+
where: { slug: String(slug || '').trim() },
|
|
85
|
+
select: { id: true },
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (existing) {
|
|
89
|
+
throw new BadRequestException(`Event "${slug}" already exists.`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private normalize(data: any, partial = false) {
|
|
94
|
+
const normalized: Record<string, any> = {};
|
|
95
|
+
const assign = (key: string, value: any) => {
|
|
96
|
+
if (!partial || value !== undefined) {
|
|
97
|
+
normalized[key] = value;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
assign('slug', String(data.slug ?? '').trim());
|
|
102
|
+
assign('name', String(data.name ?? '').trim());
|
|
103
|
+
assign('module', String(data.module ?? '').trim());
|
|
104
|
+
assign(
|
|
105
|
+
'description',
|
|
106
|
+
data.description === undefined || data.description === null
|
|
107
|
+
? partial
|
|
108
|
+
? undefined
|
|
109
|
+
: null
|
|
110
|
+
: String(data.description).trim() || null,
|
|
111
|
+
);
|
|
112
|
+
assign('status', data.status === 'inactive' ? 'inactive' : 'active');
|
|
113
|
+
|
|
114
|
+
return normalized;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
@@ -129,6 +129,14 @@ export class WebhookIntegrationController {
|
|
|
129
129
|
) {
|
|
130
130
|
return this.service.streamLogs(id, res);
|
|
131
131
|
}
|
|
132
|
+
|
|
133
|
+
@Post(':id/log/:logId/retry')
|
|
134
|
+
retryLog(
|
|
135
|
+
@Param('id', ParseIntPipe) id: number,
|
|
136
|
+
@Param('logId', ParseIntPipe) logId: number,
|
|
137
|
+
) {
|
|
138
|
+
return this.service.retryCall(id, logId);
|
|
139
|
+
}
|
|
132
140
|
}
|
|
133
141
|
|
|
134
142
|
@Public()
|
|
@@ -145,5 +153,20 @@ export class PublicWebhookController {
|
|
|
145
153
|
) {
|
|
146
154
|
return this.service.executePublic(uuid, body, headers, req);
|
|
147
155
|
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* GET variant so a webhook can be triggered by a plain clickable link (e.g.
|
|
159
|
+
* approve/reject links sent by email/WhatsApp). Query params are used as the
|
|
160
|
+
* payload for action templates (`{{body.decision}}` ← `?decision=approve`).
|
|
161
|
+
*/
|
|
162
|
+
@Get(':uuid')
|
|
163
|
+
executeGet(
|
|
164
|
+
@Param('uuid') uuid: string,
|
|
165
|
+
@Query() query: any,
|
|
166
|
+
@Headers() headers: any,
|
|
167
|
+
@Req() req: Request,
|
|
168
|
+
) {
|
|
169
|
+
return this.service.executePublic(uuid, query ?? {}, headers, req);
|
|
170
|
+
}
|
|
148
171
|
}
|
|
149
172
|
|
|
@@ -3,6 +3,7 @@ import { PaginationModule } from '@hed-hog/api-pagination';
|
|
|
3
3
|
import { PrismaModule } from '@hed-hog/api-prisma';
|
|
4
4
|
import { HttpModule } from '@nestjs/axios';
|
|
5
5
|
import { Module, forwardRef } from '@nestjs/common';
|
|
6
|
+
import { AppCommandModule } from '../app-command/app-command.module';
|
|
6
7
|
import { IntegrationModule } from '../integration/integration.module';
|
|
7
8
|
import { MailModule } from '../mail/mail.module';
|
|
8
9
|
import { McpModule } from '../mcp/mcp.module';
|
|
@@ -10,7 +11,6 @@ import { EventWebhookController } from './event-webhook.controller';
|
|
|
10
11
|
import { EventWebhookService } from './event-webhook.service';
|
|
11
12
|
import { IntegrationEventCatalogController } from './integration-event-catalog.controller';
|
|
12
13
|
import { IntegrationEventCatalogService } from './integration-event-catalog.service';
|
|
13
|
-
import { WebhookCommandRegistry } from './webhook-command.registry';
|
|
14
14
|
import {
|
|
15
15
|
PublicWebhookController,
|
|
16
16
|
WebhookIntegrationController,
|
|
@@ -26,6 +26,7 @@ import { WebhookIntegrationService } from './webhook-integration.service';
|
|
|
26
26
|
forwardRef(() => MailModule),
|
|
27
27
|
forwardRef(() => MailMainModule),
|
|
28
28
|
forwardRef(() => McpModule),
|
|
29
|
+
AppCommandModule,
|
|
29
30
|
],
|
|
30
31
|
controllers: [
|
|
31
32
|
IntegrationEventCatalogController,
|
|
@@ -35,13 +36,12 @@ import { WebhookIntegrationService } from './webhook-integration.service';
|
|
|
35
36
|
],
|
|
36
37
|
providers: [
|
|
37
38
|
IntegrationEventCatalogService,
|
|
38
|
-
WebhookCommandRegistry,
|
|
39
39
|
WebhookIntegrationService,
|
|
40
40
|
EventWebhookService,
|
|
41
41
|
],
|
|
42
42
|
exports: [
|
|
43
43
|
IntegrationEventCatalogService,
|
|
44
|
-
|
|
44
|
+
AppCommandModule,
|
|
45
45
|
WebhookIntegrationService,
|
|
46
46
|
EventWebhookService,
|
|
47
47
|
],
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
CreateWebhookActionDTO,
|
|
25
25
|
UpdateWebhookActionDTO,
|
|
26
26
|
} from './dto/webhook-action.dto';
|
|
27
|
-
import {
|
|
27
|
+
import { AppCommandRegistry } from '../app-command/app-command.registry';
|
|
28
28
|
import {
|
|
29
29
|
createPlainToken,
|
|
30
30
|
createPublicUuid,
|
|
@@ -103,7 +103,7 @@ export class WebhookIntegrationService {
|
|
|
103
103
|
private readonly mailMainService: MailMainService,
|
|
104
104
|
private readonly coreMailService: MailService,
|
|
105
105
|
private readonly settingService: SettingService,
|
|
106
|
-
private readonly commandRegistry:
|
|
106
|
+
private readonly commandRegistry: AppCommandRegistry,
|
|
107
107
|
private readonly mcpApiKeyService: McpApiKeyService,
|
|
108
108
|
) {}
|
|
109
109
|
|
|
@@ -495,7 +495,8 @@ export class WebhookIntegrationService {
|
|
|
495
495
|
pageSize,
|
|
496
496
|
prev: page > 1 ? page - 1 : null,
|
|
497
497
|
next: page < lastPage ? page + 1 : null,
|
|
498
|
-
|
|
498
|
+
// Never expose the raw replay payload (may contain secrets) to clients.
|
|
499
|
+
data: (data || []).map(({ payload_raw, ...rest }: any) => rest),
|
|
499
500
|
};
|
|
500
501
|
|
|
501
502
|
const logIds = (result.data || [])
|
|
@@ -553,7 +554,6 @@ export class WebhookIntegrationService {
|
|
|
553
554
|
async executePublic(uuid: string, body: any, headers: any, req: Request) {
|
|
554
555
|
const startedAt = Date.now();
|
|
555
556
|
const remoteIp = this.getRemoteIp(req);
|
|
556
|
-
const actionLogs: ActionExecutionLog[] = [];
|
|
557
557
|
let integration: any | null = null;
|
|
558
558
|
|
|
559
559
|
try {
|
|
@@ -575,14 +575,70 @@ export class WebhookIntegrationService {
|
|
|
575
575
|
this.validateToken(integration, headers);
|
|
576
576
|
this.validateIp(integration, remoteIp);
|
|
577
577
|
this.validateBodySchema(integration, body);
|
|
578
|
+
} catch (error) {
|
|
579
|
+
const callLog = await this.createCallLog({
|
|
580
|
+
integration,
|
|
581
|
+
uuid,
|
|
582
|
+
status: 'failed',
|
|
583
|
+
remoteIp,
|
|
584
|
+
durationMs: Date.now() - startedAt,
|
|
585
|
+
payload: body,
|
|
586
|
+
response: {
|
|
587
|
+
success: false,
|
|
588
|
+
actions: [],
|
|
589
|
+
},
|
|
590
|
+
error,
|
|
591
|
+
}).catch(() => null);
|
|
592
|
+
|
|
593
|
+
if (integration?.id && callLog?.id) {
|
|
594
|
+
this.logEmitter.emit(`log:${integration.id}`, { id: callLog.id });
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (error instanceof HttpException) {
|
|
598
|
+
throw error;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
return {
|
|
602
|
+
success: false,
|
|
603
|
+
actions: [],
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return this.runActionsAndLog({
|
|
608
|
+
integration,
|
|
609
|
+
uuid,
|
|
610
|
+
body,
|
|
611
|
+
remoteIp,
|
|
612
|
+
webhookHeaders: normalizeJsonObject(headers) || {},
|
|
613
|
+
startedAt,
|
|
614
|
+
});
|
|
615
|
+
}
|
|
578
616
|
|
|
617
|
+
/**
|
|
618
|
+
* Runs every active action of an integration against `body`, persists a new
|
|
619
|
+
* call log + action logs, and emits the SSE event. Shared by the public
|
|
620
|
+
* webhook entrypoint and by the admin-triggered retry of a failed call.
|
|
621
|
+
*/
|
|
622
|
+
private async runActionsAndLog(input: {
|
|
623
|
+
integration: any;
|
|
624
|
+
uuid: string;
|
|
625
|
+
body: any;
|
|
626
|
+
remoteIp: string | null;
|
|
627
|
+
webhookHeaders: Record<string, unknown>;
|
|
628
|
+
startedAt: number;
|
|
629
|
+
}) {
|
|
630
|
+
const { integration, uuid, body, remoteIp, webhookHeaders, startedAt } =
|
|
631
|
+
input;
|
|
632
|
+
const actionLogs: ActionExecutionLog[] = [];
|
|
633
|
+
|
|
634
|
+
try {
|
|
579
635
|
const actionResults = [];
|
|
580
636
|
for (const action of integration.webhook_action || []) {
|
|
581
637
|
const actionStartedAt = Date.now();
|
|
582
638
|
|
|
583
639
|
try {
|
|
584
640
|
const result = await this.executeAction(action, body, {
|
|
585
|
-
webhookHeaders
|
|
641
|
+
webhookHeaders,
|
|
586
642
|
remoteIp,
|
|
587
643
|
publicUuid: uuid,
|
|
588
644
|
integrationId: integration.id,
|
|
@@ -700,6 +756,56 @@ export class WebhookIntegrationService {
|
|
|
700
756
|
}
|
|
701
757
|
}
|
|
702
758
|
|
|
759
|
+
/**
|
|
760
|
+
* Replays a previously failed webhook call from the Logs tab. Re-executes the
|
|
761
|
+
* whole call (all active actions) using the original stored payload, without
|
|
762
|
+
* re-validating token/IP (the retry is triggered by an authenticated admin).
|
|
763
|
+
* Produces a brand-new call log so the retry is itself auditable.
|
|
764
|
+
*/
|
|
765
|
+
async retryCall(integrationId: number, logId: number) {
|
|
766
|
+
const log = await this.logs?.findFirst({
|
|
767
|
+
where: { id: logId, webhook_integration_id: integrationId },
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
if (!log) {
|
|
771
|
+
throw new NotFoundException('Webhook call log not found.');
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
if (log.status !== 'failed') {
|
|
775
|
+
throw new BadRequestException('Only failed webhook calls can be retried.');
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
if (log.payload_raw === null || log.payload_raw === undefined) {
|
|
779
|
+
throw new BadRequestException(
|
|
780
|
+
'This webhook call cannot be retried because its original payload was not stored.',
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
const integration = await this.integrations.findUnique({
|
|
785
|
+
where: { id: integrationId },
|
|
786
|
+
include: {
|
|
787
|
+
webhook_action: {
|
|
788
|
+
select: this.webhookActionSelect,
|
|
789
|
+
where: { status: 'active' },
|
|
790
|
+
orderBy: [{ order: 'asc' }, { id: 'asc' }],
|
|
791
|
+
},
|
|
792
|
+
},
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
if (!integration) {
|
|
796
|
+
throw new NotFoundException('Webhook integration not found.');
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
return this.runActionsAndLog({
|
|
800
|
+
integration,
|
|
801
|
+
uuid: integration.public_uuid ?? log.public_uuid,
|
|
802
|
+
body: log.payload_raw,
|
|
803
|
+
remoteIp: null,
|
|
804
|
+
webhookHeaders: {},
|
|
805
|
+
startedAt: Date.now(),
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
|
|
703
809
|
private async executeAction(
|
|
704
810
|
action: any,
|
|
705
811
|
body: any,
|
|
@@ -1300,6 +1406,10 @@ export class WebhookIntegrationService {
|
|
|
1300
1406
|
duration_ms: input.durationMs,
|
|
1301
1407
|
error_message: input.error ? this.extractErrorMessage(input.error) : null,
|
|
1302
1408
|
payload_summary: summarizePayload(sanitizeSensitiveData(input.payload)),
|
|
1409
|
+
// Store the full, unsanitized payload only for failed calls so they can
|
|
1410
|
+
// be replayed faithfully from the Logs tab. Successful calls keep just
|
|
1411
|
+
// the sanitized summary to limit secret exposure and storage.
|
|
1412
|
+
payload_raw: input.status === 'failed' ? (input.payload ?? null) : null,
|
|
1303
1413
|
response_summary: summarizePayload(sanitizeSensitiveData(input.response)),
|
|
1304
1414
|
},
|
|
1305
1415
|
select: {
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export interface WebhookCommandContext extends Record<string, unknown> {
|
|
2
|
-
webhookBody?: unknown;
|
|
3
|
-
webhookHeaders?: Record<string, unknown>;
|
|
4
|
-
remoteIp?: string | null;
|
|
5
|
-
publicUuid?: string;
|
|
6
|
-
integrationId?: number;
|
|
7
|
-
}
|
|
8
|
-
export interface WebhookCommand {
|
|
9
|
-
slug: string;
|
|
10
|
-
name: string;
|
|
11
|
-
description: string;
|
|
12
|
-
inputSchema: Record<string, unknown>;
|
|
13
|
-
handler: (params: Record<string, unknown>, context?: WebhookCommandContext) => Promise<unknown>;
|
|
14
|
-
}
|
|
15
|
-
export declare class WebhookCommandRegistry {
|
|
16
|
-
private readonly commands;
|
|
17
|
-
register(command: WebhookCommand): void;
|
|
18
|
-
find(slug: string): WebhookCommand | undefined;
|
|
19
|
-
list(): WebhookCommand[];
|
|
20
|
-
dispatch(slug: string, params: Record<string, unknown>, context?: WebhookCommandContext): Promise<unknown>;
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=webhook-command.registry.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-command.registry.d.ts","sourceRoot":"","sources":["../../src/webhook-integration/webhook-command.registry.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAsB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACpE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,EAAE,CACP,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,CAAC,EAAE,qBAAqB,KAC5B,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED,qBACa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAE9D,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIvC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI9C,IAAI,IAAI,cAAc,EAAE;IAIlB,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,OAAO,CAAC;CAQpB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-command.registry.js","sourceRoot":"","sources":["../../src/webhook-integration/webhook-command.registry.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAsBrC,IAAM,sBAAsB,GAA5B,MAAM,sBAAsB;IAA5B;QACY,aAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;IA0BhE,CAAC;IAxBC,QAAQ,CAAC,OAAuB;QAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC,IAAY;QACf,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,IAAY,EACZ,MAA+B,EAC/B,OAA+B;QAE/B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;CACF,CAAA;AA3BY,wDAAsB;iCAAtB,sBAAsB;IADlC,IAAA,mBAAU,GAAE;GACA,sBAAsB,CA2BlC"}
|