ultisuite-backend/internal/api/mail/service_rules_simulate.go
R3D347HR4Y 1b9a3394e2 Implement rule simulation and webhook enhancements
- Added a new endpoint for simulating rules based on sample messages, allowing users to test rule conditions and actions.
- Enhanced webhook management with versioning, preview capabilities, and improved validation for webhook requests.
- Updated service interfaces to support new functionalities, including max retries for webhooks and signing secrets.
- Implemented observability metrics for webhook retries and dead-letter tracking, improving error handling and monitoring.
- Enhanced unit tests to cover new simulation and webhook features, ensuring robust functionality and validation.
2026-05-22 17:53:51 +02:00

71 lines
1.9 KiB
Go

package mail
import (
"context"
"encoding/json"
"errors"
"github.com/jackc/pgx/v5"
"github.com/ultisuite/ulti-backend/internal/mail/rules"
)
func (s *Service) SimulateRule(ctx context.Context, externalID string, req *simulateRuleRequest) (rules.SimulationResult, error) {
conditions, actions, err := s.resolveSimulateRule(ctx, externalID, req)
if err != nil {
return rules.SimulationResult{}, err
}
msg := &rules.Message{
ID: "simulation",
From: req.Message.From,
To: req.Message.To,
Subject: req.Message.Subject,
BodyText: req.Message.BodyText,
HasAttachments: req.Message.HasAttachments,
}
engine := rules.NewEngine(s.db)
return engine.SimulateRule(ctx, conditions, actions, msg), nil
}
func (s *Service) resolveSimulateRule(ctx context.Context, externalID string, req *simulateRuleRequest) ([]rules.Condition, []rules.Action, error) {
if req.RuleID != "" {
var condJSON, actJSON []byte
err := s.db.QueryRow(ctx, `
SELECT conditions, actions
FROM mail_rules
WHERE id = $1 AND user_id = (SELECT id FROM users WHERE external_id = $2)
`, req.RuleID, externalID).Scan(&condJSON, &actJSON)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil, ErrNotFound
}
return nil, nil, err
}
return unmarshalRuleConditionsActions(condJSON, actJSON)
}
condJSON, err := json.Marshal(req.Rule.Conditions)
if err != nil {
return nil, nil, err
}
actJSON, err := json.Marshal(req.Rule.Actions)
if err != nil {
return nil, nil, err
}
return unmarshalRuleConditionsActions(condJSON, actJSON)
}
func unmarshalRuleConditionsActions(condJSON, actJSON []byte) ([]rules.Condition, []rules.Action, error) {
var conditions []rules.Condition
var actions []rules.Action
if err := json.Unmarshal(condJSON, &conditions); err != nil {
return nil, nil, err
}
if err := json.Unmarshal(actJSON, &actions); err != nil {
return nil, nil, err
}
return conditions, actions, nil
}