Files
oslstats/internal/validation/validation.go

94 lines
2.1 KiB
Go

// Package validation provides utilities for parsing and validating request data
package validation
import (
"errors"
"fmt"
"net/http"
"git.haelnorr.com/h/golib/hws"
"git.haelnorr.com/h/oslstats/internal/notify"
"git.haelnorr.com/h/oslstats/internal/throw"
"git.haelnorr.com/h/timefmt"
)
type ValidationRule struct {
Condition bool // Condition on which to fail validation
Title string // Title for warning message
Message string // Warning message
}
// Getter abstracts getting values from either form or query
type Getter interface {
Get(key string) string
AddCheck(check *ValidationRule)
String(key string) *StringField
Int(key string) *IntField
Time(key string, format *timefmt.Format) *TimeField
ValidateChecks() []*ValidationRule
Validate() bool
ValidateAndNotify(s *hws.Server, w http.ResponseWriter, r *http.Request) bool
ValidateAndError(s *hws.Server, w http.ResponseWriter, r *http.Request) bool
getChecks() []*ValidationRule
}
type Field struct {
Key string
optional bool
getter Getter
}
func newField(key string, g Getter) Field {
return Field{
Key: key,
getter: g,
}
}
func newFailedCheck(title, message string) *ValidationRule {
return &ValidationRule{
Condition: true,
Title: title,
Message: message,
}
}
func validate(g Getter) []*ValidationRule {
failed := []*ValidationRule{}
for _, check := range g.getChecks() {
if check != nil && check.Condition {
failed = append(failed, check)
}
}
return failed
}
func validateAndNotify(
s *hws.Server,
w http.ResponseWriter,
r *http.Request,
g Getter,
) bool {
failedChecks := g.ValidateChecks()
for _, check := range failedChecks {
notify.Warn(s, w, r, check.Title, check.Message, nil)
}
return len(failedChecks) == 0
}
func validateAndError(
s *hws.Server,
w http.ResponseWriter,
r *http.Request,
g Getter,
) bool {
failedChecks := g.ValidateChecks()
var err error
for _, check := range failedChecks {
err_ := fmt.Errorf("%s: %s", check.Title, check.Message)
err = errors.Join(err, err_)
}
throw.BadRequest(s, w, r, "Invalid form data", err)
return len(failedChecks) == 0
}