ndlvr

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 15, 2022 License: MIT Imports: 3 Imported by: 0

README

ndlvr

WIP

This package is work-in-progress and is not production ready yet.

What started as another LIVR go library turned out to be this, since I've seen how strange stuff can LIVR do. This library was created because go-livr can't do struct validation, which is like 99% of web app use case in go apps, since languages like Go, Rust, Java, Kotlin unlike JS, Python PHP tend to deserialize JSON(and other formats often) to predefined data structures rather than to language type, which can contain any data.

Features

LIVR compatibility, when no type juggling is done. LIVR will accept both JSON "2" and 2, where this library, depending on validator will use only one of these. Also all modifiers are ignored, or return error during validator compilation.

What's NDLVR?

Not-dynamic-language validation rules is set of improvements over LIVR that I've designed.

NDLVR is like LIVR but better. It:

  • Is like LIVR
  • But does no type juggling for example, in LIVR eq can change value from string to number and vice versa(!!)
  • Has better support for non-dynamic languages like go or java
  • Has no support for modification of incoming data, and thus does not remove not validated fields from data, even when it could be possible. The reason is quite simple: you can't remove struct field or java's class field, and sometimes modified value may not fit struct, so no modifications allowed. One should already sent valid data or preprocess it on it's own.
  • Makes filters like max_length do not work on numbers and FP numbers and return error if not-number is passed In general makes filters work only with types they were designed to work with. Regex on numbers does not work as well.
  • Has JOI-style builders for rules, so JSON does not have to be written by hand, which is nice.
  • Some other minor stuff
  • Has single reference implementation(go one), and all other implementations should mimic behavior of reference one, this way bugs can be found by doing fuzzing and checking if results differ.

Aside from changes above it's compatible with LIVR and for most use cases can be just used with existing LIVR rules and libraries.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MakeNDLVRError

func MakeNDLVRError(msg, code string) error

Types

type ArgumentParser

type ArgumentParser interface {
	// Parses length from argument given.
	ParseLen(ctx context.Context, arg interface{}) (sz int, err error)
	ParsePrimitiveValue(ctx context.Context, arg interface{}) (pv *value.PrimitiveValue, err error)
	ParseListValue(ctx context.Context, arg interface{}) (lv value.ListValue, err error)

	ParseRulesSource(ctx context.Context, arg interface{}) (rules RulesSource, err error)
	ParseTopRulesSource(ctx context.Context, arg interface{}) (rules TopRulesSource, err error)
}

Helper, which makes parsing incoming validation's argument simpler.

type DefaultArgumentParser

type DefaultArgumentParser struct{}

func (*DefaultArgumentParser) ParseLen

func (parser *DefaultArgumentParser) ParseLen(ctx context.Context, v interface{}) (res int, err error)

func (*DefaultArgumentParser) ParseListValue

func (parser *DefaultArgumentParser) ParseListValue(ctx context.Context, v interface{}) (lv value.ListValue, err error)

func (*DefaultArgumentParser) ParsePrimitiveValue

func (parser *DefaultArgumentParser) ParsePrimitiveValue(ctx context.Context, v interface{}) (pv *value.PrimitiveValue, err error)

func (*DefaultArgumentParser) ParseRulesSource added in v0.0.2

func (parser *DefaultArgumentParser) ParseRulesSource(ctx context.Context, arg interface{}) (rules RulesSource, err error)

func (*DefaultArgumentParser) ParseTopRulesSource added in v0.0.2

func (parser *DefaultArgumentParser) ParseTopRulesSource(ctx context.Context, arg interface{}) (rules TopRulesSource, err error)

type DefaultValidator

type DefaultValidator struct {
	Engine  Engine        // Required
	Wrapper value.Wrapper // Defaults to DefaultWrapper
}

func (*DefaultValidator) Validate

func (dv *DefaultValidator) Validate(ctx context.Context, val interface{}) (err error)

type Engine

type Engine interface {
	Validate(ctx context.Context, parentValue value.Value) (err error)
}

type ErrorBag

type ErrorBag struct {
	Errors []error
}

func (*ErrorBag) Error

func (e *ErrorBag) Error() string

func (*ErrorBag) IsEmpty

func (e *ErrorBag) IsEmpty() bool

type Options

type Options struct {
	ValidationFactory ValidationFactory
}

func (*Options) NewEngine

func (opts *Options) NewEngine(ctx context.Context, rules TopRulesSource) (v Engine, err error)

func (*Options) NewEngineWithTarget added in v0.0.2

func (opts *Options) NewEngineWithTarget(ctx context.Context, rules RulesSource, target ValidationTarget) (v Engine, err error)

This is used to compile embedded validations - validations in validations. It *should* not be used by user code, unless user is implementing custom validation.

type Parser

type Parser struct{}

Parser, which is used to parse LIVR rules into immediate representation, which can be used to construct Validations and Validators. For now it has no options.

func (*Parser) ParseInnerEntry

func (p *Parser) ParseInnerEntry(rawRule interface{}, recv RuleReceiver) (err error)

Just like ParseTopLevelRules, but disallows list. This way nested lists in rules are not allowed.

Think of: ``` ... "asdf": [ ["required"] ] // Not allowed "fdsa": [ "required", { "list_of_objects" : { ... }}] // Ok ... ```

func (*Parser) ParseTopLevelEntry

func (p *Parser) ParseTopLevelEntry(rawRule interface{}, recv RuleReceiver) (err error)

type RuleData

type RuleData struct {
	ValidationName     string
	ValidationArgument interface{}
}

