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
|
|
|
|