package rule import ( "errors" "regexp" "strings" "unicode/utf8" ) var ( ErrInvalid = errors.New("规则内容不符合要求") ErrNotFound = errors.New("规则不存在") codePattern = regexp.MustCompile(`^[a-z0-9][a-z0-9_-]{1,127}$`) ) type WriteInput struct { Code string `json:"code"` Name string `json:"name"` EventType *string `json:"eventType"` MinimumSeverity string `json:"minimumSeverity"` LocationContains *string `json:"locationContains"` } func Normalize(input WriteInput, requireCode bool) (WriteInput, error) { input.Code = strings.ToLower(strings.TrimSpace(input.Code)) input.Name = strings.TrimSpace(input.Name) input.MinimumSeverity = strings.ToLower(strings.TrimSpace(input.MinimumSeverity)) if requireCode && !codePattern.MatchString(input.Code) { return WriteInput{}, ErrInvalid } if !validText(input.Name, 128) || !validSeverity(input.MinimumSeverity) { return WriteInput{}, ErrInvalid } var err error if input.EventType, err = optionalText(input.EventType, 128); err != nil { return WriteInput{}, err } if input.LocationContains, err = optionalText(input.LocationContains, 128); err != nil { return WriteInput{}, err } return input, nil } func validSeverity(value string) bool { switch value { case "low", "medium", "high", "critical": return true default: return false } } func optionalText(value *string, max int) (*string, error) { if value == nil { return nil, nil } normalized := strings.TrimSpace(*value) if normalized == "" { return nil, nil } if !validText(normalized, max) { return nil, ErrInvalid } return &normalized, nil } func validText(value string, max int) bool { return value != "" && utf8.ValidString(value) && utf8.RuneCountInString(value) <= max && !strings.ContainsAny(value, "\x00\r\n") }