Smail/backend/utils/validation/input.go
smail f60d3b0880
Some checks are pending
Security Checks / security (push) Waiting to run
整理前后端与测试构建目录并完善配置和安全引导
统一 frontend、backend、test、test-log 和 out 目录,更新构建、部署及测试入口;纳入配置管理兼容与首次安全引导修复;排除本机配置、密钥和测试产物。
2026-09-05 19:19:52 +08:00

93 lines
2.5 KiB
Go

package validation
import (
"errors"
"net"
"strings"
"unicode"
"unicode/utf8"
)
const (
MaxAccountBytes = 20
MaxNameRunes = 10
MaxDomainCount = 100
)
func NormalizeAccount(value string) (string, error) {
value = strings.TrimSpace(value)
if len(value) == 0 || len(value) > MaxAccountBytes {
return "", errors.New("invalid account length")
}
for index, char := range []byte(value) {
isLetter := char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z'
isDigit := char >= '0' && char <= '9'
if !isLetter && !isDigit && char != '.' && char != '_' && char != '-' {
return "", errors.New("invalid account character")
}
if (index == 0 || index == len(value)-1) && !isLetter && !isDigit {
return "", errors.New("invalid account boundary")
}
}
return value, nil
}
func NormalizeDisplayName(value string) (string, error) {
value = strings.TrimSpace(value)
if value == "" || !utf8.ValidString(value) || utf8.RuneCountInString(value) > MaxNameRunes {
return "", errors.New("invalid display name length")
}
for _, char := range value {
if unicode.IsControl(char) {
return "", errors.New("invalid display name character")
}
}
return value, nil
}
func NormalizeDomain(value string) (string, error) {
value = strings.ToLower(strings.TrimSpace(value))
value = strings.TrimSuffix(value, ".")
if value == "" || len(value) > 253 || net.ParseIP(value) != nil || strings.ContainsAny(value, ":/@\\?#") {
return "", errors.New("invalid domain")
}
labels := strings.Split(value, ".")
for _, label := range labels {
if len(label) == 0 || len(label) > 63 || label[0] == '-' || label[len(label)-1] == '-' {
return "", errors.New("invalid domain label")
}
for _, char := range []byte(label) {
isLetter := char >= 'a' && char <= 'z'
isDigit := char >= '0' && char <= '9'
if !isLetter && !isDigit && char != '-' {
return "", errors.New("invalid domain character")
}
}
}
return value, nil
}
func NormalizeDomainList(value string) ([]string, error) {
if strings.TrimSpace(value) == "" {
return nil, nil
}
parts := strings.Split(value, ",")
if len(parts) > MaxDomainCount {
return nil, errors.New("too many domains")
}
seen := make(map[string]struct{}, len(parts))
result := make([]string, 0, len(parts))
for _, part := range parts {
domain, err := NormalizeDomain(part)
if err != nil {
return nil, err
}
if _, exists := seen[domain]; exists {
continue
}
seen[domain] = struct{}{}
result = append(result, domain)
}
return result, nil
}