Skip to content

Commit

Permalink
Disallow user constraints from returning custom error messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmalloc committed Mar 12, 2023
1 parent 1c5fe0b commit 61cd02b
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 31 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The format is based on [Keep a Changelog], and this project adheres to

- **[BC]** Floating point variables no longer accepted `NaN`, `+Inf` or `-Inf` as valid values
- **[BC]** `variable.Register()` now directly accepts a `Registry` instead of using functional options
- **[BC]** Replaced `WithConstraintFunc()` with `WithConstraint()`

### Removed

Expand Down
24 changes: 8 additions & 16 deletions modevalidateexample_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package ferrite_test

import (
"errors"
"os"
"strings"
"time"

"github.com/dogmatiq/ferrite"
"github.com/dogmatiq/ferrite/variable"
)

func ExampleInit_validation() {
Expand Down Expand Up @@ -323,27 +321,21 @@ func ExampleInit_validationWithInvalidValues() {
os.Setenv("FERRITE_STRING", "foo bar")
ferrite.
String("FERRITE_STRING", "example string").
WithConstraintFunc(
"MUST NOT contain whitespace",
func(s string) variable.ConstraintError {
if strings.ContainsRune(s, ' ') {
return errors.New("must not contain whitespace")
}
return nil
WithConstraint(
"must not contain whitespace",
func(s string) bool {
return !strings.ContainsRune(s, ' ')
},
).
Required()

os.Setenv("FERRITE_STRING_SENSITIVE", "foo bar")
ferrite.
String("FERRITE_STRING_SENSITIVE", "example sensitive string").
WithConstraintFunc(
"MUST NOT contain whitespace",
func(s string) variable.ConstraintError {
if strings.ContainsRune(s, ' ') {
return errors.New("must not contain whitespace")
}
return nil
WithConstraint(
"must not contain whitespace",
func(s string) bool {
return !strings.ContainsRune(s, ' ')
},
).
WithSensitiveContent().
Expand Down
2 changes: 1 addition & 1 deletion numfloat.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func Float[T constraints.Float](name, desc string) *FloatBuilder[T] {
b.spec.Name(name)
b.spec.Description(desc)
b.spec.BuiltInConstraint(
"MUST be a fine number",
"must be a finite number",
func(v T) variable.ConstraintError {
v64 := float64(v)
if math.IsNaN(v64) || math.IsInf(v64, 0) {
Expand Down
11 changes: 4 additions & 7 deletions string.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,13 @@ func (b *StringBuilder[T]) WithDefault(v T) *StringBuilder[T] {
return b
}

// WithConstraintFunc adds a constraint function to the variable.
// WithConstraint adds a constraint to the variable.
//
// fn is called with the environment variable value after it is parsed. If fn
// returns an error the value is considered invalid.
//
// Care should be taken never to include the value in the error message, as it
// may contain sensitive information.
func (b *StringBuilder[T]) WithConstraintFunc(
// returns false the value is considered invalid.
func (b *StringBuilder[T]) WithConstraint(
desc string,
fn func(T) variable.ConstraintError,
fn func(T) bool,
) *StringBuilder[T] {
b.spec.UserConstraint(desc, fn)
return b
Expand Down
10 changes: 5 additions & 5 deletions stringexample_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package ferrite_test

import (
"errors"
"fmt"
"os"

"github.com/dogmatiq/ferrite"
"github.com/dogmatiq/ferrite/variable"
)

func ExampleString_required() {
Expand Down Expand Up @@ -66,10 +64,12 @@ func ExampleString_sensitive() {
os.Setenv("FERRITE_STRING", "hunter2")
ferrite.
String("FERRITE_STRING", "example sensitive string variable").
WithConstraintFunc(
WithConstraint(
"always fail",
func(s string) variable.ConstraintError {
return errors.New("always fail")
func(s string) bool {
// Force the variable to be considered invalid so that the
// variable table is rendered to the console.
return false
},
).
WithSensitiveContent().
Expand Down
14 changes: 12 additions & 2 deletions variable/specbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,21 @@ func (b *TypedSpecBuilder[T]) BuiltInConstraint(
// UserConstraint adds a user-defined constraint to the variable's value.
func (b *TypedSpecBuilder[T]) UserConstraint(
desc string,
fn func(T) ConstraintError,
fn func(T) bool,
) {
b.spec.constraints = append(
b.spec.constraints,
constraint[T]{desc, true, fn},
constraint[T]{
desc,
true,
func(v T) ConstraintError {
if fn(v) {
return nil
}

return errors.New(desc)
},
},
)
}

Expand Down

0 comments on commit 61cd02b

Please sign in to comment.