/
rule.go
135 lines (108 loc) · 2.49 KB
/
rule.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
package rule
import (
"bytes"
"database/sql"
"fmt"
"strconv"
"text/template"
"github.com/ItsNotGoodName/smtpbridge/internal/models"
)
func validate(r models.Rule) error {
if r.Internal && !r.InternalID.Valid {
return fmt.Errorf("internal id is empty")
}
if r.Name == "" {
return models.FieldError{Field: models.FieldName, Err: fmt.Errorf("cannot be empty")}
}
t, err := TemplateBuild(r.Expression)
if err != nil {
return models.FieldError{Field: models.FieldExpression, Err: err}
}
_, err = TemplateRun(t, models.Envelope{})
if err != nil {
return models.FieldError{Field: models.FieldExpression, Err: err}
}
return nil
}
func new(r models.DTORuleCreate) models.Rule {
return models.Rule{
Internal: false,
InternalID: sql.NullString{},
Name: r.Name,
Expression: r.Expression,
Enable: true,
}
}
func New(r models.DTORuleCreate) (models.Rule, error) {
rule := new(r)
return rule, validate(rule)
}
func NewInternal(r models.DTORuleCreate, internalID string) (models.Rule, error) {
if r.Name == "" {
r.Name = internalID
}
rule := new(r)
rule.Internal = true
rule.InternalID = sql.NullString{
String: internalID,
Valid: true,
}
return rule, validate(rule)
}
func Update(r models.Rule, req models.DTORuleUpdate) (models.Rule, error) {
if r.Internal {
if req.Name == nil && req.Expression == nil && req.Enable != nil {
r.Enable = *req.Enable
return r, validate(r)
}
return models.Rule{}, models.ErrInternalResource
}
if req.Name != nil {
r.Name = *req.Name
}
if req.Expression != nil {
r.Expression = *req.Expression
}
if req.Enable != nil {
r.Enable = *req.Enable
}
return r, validate(r)
}
func Delete(r models.Rule) error {
if r.Internal {
return models.ErrInternalResource
}
return nil
}
func TemplateBuild(expression string) (*template.Template, error) {
t := expression
if t == "" {
t = "\"true\""
}
return template.New("").Parse("{{" + t + "}}")
}
func TemplateRun(tmpl *template.Template, env models.Envelope) (bool, error) {
var buffer bytes.Buffer
err := tmpl.Execute(&buffer, env)
if err != nil {
return false, err
}
return strconv.ParseBool(buffer.String())
}
type Rule struct {
ID int64
Template *template.Template
}
func Build(r models.Rule) (Rule, error) {
tmpl, err := TemplateBuild(r.Expression)
if err != nil {
return Rule{}, err
}
return Rule{
ID: r.ID,
Template: tmpl,
}, nil
}
func (r Rule) Match(env models.Envelope) (bool, error) {
return TemplateRun(r.Template, env)
}