mirror of
https://github.com/Dvorinka/Primora.git
synced 2026-06-04 04:23:00 +00:00
initiall commit
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
package validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// SlugRegex matches valid slugs (lowercase alphanumeric with hyphens)
|
||||
SlugRegex = regexp.MustCompile(`^[a-z0-9]+(?:-[a-z0-9]+)*$`)
|
||||
|
||||
// EmailRegex matches valid email addresses
|
||||
EmailRegex = regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
|
||||
|
||||
// BucketNameRegex matches valid bucket names
|
||||
BucketNameRegex = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*[a-z0-9]$`)
|
||||
)
|
||||
|
||||
// ValidationError represents a validation error
|
||||
type ValidationError struct {
|
||||
Field string `json:"field"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Error implements the error interface
|
||||
func (ve ValidationError) Error() string {
|
||||
return fmt.Sprintf("%s: %s", ve.Field, ve.Message)
|
||||
}
|
||||
|
||||
// ValidationErrors is a collection of validation errors
|
||||
type ValidationErrors []ValidationError
|
||||
|
||||
// Error implements the error interface
|
||||
func (ve ValidationErrors) Error() string {
|
||||
if len(ve) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
var messages []string
|
||||
for _, err := range ve {
|
||||
messages = append(messages, err.Error())
|
||||
}
|
||||
return strings.Join(messages, "; ")
|
||||
}
|
||||
|
||||
// Validator provides validation functions
|
||||
type Validator struct {
|
||||
errors ValidationErrors
|
||||
}
|
||||
|
||||
// New creates a new validator
|
||||
func New() *Validator {
|
||||
return &Validator{
|
||||
errors: make(ValidationErrors, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// Required checks if a field is not empty
|
||||
func (v *Validator) Required(field, value string) *Validator {
|
||||
if strings.TrimSpace(value) == "" {
|
||||
v.errors = append(v.errors, ValidationError{
|
||||
Field: field,
|
||||
Message: "is required",
|
||||
})
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// MinLength checks if a field meets minimum length
|
||||
func (v *Validator) MinLength(field, value string, min int) *Validator {
|
||||
if len(value) < min {
|
||||
v.errors = append(v.errors, ValidationError{
|
||||
Field: field,
|
||||
Message: fmt.Sprintf("must be at least %d characters", min),
|
||||
})
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// MaxLength checks if a field doesn't exceed maximum length
|
||||
func (v *Validator) MaxLength(field, value string, max int) *Validator {
|
||||
if len(value) > max {
|
||||
v.errors = append(v.errors, ValidationError{
|
||||
Field: field,
|
||||
Message: fmt.Sprintf("must not exceed %d characters", max),
|
||||
})
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Email checks if a field is a valid email
|
||||
func (v *Validator) Email(field, value string) *Validator {
|
||||
if value != "" && !EmailRegex.MatchString(value) {
|
||||
v.errors = append(v.errors, ValidationError{
|
||||
Field: field,
|
||||
Message: "must be a valid email address",
|
||||
})
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Slug checks if a field is a valid slug
|
||||
func (v *Validator) Slug(field, value string) *Validator {
|
||||
if value != "" && !SlugRegex.MatchString(value) {
|
||||
v.errors = append(v.errors, ValidationError{
|
||||
Field: field,
|
||||
Message: "must be a valid slug (lowercase letters, numbers, and hyphens)",
|
||||
})
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// BucketName checks if a field is a valid bucket name
|
||||
func (v *Validator) BucketName(field, value string) *Validator {
|
||||
if value != "" {
|
||||
if !BucketNameRegex.MatchString(value) {
|
||||
v.errors = append(v.errors, ValidationError{
|
||||
Field: field,
|
||||
Message: "must be a valid bucket name (lowercase letters, numbers, and hyphens, cannot start or end with hyphen)",
|
||||
})
|
||||
}
|
||||
if len(value) < 3 || len(value) > 63 {
|
||||
v.errors = append(v.errors, ValidationError{
|
||||
Field: field,
|
||||
Message: "must be between 3 and 63 characters",
|
||||
})
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// OneOf checks if a field value is one of the allowed values
|
||||
func (v *Validator) OneOf(field, value string, allowed []string) *Validator {
|
||||
if value != "" {
|
||||
found := false
|
||||
for _, a := range allowed {
|
||||
if value == a {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
v.errors = append(v.errors, ValidationError{
|
||||
Field: field,
|
||||
Message: fmt.Sprintf("must be one of: %s", strings.Join(allowed, ", ")),
|
||||
})
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Custom adds a custom validation error
|
||||
func (v *Validator) Custom(field, message string) *Validator {
|
||||
v.errors = append(v.errors, ValidationError{
|
||||
Field: field,
|
||||
Message: message,
|
||||
})
|
||||
return v
|
||||
}
|
||||
|
||||
// Valid returns true if there are no validation errors
|
||||
func (v *Validator) Valid() bool {
|
||||
return len(v.errors) == 0
|
||||
}
|
||||
|
||||
// Errors returns all validation errors
|
||||
func (v *Validator) Errors() ValidationErrors {
|
||||
return v.errors
|
||||
}
|
||||
|
||||
// FirstError returns the first validation error or nil
|
||||
func (v *Validator) FirstError() error {
|
||||
if len(v.errors) > 0 {
|
||||
return v.errors[0]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user