Test Failed
Push — main ( 747a0a...19c488 )
by Igor
01:58
created

validation_test.*AccessViolation.Error   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
nop 0
1
package validation_test
2
3
import (
4
	"context"
5
	"fmt"
6
7
	"github.com/muonsoft/validation"
8
	"github.com/muonsoft/validation/it"
9
	"github.com/muonsoft/validation/validator"
10
)
11
12
var ErrModificationProhibited = validation.NewError(
13
	"modification is prohibited",
14
	"Modification of resource is prohibited.",
15
)
16
17
type AccessViolation struct {
18
	validation.Violation
19
	UserID     int
20
	Permission string
21
}
22
23
func (err *AccessViolation) Error() string {
24
	return err.Violation.Error()
25
}
26
27
type Blog struct {
28
	Name    string
29
	Entries BlogEntries
30
}
31
32
func (b Blog) Validate(ctx context.Context, validator *validation.Validator, userID int) error {
33
	return validator.Validate(
34
		ctx,
35
		validation.StringProperty("name", b.Name, it.IsNotBlank(), it.HasMaxLength(50)),
36
		validation.ValidProperty(
37
			"entries",
38
			validation.ValidatableFunc(func(ctx context.Context, validator *validation.Validator) error {
39
				// passing user id further
40
				return b.Entries.Validate(ctx, validator, userID)
41
			}),
42
		),
43
	)
44
}
45
46
type BlogEntry struct {
47
	AuthorID int
48
	Title    string
49
	Text     string
50
}
51
52
func (e BlogEntry) Validate(ctx context.Context, validator *validation.Validator, userID int) error {
53
	// creating violation with domain payload
54
	if e.AuthorID != userID {
55
		return &AccessViolation{
56
			Violation:  validator.CreateViolation(ctx, ErrModificationProhibited, ErrModificationProhibited.Message()),
57
			UserID:     userID,
58
			Permission: "edit",
59
		}
60
	}
61
62
	return validator.Validate(
63
		ctx,
64
		validation.StringProperty("title", e.Title, it.IsNotBlank(), it.HasMaxLength(100)),
65
		validation.StringProperty("text", e.Text, it.IsNotBlank(), it.HasMaxLength(10000)),
66
	)
67
}
68
69
type BlogEntries []BlogEntry
70
71
func (entries BlogEntries) Validate(ctx context.Context, validator *validation.Validator, userID int) error {
72
	violations := validation.NewViolationList()
73
74
	for i, entry := range entries {
75
		err := violations.AppendFromError(entry.Validate(ctx, validator.AtIndex(i), userID))
76
		if err != nil {
77
			return err
78
		}
79
	}
80
81
	return violations.AsError()
82
}
83
84
func ExampleValidator_ValidateIt_violationWithPayload() {
85
	blog := Blog{
86
		Name: "News blog",
87
		Entries: []BlogEntry{
88
			{
89
				AuthorID: 123,
90
				Title:    "Good weather",
91
				Text:     "Good weather is coming!",
92
			},
93
			{
94
				AuthorID: 321,
95
				Title:    "Secret entry",
96
				Text:     "This should not be edited!",
97
			},
98
		},
99
	}
100
101
	userID := 123 // user id from session
102
	err := validator.ValidateIt(
103
		context.Background(),
104
		validation.ValidatableFunc(func(ctx context.Context, validator *validation.Validator) error {
105
			return blog.Validate(ctx, validator, userID)
106
		}),
107
	)
108
109
	if violations, ok := validation.UnwrapViolationList(err); ok {
110
		violations.ForEach(func(i int, violation validation.Violation) error {
111
			fmt.Println(violation)
112
			// unwrap concrete violation from chain
113
			if accessError, ok := violation.(*AccessViolation); ok {
114
				fmt.Println("user id:", accessError.UserID)
115
				fmt.Println("permission:", accessError.Permission)
116
			}
117
			return nil
118
		})
119
	}
120
	// Output:
121
	// violation at "entries[1]": "Modification of resource is prohibited."
122
	// user id: 123
123
	// permission: edit
124
}
125