mirror of
https://github.com/oarkflow/mq.git
synced 2025-09-27 04:15:52 +08:00
282 lines
7.4 KiB
Go
282 lines
7.4 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/oarkflow/mq/dag"
|
|
)
|
|
|
|
// Enhanced validation implementation
|
|
type enhancedValidation struct {
|
|
config *ValidationServiceConfig
|
|
base Validation
|
|
}
|
|
|
|
// NewEnhancedValidation creates a new enhanced validation service
|
|
func NewEnhancedValidation(config *ValidationServiceConfig) (EnhancedValidation, error) {
|
|
// Create base validation (assuming ValidationInstance is available)
|
|
if ValidationInstance == nil {
|
|
return nil, fmt.Errorf("base validation instance not available")
|
|
}
|
|
|
|
return &enhancedValidation{
|
|
config: config,
|
|
base: ValidationInstance,
|
|
}, nil
|
|
}
|
|
|
|
// Make implements the base Validation interface
|
|
func (ev *enhancedValidation) Make(ctx *fiber.Ctx, data any, rules map[string]string, options ...Option) (Validator, error) {
|
|
return ev.base.Make(ctx, data, rules, options...)
|
|
}
|
|
|
|
// AddRules implements the base Validation interface
|
|
func (ev *enhancedValidation) AddRules(rules []Rule) error {
|
|
return ev.base.AddRules(rules)
|
|
}
|
|
|
|
// Rules implements the base Validation interface
|
|
func (ev *enhancedValidation) Rules() []Rule {
|
|
return ev.base.Rules()
|
|
}
|
|
|
|
// ValidateWorkflowInput validates input using workflow validation rules
|
|
func (ev *enhancedValidation) ValidateWorkflowInput(ctx context.Context, input map[string]any, rules []*dag.WorkflowValidationRule) (ValidationResult, error) {
|
|
result := ValidationResult{
|
|
Valid: true,
|
|
Errors: make(map[string]string),
|
|
Data: input,
|
|
}
|
|
|
|
for _, rule := range rules {
|
|
if err := ev.validateField(input, rule, &result); err != nil {
|
|
return result, err
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// CreateValidationProcessor creates a validator processor from rules
|
|
func (ev *enhancedValidation) CreateValidationProcessor(rules []*dag.WorkflowValidationRule) (*dag.ValidatorProcessor, error) {
|
|
config := &dag.WorkflowNodeConfig{
|
|
ValidationType: "custom",
|
|
ValidationRules: make([]dag.WorkflowValidationRule, len(rules)),
|
|
}
|
|
|
|
// Convert pointer slice to value slice
|
|
for i, rule := range rules {
|
|
config.ValidationRules[i] = *rule
|
|
}
|
|
|
|
// Create processor factory and get validator processor
|
|
factory := dag.NewProcessorFactory()
|
|
processor, err := factory.CreateProcessor("validator", config)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create validator processor: %w", err)
|
|
}
|
|
|
|
// Type assert to ValidatorProcessor
|
|
validatorProcessor, ok := processor.(*dag.ValidatorProcessor)
|
|
if !ok {
|
|
return nil, fmt.Errorf("processor is not a ValidatorProcessor")
|
|
}
|
|
|
|
return validatorProcessor, nil
|
|
}
|
|
|
|
// Helper method to validate individual fields
|
|
func (ev *enhancedValidation) validateField(input map[string]any, rule *dag.WorkflowValidationRule, result *ValidationResult) error {
|
|
value, exists := input[rule.Field]
|
|
|
|
// Check required fields
|
|
if rule.Required && (!exists || value == nil || value == "") {
|
|
result.Valid = false
|
|
result.Errors[rule.Field] = rule.Message
|
|
if result.Errors[rule.Field] == "" {
|
|
result.Errors[rule.Field] = fmt.Sprintf("Field %s is required", rule.Field)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Skip validation if field doesn't exist and is not required
|
|
if !exists {
|
|
return nil
|
|
}
|
|
|
|
// Validate based on type
|
|
switch rule.Type {
|
|
case "string":
|
|
if err := ev.validateString(value, rule, result); err != nil {
|
|
return err
|
|
}
|
|
case "number":
|
|
if err := ev.validateNumber(value, rule, result); err != nil {
|
|
return err
|
|
}
|
|
case "email":
|
|
if err := ev.validateEmail(value, rule, result); err != nil {
|
|
return err
|
|
}
|
|
case "bool":
|
|
if err := ev.validateBool(value, rule, result); err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
// Custom validation type
|
|
if err := ev.validateCustom(value, rule, result); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ev *enhancedValidation) validateString(value any, rule *dag.WorkflowValidationRule, result *ValidationResult) error {
|
|
str, ok := value.(string)
|
|
if !ok {
|
|
result.Valid = false
|
|
result.Errors[rule.Field] = fmt.Sprintf("Field %s must be a string", rule.Field)
|
|
return nil
|
|
}
|
|
|
|
// Check length constraints
|
|
if rule.MinLength > 0 && len(str) < rule.MinLength {
|
|
result.Valid = false
|
|
result.Errors[rule.Field] = fmt.Sprintf("Field %s must be at least %d characters", rule.Field, rule.MinLength)
|
|
return nil
|
|
}
|
|
|
|
if rule.MaxLength > 0 && len(str) > rule.MaxLength {
|
|
result.Valid = false
|
|
result.Errors[rule.Field] = fmt.Sprintf("Field %s must be at most %d characters", rule.Field, rule.MaxLength)
|
|
return nil
|
|
}
|
|
|
|
// Check pattern
|
|
if rule.Pattern != "" {
|
|
// Simple pattern matching - in practice, you'd use regex
|
|
// This is a placeholder implementation
|
|
if rule.Pattern == "^[a-zA-Z\\s]+$" && !isAlphaSpace(str) {
|
|
result.Valid = false
|
|
result.Errors[rule.Field] = rule.Message
|
|
if result.Errors[rule.Field] == "" {
|
|
result.Errors[rule.Field] = fmt.Sprintf("Field %s contains invalid characters", rule.Field)
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ev *enhancedValidation) validateNumber(value any, rule *dag.WorkflowValidationRule, result *ValidationResult) error {
|
|
var num float64
|
|
var ok bool
|
|
|
|
switch v := value.(type) {
|
|
case float64:
|
|
num = v
|
|
ok = true
|
|
case int:
|
|
num = float64(v)
|
|
ok = true
|
|
case int64:
|
|
num = float64(v)
|
|
ok = true
|
|
default:
|
|
ok = false
|
|
}
|
|
|
|
if !ok {
|
|
result.Valid = false
|
|
result.Errors[rule.Field] = fmt.Sprintf("Field %s must be a number", rule.Field)
|
|
return nil
|
|
}
|
|
|
|
// Check range constraints
|
|
if rule.Min != nil && num < *rule.Min {
|
|
result.Valid = false
|
|
result.Errors[rule.Field] = fmt.Sprintf("Field %s must be at least %f", rule.Field, *rule.Min)
|
|
return nil
|
|
}
|
|
|
|
if rule.Max != nil && num > *rule.Max {
|
|
result.Valid = false
|
|
result.Errors[rule.Field] = fmt.Sprintf("Field %s must be at most %f", rule.Field, *rule.Max)
|
|
return nil
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ev *enhancedValidation) validateEmail(value any, rule *dag.WorkflowValidationRule, result *ValidationResult) error {
|
|
email, ok := value.(string)
|
|
if !ok {
|
|
result.Valid = false
|
|
result.Errors[rule.Field] = fmt.Sprintf("Field %s must be a string", rule.Field)
|
|
return nil
|
|
}
|
|
|
|
// Simple email validation - in practice, you'd use a proper email validator
|
|
if !isValidEmail(email) {
|
|
result.Valid = false
|
|
result.Errors[rule.Field] = rule.Message
|
|
if result.Errors[rule.Field] == "" {
|
|
result.Errors[rule.Field] = fmt.Sprintf("Field %s must be a valid email", rule.Field)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ev *enhancedValidation) validateBool(value any, rule *dag.WorkflowValidationRule, result *ValidationResult) error {
|
|
_, ok := value.(bool)
|
|
if !ok {
|
|
result.Valid = false
|
|
result.Errors[rule.Field] = fmt.Sprintf("Field %s must be a boolean", rule.Field)
|
|
return nil
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ev *enhancedValidation) validateCustom(value any, rule *dag.WorkflowValidationRule, result *ValidationResult) error {
|
|
// Custom validation logic - implement based on your needs
|
|
// For now, just accept any value for custom types
|
|
return nil
|
|
}
|
|
|
|
// Helper functions for validation
|
|
|
|
func isAlphaSpace(s string) bool {
|
|
for _, r := range s {
|
|
if !((r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || r == ' ') {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func isValidEmail(email string) bool {
|
|
// Very basic email validation - in practice, use a proper email validator
|
|
return len(email) > 3 &&
|
|
len(email) < 255 &&
|
|
contains(email, "@") &&
|
|
contains(email, ".") &&
|
|
email[0] != '@' &&
|
|
email[len(email)-1] != '@'
|
|
}
|
|
|
|
func contains(s, substr string) bool {
|
|
for i := 0; i <= len(s)-len(substr); i++ {
|
|
if s[i:i+len(substr)] == substr {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|