generated from xmidt-org/.go-template
-
Notifications
You must be signed in to change notification settings - Fork 2
/
webhookValidator.go
145 lines (130 loc) · 3.89 KB
/
webhookValidator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// SPDX-FileCopyrightText: 2022 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0
package ancla
import (
"errors"
"fmt"
"net/url"
"regexp"
"time"
)
var (
errZeroEvents = errors.New("cannot have zero events")
errEventsUnparseable = errors.New("event cannot be parsed")
errDeviceIDUnparseable = errors.New("deviceID cannot be parsed")
errInvalidDuration = errors.New("duration value of webhook is out of bounds")
errInvalidUntil = errors.New("until value of webhook is out of bounds")
errUntilDurationAbsent = errors.New("until and duration are both absent")
errInvalidTTL = errors.New("TTL must be non-negative")
errInvalidJitter = errors.New("jitter must be non-negative")
)
// Validator is a WebhookValidator that allows access to the Validate function.
type Validator interface {
Validate(w Webhook) error
}
// Validators is a WebhookValidator that ensures the webhook is valid with
// each validator in the list.
type Validators []Validator
// ValidatorFunc is a WebhookValidator that takes Webhooks and validates them
// against functions.
type ValidatorFunc func(Webhook) error
// ValidURLFunc takes URLs and ensures they are valid.
type ValidURLFunc func(*url.URL) error
// Validate runs the given webhook through each validator in the validators list.
// It returns as soon as the webhook is considered invalid and returns nil if the
// webhook is valid.
func (vs Validators) Validate(w Webhook) error {
for _, v := range vs {
err := v.Validate(w)
if err != nil {
return err
}
}
return nil
}
// Validate runs the function and returns the result. This allows any ValidatorFunc to implement
// the Validator interface.
func (vf ValidatorFunc) Validate(w Webhook) error {
return vf(w)
}
// AlwaysValid doesn't check anything in the webhook and never returns an error.
func AlwaysValid() ValidatorFunc {
return func(w Webhook) error {
return nil
}
}
// CheckEvents makes sure there is at least one value in Events and ensures that
// all values should parse into regex.
func CheckEvents() ValidatorFunc {
return func(w Webhook) error {
if len(w.Events) == 0 {
return errZeroEvents
}
for _, e := range w.Events {
_, err := regexp.Compile(e)
if err != nil {
return errEventsUnparseable
}
}
return nil
}
}
// CheckDeviceID ensures that the DeviceIDs are able to parse into regex.
func CheckDeviceID() ValidatorFunc {
return func(w Webhook) error {
for _, i := range w.Matcher.DeviceID {
_, err := regexp.Compile(i)
if err != nil {
return errDeviceIDUnparseable
}
}
return nil
}
}
// CheckDuration ensures that 0 <= Duration <= ttl. Duration returns an error
// if a negative value is given.
func CheckDuration(maxTTL time.Duration) (ValidatorFunc, error) {
if maxTTL < 0 {
return nil, errInvalidTTL
}
return func(w Webhook) error {
if maxTTL < w.Duration || w.Duration < 0 {
return fmt.Errorf("%w: %v not between 0 and %v",
errInvalidDuration, w.Duration, maxTTL)
}
return nil
}, nil
}
// CheckUntil ensures that Until, with jitter, is not more than ttl in the future.
func CheckUntil(jitter time.Duration, maxTTL time.Duration, now func() time.Time) (ValidatorFunc, error) {
if now == nil {
now = time.Now
}
if maxTTL < 0 {
return nil, errInvalidTTL
} else if jitter < 0 {
return nil, errInvalidJitter
}
return func(w Webhook) error {
if w.Until.IsZero() {
return nil
}
limit := (now().Add(maxTTL)).Add(jitter)
proposed := (w.Until)
if proposed.After(limit) {
return fmt.Errorf("%w: %v after %v",
errInvalidUntil, proposed.String(), limit.String())
}
return nil
}, nil
}
// CheckUntilAndDuration checks if either Until or Duration exists and returns an error
// if neither exist.
func CheckUntilOrDurationExist() ValidatorFunc {
return func(w Webhook) error {
if w.Duration == 0 && (w.Until).IsZero() {
return errUntilDurationAbsent
}
return nil
}
}