type RuleParseError

type RuleParseError struct {
	Rule interface{}
}

func (*RuleParseError) Error

func (e *RuleParseError) Error() string

type RuleReceiver

type RuleReceiver = func(rd RuleData) (err error)

type RulesMap

type RulesMap map[string]interface{}

RulesMap defines type to deserialize from JSON when parsing is required.

func (RulesMap) GetRules

func (r RulesMap) GetRules(recv func(key string, value interface{}) (err error)) (err error)

type RulesSource

type RulesSource interface {
	GetRules(recv func(rawRule interface{}) (err error)) (err error)
}

Returns set of rules for single field.

type SliceRules added in v0.0.2

type SliceRules []interface{}

func (SliceRules) GetRules added in v0.0.2

func (srs SliceRules) GetRules(recv func(rawRule interface{}) (err error)) (err error)

type TopLevelRuleData added in v0.0.2

type TopLevelRuleData struct {
	FieldName string
	RuleData
}

type TopLevelRuleReceiver added in v0.0.2

type TopLevelRuleReceiver = func(rd TopLevelRuleData) (err error)

type TopRulesSource added in v0.0.2

type TopRulesSource interface {
	// Note: each key may be yielded only once.
	GetRules(recv func(fieldName string, rawRule interface{}) (err error)) (err error)
}

TopRulesSource is top-level source of rules. For each key it returns rules.

Usually, it's JSON parsed map but in future go tags probably will be supported.

type Validation

type Validation interface {
	// Note: validate MUST NOT modify value.
	Validate(ctx context.Context, parentValue value.Value) (err error)
}

Validation validates specified key, but has access to whole value, so things like checking if fields are same work.

type ValidationAsFactory

type ValidationAsFactory func(bctx ValidationBuildContext, value value.Value) (err error)

func (ValidationAsFactory) BuildValidation

func (f ValidationAsFactory) BuildValidation(bctx ValidationBuildContext) (val Validation, err error)

type ValidationBuildContext

type ValidationBuildContext struct {
	Ctx context.Context

	Options *Options
	Parser  *Parser

	OPs            value.OPs
	ArgumentParser ArgumentParser

	Data ValidationBuildData
}

type ValidationBuildData

type ValidationBuildData struct {
	Target ValidationTarget

	ValidationName string
	Argument       interface{}
}

type ValidationCreateError

type ValidationCreateError struct {
	Msg string
}

func (*ValidationCreateError) Error

func (e *ValidationCreateError) Error() string

type ValidationFactory

type ValidationFactory interface {
	BuildValidation(bctx ValidationBuildContext) (val Validation, err error)
}

func SimpleFieldValidation

func SimpleFieldValidation(
	require bool,
	inner func(bctx ValidationBuildContext, parentValue value.Value, fieldValue value.Value) (err error),
) ValidationFactory

SimpleFieldValidation, which accesses value of field passed in build data.

func WrapNamed

func WrapNamed(name string, factory ValidationFactory) ValidationFactory

Wraps specified factory, in one which verifies validaton name and returns error on mismatch.

type ValidationFactoryFunc

type ValidationFactoryFunc func(bctx ValidationBuildContext) (val Validation, err error)

func (ValidationFactoryFunc) BuildValidation

func (f ValidationFactoryFunc) BuildValidation(bctx ValidationBuildContext) (val Validation, err error)

type ValidationFactoryRegistry

type ValidationFactoryRegistry map[string]ValidationFactory

ValidationFactoryRegistry is registry of factories, which always directs same validation name to same factory.

func (ValidationFactoryRegistry) BuildValidation

func (reg ValidationFactoryRegistry) BuildValidation(bctx ValidationBuildContext) (val Validation, err error)

func (ValidationFactoryRegistry) MustPut

func (reg ValidationFactoryRegistry) MustPut(name string, valFac ValidationFactory)

MustPut puts ValidationFactory with given name. Fails if one with given name is already set. Registry must not be nil map.

func (ValidationFactoryRegistry) Set

func (reg ValidationFactoryRegistry) Set(name string, valFac ValidationFactory)

Sets ValidationFactory with given name. Overrides one if was set already. Registry must not be nil map.

type ValidationFunc

type ValidationFunc func(ctx context.Context, parentValue value.Value) (err error)

func (ValidationFunc) Validate

func (vf ValidationFunc) Validate(ctx context.Context, parentValue value.Value) (err error)

type ValidationNameMismatchError

type ValidationNameMismatchError struct {
	Name         string
	ExpectedName string
}

func (*ValidationNameMismatchError) Error

type ValidationNotSupportedError

type ValidationNotSupportedError struct {
	Name string
}

func (*ValidationNotSupportedError) Error

type ValidationTarget added in v0.0.2

type ValidationTarget struct {
	FunctionalTarget func(v value.Value, recv func(child value.Value) (err error)) (err error)
	IsOrphanValue    bool   // ignored when FunctionalTarget
	IsListValue      bool   // ignored when FunctionalTarget or IsOrphanValue is set
	FieldName        string // ignored when FunctionalTarget or IsOrphanValue or IsListValue is set
}

Defines what this validation is running on.

type Validator

type Validator interface {
	Validate(ctx context.Context, val interface{}) (err error)
}

Validator is just like engine, but operates on interface{} type instead of ndlvr's value.

Directories

Path Synopsis
internal
Package value defined Values that LIVR operate on to mimic all kinds of strange behaviour like eq changing value type.
Package value defined Values that LIVR operate on to mimic all kinds of strange behaviour like eq changing value type.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL