forgejo_backup/modules/validation/validatable.go
Michael Jerger f4e87c6772 enhance validateable interface (#7714)
This PR is part of https://codeberg.org/forgejo/forgejo/pulls/4767 filed by @algernon

Validateable is enhanced for less duplication.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.

### Release notes

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: zam <mirco.zachmann@meissa.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7714
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Michael Jerger <michael.jerger@meissa-gmbh.de>
Co-committed-by: Michael Jerger <michael.jerger@meissa-gmbh.de>
2025-06-02 14:13:27 +02:00

96 lines
2 KiB
Go

// Copyright 2023, 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package validation
import (
"fmt"
"reflect"
"strings"
"unicode/utf8"
"forgejo.org/modules/timeutil"
ap "github.com/go-ap/activitypub"
)
// ErrNotValid represents an validation error
type ErrNotValid struct {
Message string
}
func (err ErrNotValid) Error() string {
return fmt.Sprintf("Validation Error: %v", err.Message)
}
// IsErrNotValid checks if an error is a ErrNotValid.
func IsErrNotValid(err error) bool {
_, ok := err.(ErrNotValid)
return ok
}
type Validateable interface {
Validate() []string
}
func IsValid(v Validateable) (bool, error) {
if valdationErrors := v.Validate(); len(valdationErrors) > 0 {
typeof := reflect.TypeOf(v)
errString := strings.Join(valdationErrors, "\n")
return false, ErrNotValid{fmt.Sprint(typeof, ": ", errString)}
}
return true, nil
}
func ValidateIDExists(value ap.Item, name string) []string {
if value == nil {
return []string{fmt.Sprintf("%v should not be nil", name)}
}
return ValidateNotEmpty(value.GetID().String(), name)
}
func ValidateNotEmpty(value any, name string) []string {
isValid := true
switch v := value.(type) {
case string:
if v == "" {
isValid = false
}
case timeutil.TimeStamp:
if v.IsZero() {
isValid = false
}
case uint16:
if v == 0 {
isValid = false
}
case int64:
if v == 0 {
isValid = false
}
default:
isValid = false
}
if isValid {
return []string{}
}
return []string{fmt.Sprintf("%v should not be empty", name)}
}
func ValidateMaxLen(value string, maxLen int, name string) []string {
if utf8.RuneCountInString(value) > maxLen {
return []string{fmt.Sprintf("Value %v was longer than %v", name, maxLen)}
}
return []string{}
}
func ValidateOneOf(value any, allowed []any, name string) []string {
for _, allowedElem := range allowed {
if value == allowedElem {
return []string{}
}
}
return []string{fmt.Sprintf("Field %s contains the value %v, which is not in allowed subset %v", name, value, allowed)}
}