ultisuite-backend/internal/api/mail/service_webhooks.go
R3D347HR4Y 082cac36b2 feat(automation): dispatch rules/webhooks on mail, drive, contacts
Wire automation dispatcher to IMAP sync, drive mutations, and contact CRUD.
Add webhook event_types and mail/drive/contacts scope filters (migration 30).
2026-06-07 15:51:47 +02:00

93 lines
2.4 KiB
Go

package mail
import (
"context"
"encoding/json"
"errors"
"github.com/jackc/pgx/v5"
"github.com/ultisuite/ulti-backend/internal/mail/webhooks"
)
func (s *Service) UpdateWebhook(ctx context.Context, externalID, webhookID string, req *updateWebhookRequest, method string, maxRetries int) error {
headersJSON, _ := json.Marshal(req.Headers)
tx, err := s.db.Begin(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx)
var version int
eventTypesJSON, err := marshalWebhookEventTypes(req.EventTypes)
if err != nil {
return err
}
mailScopeJSON, err := marshalWebhookMailScope(req.MailScope)
if err != nil {
return err
}
driveScopeJSON, err := marshalWebhookDriveScope(req.DriveScope)
if err != nil {
return err
}
contactsScopeJSON, err := marshalWebhookContactsScope(req.ContactsScope)
if err != nil {
return err
}
err = tx.QueryRow(ctx, `
UPDATE webhook_templates
SET
name = $1,
url = $2,
method = $3,
headers = $4,
body_template = $5,
signing_secret = $6,
max_retries = $7,
event_types = $8,
mail_scope = $9,
drive_scope = $10,
contacts_scope = $11,
version = version + 1,
updated_at = NOW()
WHERE id = $12
AND user_id = (SELECT id FROM users WHERE external_id = $13)
RETURNING version
`, req.Name, req.URL, method, headersJSON, req.BodyTemplate, req.SigningSecret, maxRetries,
eventTypesJSON, mailScopeJSON, driveScopeJSON, contactsScopeJSON, webhookID, externalID).Scan(&version)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return ErrNotFound
}
return err
}
if _, err := tx.Exec(ctx, `
INSERT INTO webhook_template_versions (template_id, version, method, headers, body_template)
VALUES ($1, $2, $3, $4, $5)
`, webhookID, version, method, headersJSON, req.BodyTemplate); err != nil {
return err
}
return tx.Commit(ctx)
}
func (s *Service) PreviewWebhookTemplate(_ context.Context, _ string, req *previewWebhookRequest) (map[string]any, error) {
msgCtx := &webhooks.MessageContext{
SenderName: req.Message.SenderName,
SenderEmail: req.Message.SenderEmail,
Subject: req.Message.Subject,
BodyText: req.Message.BodyText,
BodyHTML: req.Message.BodyHTML,
Date: req.Message.Date,
Recipients: req.Message.Recipients,
HasAttachment: req.Message.HasAttachment,
MessageID: req.Message.MessageID,
}
return map[string]any{
"payload": webhooks.RenderBodyTemplate(req.BodyTemplate, msgCtx),
}, nil
}