112 lines
3.3 KiB
Go
112 lines
3.3 KiB
Go
//go:build linux || freebsd
|
|||
|
|
|
||
|
|
package contactform
|
||
|
|
|
||
|
|
import (
|
||
|
|
"net/mail"
|
||
|
|
"strings"
|
||
|
|
"unicode/utf8"
|
||
|
|
)
|
||
|
|
|
||
|
|
// validServices is the allow-list for contact-type forms.
|
||
|
|
var validServices = map[string]bool{
|
||
|
|
"": true,
|
||
|
|
"architecture": true,
|
||
|
|
"ai": true,
|
||
|
|
"infrastructure": true,
|
||
|
|
"software": true,
|
||
|
|
"unix": true,
|
||
|
|
"other": true,
|
||
|
|
}
|
||
|
|
|
||
|
|
// MinNameRunes is the minimum allowed length of a name.
|
||
|
|
const MinNameRunes = 2
|
||
|
|
|
||
|
|
// MaxNameRunes is the maximum allowed length of a name.
|
||
|
|
const MaxNameRunes = 100
|
||
|
|
|
||
|
|
// MinMessageRunes is the minimum allowed length of a message body.
|
||
|
|
const MinMessageRunes = 10
|
||
|
|
|
||
|
|
// MaxMessageRunes is the maximum allowed length of a message body.
|
||
|
|
const MaxMessageRunes = 5000
|
||
|
|
|
||
|
|
// Validate dispatches to the correct type-specific validator.
|
||
|
|
// Supported types: contact, feedback, newsletter, generic. Default is "contact".
|
||
|
|
func Validate(r *Request, formType string) []FieldError {
|
||
|
|
switch formType {
|
||
|
|
case "newsletter":
|
||
|
|
return validateNewsletter(r)
|
||
|
|
case "feedback", "generic":
|
||
|
|
return validateGeneric(r)
|
||
|
|
default:
|
||
|
|
return validateContact(r)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func validateContact(r *Request) []FieldError {
|
||
|
|
r.Name = strings.TrimSpace(r.Name)
|
||
|
|
r.Email = strings.TrimSpace(r.Email)
|
||
|
|
r.Service = strings.TrimSpace(r.Service)
|
||
|
|
r.Message = strings.TrimSpace(r.Message)
|
||
|
|
|
||
|
|
var errs []FieldError
|
||
|
|
|
||
|
|
if n := utf8.RuneCountInString(r.Name); n < MinNameRunes {
|
||
|
|
errs = append(errs, FieldError{Field: "name", Message: "name must be at least 2 characters"})
|
||
|
|
} else if n > MaxNameRunes {
|
||
|
|
errs = append(errs, FieldError{Field: "name", Message: "name must be at most 100 characters"})
|
||
|
|
}
|
||
|
|
|
||
|
|
if _, err := mail.ParseAddress(r.Email); err != nil {
|
||
|
|
errs = append(errs, FieldError{Field: "email", Message: "email is invalid"})
|
||
|
|
}
|
||
|
|
|
||
|
|
if !validServices[r.Service] {
|
||
|
|
errs = append(errs, FieldError{Field: "service", Message: "service is not a recognised value"})
|
||
|
|
}
|
||
|
|
|
||
|
|
if n := utf8.RuneCountInString(r.Message); n < MinMessageRunes {
|
||
|
|
errs = append(errs, FieldError{Field: "message", Message: "message must be at least 10 characters"})
|
||
|
|
} else if n > MaxMessageRunes {
|
||
|
|
errs = append(errs, FieldError{Field: "message", Message: "message must be at most 5000 characters"})
|
||
|
|
}
|
||
|
|
|
||
|
|
return errs
|
||
|
|
}
|
||
|
|
|
||
|
|
func validateNewsletter(r *Request) []FieldError {
|
||
|
|
r.Email = strings.TrimSpace(r.Email)
|
||
|
|
|
||
|
|
if _, err := mail.ParseAddress(r.Email); err != nil {
|
||
|
|
return []FieldError{{Field: "email", Message: "email is invalid"}}
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func validateGeneric(r *Request) []FieldError {
|
||
|
|
r.Name = strings.TrimSpace(r.Name)
|
||
|
|
r.Email = strings.TrimSpace(r.Email)
|
||
|
|
r.Message = strings.TrimSpace(r.Message)
|
||
|
|
|
||
|
|
var errs []FieldError
|
||
|
|
|
||
|
|
if n := utf8.RuneCountInString(r.Name); n < MinNameRunes {
|
||
|
|
errs = append(errs, FieldError{Field: "name", Message: "name must be at least 2 characters"})
|
||
|
|
} else if n > MaxNameRunes {
|
||
|
|
errs = append(errs, FieldError{Field: "name", Message: "name must be at most 100 characters"})
|
||
|
|
}
|
||
|
|
|
||
|
|
if _, err := mail.ParseAddress(r.Email); err != nil {
|
||
|
|
errs = append(errs, FieldError{Field: "email", Message: "email is invalid"})
|
||
|
|
}
|
||
|
|
|
||
|
|
if n := utf8.RuneCountInString(r.Message); n < MinMessageRunes {
|
||
|
|
errs = append(errs, FieldError{Field: "message", Message: "message must be at least 10 characters"})
|
||
|
|
} else if n > MaxMessageRunes {
|
||
|
|
errs = append(errs, FieldError{Field: "message", Message: "message must be at most 5000 characters"})
|
||
|
|
}
|
||
|
|
|
||
|
|
return errs
|
||
|
|
}
|