Handle decisions with varying expiry for same IP (#1262)

* Upgrade ent and add sql/modifier in codegen

* update db wrappers to sanitize LAPI

Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
This commit is contained in:
Shivam Sandbhor 2022-02-16 19:49:14 +05:30 committed by GitHub
parent d18620858e
commit e4f6cdfc14
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 1120 additions and 227 deletions

43
go.mod
View file

@ -3,7 +3,7 @@ module github.com/crowdsecurity/crowdsec
go 1.17
require (
entgo.io/ent v0.9.1
entgo.io/ent v0.10.0
github.com/AlecAivazis/survey/v2 v2.2.7
github.com/Masterminds/sprig v2.22.0+incompatible
github.com/ahmetb/dlog v0.0.0-20170105205344-4fb5f8204f26
@ -21,23 +21,23 @@ require (
github.com/docker/go-connections v0.4.0
github.com/enescakir/emoji v1.0.0
github.com/fatih/color v1.13.0
github.com/fsnotify/fsnotify v1.4.9
github.com/fsnotify/fsnotify v1.5.1
github.com/gin-gonic/gin v1.7.7
github.com/go-co-op/gocron v1.9.0
github.com/go-openapi/errors v0.20.1
github.com/go-openapi/strfmt v0.19.11
github.com/go-openapi/swag v0.19.12
github.com/go-openapi/validate v0.20.0
github.com/go-sql-driver/mysql v1.5.1-0.20200311113236-681ffa848bae
github.com/go-sql-driver/mysql v1.6.0
github.com/google/go-querystring v1.0.0
github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e
github.com/hashicorp/go-hclog v0.14.1
github.com/hashicorp/go-hclog v1.0.0
github.com/hashicorp/go-plugin v1.4.2
github.com/hashicorp/go-version v1.2.1
github.com/influxdata/go-syslog/v3 v3.0.0
github.com/jszwec/csvutil v1.5.1
github.com/lib/pq v1.10.2
github.com/mattn/go-sqlite3 v1.14.8
github.com/lib/pq v1.10.4
github.com/mattn/go-sqlite3 v1.14.10
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/nxadm/tail v1.4.6
github.com/olekukonko/tablewriter v0.0.5
@ -49,11 +49,11 @@ require (
github.com/prometheus/prom2json v1.3.0
github.com/r3labs/diff/v2 v2.14.1
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.1.3
github.com/stretchr/testify v1.7.0
github.com/spf13/cobra v1.3.0
github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce
golang.org/x/mod v0.4.2
google.golang.org/grpc v1.35.0
golang.org/x/mod v0.5.1
google.golang.org/grpc v1.42.0
google.golang.org/protobuf v1.27.1
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637
@ -62,22 +62,26 @@ require (
)
require (
ariga.io/atlas v0.3.2-0.20220120225051-c3fac7d636dd // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Microsoft/go-winio v0.4.16 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
github.com/ahmetalpbalkan/dlog v0.0.0-20170105205344-4fb5f8204f26 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/c-robinson/iplib v1.0.3 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/containerd/containerd v1.4.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-openapi/analysis v0.19.16 // indirect
github.com/go-openapi/inflect v0.19.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/loads v0.20.0 // indirect
@ -90,8 +94,9 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.5 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/hcl/v2 v2.10.0 // indirect
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.12 // indirect
@ -110,14 +115,15 @@ require (
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.10 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@ -137,14 +143,17 @@ require (
github.com/ugorji/go/codec v1.2.6 // indirect
github.com/vjeantet/grok v1.0.1 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/zclconf/go-cty v1.8.0 // indirect
go.mongodb.org/mongo-driver v1.4.4 // indirect
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/appengine v1.6.6 // indirect
google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f // indirect
golang.org/x/tools v0.1.9-0.20211216111533-8d383106f7e7 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)

444
go.sum

File diff suppressed because it is too large Load diff

View file

@ -267,7 +267,7 @@ func TestGetDecision(t *testing.T) {
router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
assert.Contains(t, w.Body.String(), "\"id\":1,\"origin\":\"test\",\"scenario\":\"crowdsecurity/test\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"}]")
assert.Contains(t, w.Body.String(), "\"id\":3,\"origin\":\"test\",\"scenario\":\"crowdsecurity/test\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"}]")
}
@ -377,7 +377,7 @@ func TestDeleteDecision(t *testing.T) {
router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
assert.Equal(t, "{\"nbDeleted\":\"1\"}", w.Body.String())
assert.Equal(t, "{\"nbDeleted\":\"3\"}", w.Body.String())
}
@ -431,6 +431,56 @@ func TestStreamDecision(t *testing.T) {
req.Header.Add("X-Api-Key", APIKey)
router.ServeHTTP(w, req)
// the decision with id=3 is only returned because it's the longest decision
assert.Equal(t, 200, w.Code)
assert.Contains(t, w.Body.String(), "\"id\":1,\"origin\":\"test\",\"scenario\":\"crowdsecurity/test\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"}]}")
assert.Contains(t, w.Body.String(), "\"id\":3,\"origin\":\"test\",\"scenario\":\"crowdsecurity/test\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"}]}")
assert.NotContains(t, w.Body.String(), "\"id\":2")
assert.NotContains(t, w.Body.String(), "\"id\":1")
assert.Contains(t, w.Body.String(), "2h")
// id=3 decision is deleted, this won't affect `deleted`, because there are decisions
// targetting same IP
req, _ = http.NewRequest("DELETE", "/v1/decisions/3", strings.NewReader(""))
AddAuthHeaders(req, loginResp)
router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
w = httptest.NewRecorder()
req, _ = http.NewRequest("GET", "/v1/decisions/stream?startup=true", strings.NewReader(""))
req.Header.Add("X-Api-Key", APIKey)
router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
// the decision with id=2 is only returned because it's the longest decision
assert.Contains(t, w.Body.String(), "\"id\":2,\"origin\":\"test\",\"scenario\":\"crowdsecurity/test\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"}]}")
assert.NotContains(t, w.Body.String(), "\"id\":3")
assert.NotContains(t, w.Body.String(), "\"id\":1")
assert.Contains(t, w.Body.String(), "1h")
assert.Contains(t, w.Body.String(), "\"deleted\":null")
// We delete another decision, yet don't receive it in stream, since there's another decision on same IP
req, _ = http.NewRequest("DELETE", "/v1/decisions/2", strings.NewReader(""))
AddAuthHeaders(req, loginResp)
router.ServeHTTP(w, req)
w = httptest.NewRecorder()
req, _ = http.NewRequest("GET", "/v1/decisions/stream", strings.NewReader(""))
req.Header.Add("X-Api-Key", APIKey)
router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
assert.Equal(t, "{\"deleted\":null,\"new\":null}", w.Body.String())
// Now all decisions for this IP are deleted, we should receive it in stream
req, _ = http.NewRequest("DELETE", "/v1/decisions/1", strings.NewReader(""))
AddAuthHeaders(req, loginResp)
router.ServeHTTP(w, req)
w = httptest.NewRecorder()
req, _ = http.NewRequest("GET", "/v1/decisions/stream", strings.NewReader(""))
req.Header.Add("X-Api-Key", APIKey)
router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
assert.NotContains(t, "\"deleted\":null", w.Body.String())
}

View file

@ -13,6 +13,24 @@
"scope": "Ip",
"value": "127.0.0.1",
"type": "ban"
},
{
"id": 2,
"duration": "2h",
"origin": "test",
"scenario": "crowdsecurity/test",
"scope": "Ip",
"value": "127.0.0.1",
"type": "ban"
},
{
"id": 3,
"duration": "3h",
"origin": "test",
"scenario": "crowdsecurity/test",
"scope": "Ip",
"value": "127.0.0.1",
"type": "ban"
}
],
"Events": [

View file

@ -7,6 +7,7 @@ import (
"strconv"
"entgo.io/ent/dialect/sql"
"github.com/crowdsecurity/crowdsec/pkg/database/ent"
"github.com/crowdsecurity/crowdsec/pkg/database/ent/decision"
"github.com/crowdsecurity/crowdsec/pkg/types"
@ -170,8 +171,35 @@ func (c *Client) QueryDecisionWithFilter(filter map[string][]string) ([]*ent.Dec
return data, nil
}
// Groups by (decision.scope, decision.type, decision.value)
func decisionGroupBy(s *sql.Selector) {
s.GroupBy(
decision.FieldScope,
decision.FieldType,
decision.FieldValue,
)
}
// Gets decisions where all (decision.scope, decision.type, decision.value) tuples are unique.
// The decision with maximum duration would be included if it's not expired.
func (c *Client) QueryAllDecisionsWithFilters(filters map[string][]string) ([]*ent.Decision, error) {
query := c.Ent.Decision.Query().Where(decision.UntilGT(time.Now().UTC()))
decisionModifier := func(s *sql.Selector) {
decisionGroupBy(s)
s.Having(
sql.And(
sql.EQ(
decision.FieldUntil,
sql.Raw(sql.Max(decision.FieldUntil)),
),
sql.GT(
decision.FieldUntil,
time.Now().UTC(),
),
),
)
}
query := c.Ent.Decision.Query().Modify(decisionModifier).Where()
query, err := BuildDecisionRequestWithFilter(query, filters)
if err != nil {
@ -188,7 +216,24 @@ func (c *Client) QueryAllDecisionsWithFilters(filters map[string][]string) ([]*e
}
func (c *Client) QueryExpiredDecisionsWithFilters(filters map[string][]string) ([]*ent.Decision, error) {
query := c.Ent.Decision.Query().Where(decision.UntilLT(time.Now().UTC()))
decisionModifier := func(s *sql.Selector) {
decisionGroupBy(s)
s.Having(
sql.And(
sql.EQ(
decision.FieldUntil,
sql.Raw(sql.Max(decision.FieldUntil)),
),
sql.LT(
decision.FieldUntil,
time.Now().UTC(),
),
),
)
}
query := c.Ent.Decision.Query().Modify(decisionModifier).Where()
query, err := BuildDecisionRequestWithFilter(query, filters)
if err != nil {
@ -204,7 +249,32 @@ func (c *Client) QueryExpiredDecisionsWithFilters(filters map[string][]string) (
}
func (c *Client) QueryExpiredDecisionsSinceWithFilters(since time.Time, filters map[string][]string) ([]*ent.Decision, error) {
query := c.Ent.Decision.Query().Where(decision.UntilLT(time.Now().UTC())).Where(decision.UntilGT(since))
decisionModifier := func(s *sql.Selector) {
decisionGroupBy(s)
s.Having(
sql.And(
sql.EQ(
decision.FieldUntil,
sql.Raw(sql.Max(decision.FieldUntil)), // It has max duration
),
sql.GT(
decision.FieldUntil, // It was active at t=since
since,
),
sql.LT(
decision.FieldUntil, // It is expired as of now
time.Now().UTC(),
),
),
)
}
// This query returns 1 decision for each (decision.scope, decision.type, decision.value)
// if all decisions for the tuple are dead. Else it gives 0 decisions.
query := c.Ent.Decision.Query().Modify(
decisionModifier,
).Where()
query, err := BuildDecisionRequestWithFilter(query, filters)
if err != nil {
c.Log.Warningf("QueryExpiredDecisionsSinceWithFilters : %s", err)
@ -221,7 +291,26 @@ func (c *Client) QueryExpiredDecisionsSinceWithFilters(since time.Time, filters
}
func (c *Client) QueryNewDecisionsSinceWithFilters(since time.Time, filters map[string][]string) ([]*ent.Decision, error) {
query := c.Ent.Decision.Query().Where(decision.CreatedAtGT(since)).Where(decision.UntilGT(time.Now().UTC()))
decisionModifier := func(s *sql.Selector) {
decisionGroupBy(s)
s.Having(
sql.And(
sql.EQ(
decision.FieldUntil,
sql.Raw(sql.Max(decision.FieldUntil)),
),
sql.GT(
decision.FieldCreatedAt,
since,
),
sql.GT(
decision.FieldUntil,
time.Now().UTC(),
),
),
)
}
query := c.Ent.Decision.Query().Modify(decisionModifier).Where()
query, err := BuildDecisionRequestWithFilter(query, filters)
if err != nil {
c.Log.Warningf("QueryNewDecisionsSinceWithFilters : %s", err)

View file

@ -496,10 +496,10 @@ func (ac *AlertCreate) defaults() {
// check runs all checks and user-defined validators on the builder.
func (ac *AlertCreate) check() error {
if _, ok := ac.mutation.Scenario(); !ok {
return &ValidationError{Name: "scenario", err: errors.New(`ent: missing required field "scenario"`)}
return &ValidationError{Name: "scenario", err: errors.New(`ent: missing required field "Alert.scenario"`)}
}
if _, ok := ac.mutation.Simulated(); !ok {
return &ValidationError{Name: "simulated", err: errors.New(`ent: missing required field "simulated"`)}
return &ValidationError{Name: "simulated", err: errors.New(`ent: missing required field "Alert.simulated"`)}
}
return nil
}

View file

@ -35,6 +35,7 @@ type AlertQuery struct {
withEvents *EventQuery
withMetas *MetaQuery
withFKs bool
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@ -486,6 +487,9 @@ func (aq *AlertQuery) sqlAll(ctx context.Context) ([]*Alert, error) {
node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values)
}
if len(aq.modifiers) > 0 {
_spec.Modifiers = aq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, aq.driver, _spec); err != nil {
return nil, err
}
@ -614,6 +618,13 @@ func (aq *AlertQuery) sqlAll(ctx context.Context) ([]*Alert, error) {
func (aq *AlertQuery) sqlCount(ctx context.Context) (int, error) {
_spec := aq.querySpec()
if len(aq.modifiers) > 0 {
_spec.Modifiers = aq.modifiers
}
_spec.Node.Columns = aq.fields
if len(aq.fields) > 0 {
_spec.Unique = aq.unique != nil && *aq.unique
}
return sqlgraph.CountNodes(ctx, aq.driver, _spec)
}
@ -685,6 +696,12 @@ func (aq *AlertQuery) sqlQuery(ctx context.Context) *sql.Selector {
selector = aq.sql
selector.Select(selector.Columns(columns...)...)
}
if aq.unique != nil && *aq.unique {
selector.Distinct()
}
for _, m := range aq.modifiers {
m(selector)
}
for _, p := range aq.predicates {
p(selector)
}
@ -702,6 +719,12 @@ func (aq *AlertQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector
}
// Modify adds a query modifier for attaching custom logic to queries.
func (aq *AlertQuery) Modify(modifiers ...func(s *sql.Selector)) *AlertSelect {
aq.modifiers = append(aq.modifiers, modifiers...)
return aq.Select()
}
// AlertGroupBy is the group-by builder for Alert entities.
type AlertGroupBy struct {
config
@ -963,9 +986,7 @@ func (agb *AlertGroupBy) sqlQuery() *sql.Selector {
for _, f := range agb.fields {
columns = append(columns, selector.C(f))
}
for _, c := range aggregation {
columns = append(columns, c)
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
return selector.GroupBy(selector.Columns(agb.fields...)...)
@ -1191,3 +1212,9 @@ func (as *AlertSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// Modify adds a query modifier for attaching custom logic to queries.
func (as *AlertSelect) Modify(modifiers ...func(s *sql.Selector)) *AlertSelect {
as.modifiers = append(as.modifiers, modifiers...)
return as
}

View file

@ -4,6 +4,7 @@ package ent
import (
"context"
"errors"
"fmt"
"time"
@ -1861,7 +1862,7 @@ func (auo *AlertUpdateOne) sqlSave(ctx context.Context) (_node *Alert, err error
}
id, ok := auo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "ID", err: fmt.Errorf("missing Alert.ID for update")}
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Alert.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := auo.fields; len(fields) > 0 {

View file

@ -232,16 +232,16 @@ func (bc *BouncerCreate) defaults() {
// check runs all checks and user-defined validators on the builder.
func (bc *BouncerCreate) check() error {
if _, ok := bc.mutation.Name(); !ok {
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "name"`)}
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Bouncer.name"`)}
}
if _, ok := bc.mutation.APIKey(); !ok {
return &ValidationError{Name: "api_key", err: errors.New(`ent: missing required field "api_key"`)}
return &ValidationError{Name: "api_key", err: errors.New(`ent: missing required field "Bouncer.api_key"`)}
}
if _, ok := bc.mutation.Revoked(); !ok {
return &ValidationError{Name: "revoked", err: errors.New(`ent: missing required field "revoked"`)}
return &ValidationError{Name: "revoked", err: errors.New(`ent: missing required field "Bouncer.revoked"`)}
}
if _, ok := bc.mutation.LastPull(); !ok {
return &ValidationError{Name: "last_pull", err: errors.New(`ent: missing required field "last_pull"`)}
return &ValidationError{Name: "last_pull", err: errors.New(`ent: missing required field "Bouncer.last_pull"`)}
}
return nil
}

View file

@ -24,6 +24,7 @@ type BouncerQuery struct {
order []OrderFunc
fields []string
predicates []predicate.Bouncer
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@ -325,6 +326,9 @@ func (bq *BouncerQuery) sqlAll(ctx context.Context) ([]*Bouncer, error) {
node := nodes[len(nodes)-1]
return node.assignValues(columns, values)
}
if len(bq.modifiers) > 0 {
_spec.Modifiers = bq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, bq.driver, _spec); err != nil {
return nil, err
}
@ -336,6 +340,13 @@ func (bq *BouncerQuery) sqlAll(ctx context.Context) ([]*Bouncer, error) {
func (bq *BouncerQuery) sqlCount(ctx context.Context) (int, error) {
_spec := bq.querySpec()
if len(bq.modifiers) > 0 {
_spec.Modifiers = bq.modifiers
}
_spec.Node.Columns = bq.fields
if len(bq.fields) > 0 {
_spec.Unique = bq.unique != nil && *bq.unique
}
return sqlgraph.CountNodes(ctx, bq.driver, _spec)
}
@ -407,6 +418,12 @@ func (bq *BouncerQuery) sqlQuery(ctx context.Context) *sql.Selector {
selector = bq.sql
selector.Select(selector.Columns(columns...)...)
}
if bq.unique != nil && *bq.unique {
selector.Distinct()
}
for _, m := range bq.modifiers {
m(selector)
}
for _, p := range bq.predicates {
p(selector)
}
@ -424,6 +441,12 @@ func (bq *BouncerQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector
}
// Modify adds a query modifier for attaching custom logic to queries.
func (bq *BouncerQuery) Modify(modifiers ...func(s *sql.Selector)) *BouncerSelect {
bq.modifiers = append(bq.modifiers, modifiers...)
return bq.Select()
}
// BouncerGroupBy is the group-by builder for Bouncer entities.
type BouncerGroupBy struct {
config
@ -685,9 +708,7 @@ func (bgb *BouncerGroupBy) sqlQuery() *sql.Selector {
for _, f := range bgb.fields {
columns = append(columns, selector.C(f))
}
for _, c := range aggregation {
columns = append(columns, c)
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
return selector.GroupBy(selector.Columns(bgb.fields...)...)
@ -913,3 +934,9 @@ func (bs *BouncerSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// Modify adds a query modifier for attaching custom logic to queries.
func (bs *BouncerSelect) Modify(modifiers ...func(s *sql.Selector)) *BouncerSelect {
bs.modifiers = append(bs.modifiers, modifiers...)
return bs
}

View file

@ -4,6 +4,7 @@ package ent
import (
"context"
"errors"
"fmt"
"time"
@ -606,7 +607,7 @@ func (buo *BouncerUpdateOne) sqlSave(ctx context.Context) (_node *Bouncer, err e
}
id, ok := buo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "ID", err: fmt.Errorf("missing Bouncer.ID for update")}
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Bouncer.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := buo.fields; len(fields) > 0 {

View file

@ -113,6 +113,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
cfg := c.config
cfg.driver = &txDriver{tx: tx, drv: c.driver}
return &Tx{
ctx: ctx,
config: cfg,
Alert: NewAlertClient(cfg),
Bouncer: NewBouncerClient(cfg),

View file

@ -276,25 +276,25 @@ func (dc *DecisionCreate) defaults() {
// check runs all checks and user-defined validators on the builder.
func (dc *DecisionCreate) check() error {
if _, ok := dc.mutation.Until(); !ok {
return &ValidationError{Name: "until", err: errors.New(`ent: missing required field "until"`)}
return &ValidationError{Name: "until", err: errors.New(`ent: missing required field "Decision.until"`)}
}
if _, ok := dc.mutation.Scenario(); !ok {
return &ValidationError{Name: "scenario", err: errors.New(`ent: missing required field "scenario"`)}
return &ValidationError{Name: "scenario", err: errors.New(`ent: missing required field "Decision.scenario"`)}
}
if _, ok := dc.mutation.GetType(); !ok {
return &ValidationError{Name: "type", err: errors.New(`ent: missing required field "type"`)}
return &ValidationError{Name: "type", err: errors.New(`ent: missing required field "Decision.type"`)}
}
if _, ok := dc.mutation.Scope(); !ok {
return &ValidationError{Name: "scope", err: errors.New(`ent: missing required field "scope"`)}
return &ValidationError{Name: "scope", err: errors.New(`ent: missing required field "Decision.scope"`)}
}
if _, ok := dc.mutation.Value(); !ok {
return &ValidationError{Name: "value", err: errors.New(`ent: missing required field "value"`)}
return &ValidationError{Name: "value", err: errors.New(`ent: missing required field "Decision.value"`)}
}
if _, ok := dc.mutation.Origin(); !ok {
return &ValidationError{Name: "origin", err: errors.New(`ent: missing required field "origin"`)}
return &ValidationError{Name: "origin", err: errors.New(`ent: missing required field "Decision.origin"`)}
}
if _, ok := dc.mutation.Simulated(); !ok {
return &ValidationError{Name: "simulated", err: errors.New(`ent: missing required field "simulated"`)}
return &ValidationError{Name: "simulated", err: errors.New(`ent: missing required field "Decision.simulated"`)}
}
return nil
}

View file

@ -28,6 +28,7 @@ type DecisionQuery struct {
// eager-loading edges.
withOwner *AlertQuery
withFKs bool
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@ -374,6 +375,9 @@ func (dq *DecisionQuery) sqlAll(ctx context.Context) ([]*Decision, error) {
node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values)
}
if len(dq.modifiers) > 0 {
_spec.Modifiers = dq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, dq.driver, _spec); err != nil {
return nil, err
}
@ -415,6 +419,13 @@ func (dq *DecisionQuery) sqlAll(ctx context.Context) ([]*Decision, error) {
func (dq *DecisionQuery) sqlCount(ctx context.Context) (int, error) {
_spec := dq.querySpec()
if len(dq.modifiers) > 0 {
_spec.Modifiers = dq.modifiers
}
_spec.Node.Columns = dq.fields
if len(dq.fields) > 0 {
_spec.Unique = dq.unique != nil && *dq.unique
}
return sqlgraph.CountNodes(ctx, dq.driver, _spec)
}
@ -486,6 +497,12 @@ func (dq *DecisionQuery) sqlQuery(ctx context.Context) *sql.Selector {
selector = dq.sql
selector.Select(selector.Columns(columns...)...)
}
if dq.unique != nil && *dq.unique {
selector.Distinct()
}
for _, m := range dq.modifiers {
m(selector)
}
for _, p := range dq.predicates {
p(selector)
}
@ -503,6 +520,12 @@ func (dq *DecisionQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector
}
// Modify adds a query modifier for attaching custom logic to queries.
func (dq *DecisionQuery) Modify(modifiers ...func(s *sql.Selector)) *DecisionSelect {
dq.modifiers = append(dq.modifiers, modifiers...)
return dq.Select()
}
// DecisionGroupBy is the group-by builder for Decision entities.
type DecisionGroupBy struct {
config
@ -764,9 +787,7 @@ func (dgb *DecisionGroupBy) sqlQuery() *sql.Selector {
for _, f := range dgb.fields {
columns = append(columns, selector.C(f))
}
for _, c := range aggregation {
columns = append(columns, c)
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
return selector.GroupBy(selector.Columns(dgb.fields...)...)
@ -992,3 +1013,9 @@ func (ds *DecisionSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// Modify adds a query modifier for attaching custom logic to queries.
func (ds *DecisionSelect) Modify(modifiers ...func(s *sql.Selector)) *DecisionSelect {
ds.modifiers = append(ds.modifiers, modifiers...)
return ds
}

View file

@ -4,6 +4,7 @@ package ent
import (
"context"
"errors"
"fmt"
"time"
@ -907,7 +908,7 @@ func (duo *DecisionUpdateOne) sqlSave(ctx context.Context) (_node *Decision, err
}
id, ok := duo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "ID", err: fmt.Errorf("missing Decision.ID for update")}
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Decision.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := duo.fields; len(fields) > 0 {

View file

@ -151,7 +151,7 @@ func Sum(field string) AggregateFunc {
}
}
// ValidationError returns when validating a field fails.
// ValidationError returns when validating a field or edge fails.
type ValidationError struct {
Name string // Field or edge name.
err error

View file

@ -164,14 +164,14 @@ func (ec *EventCreate) defaults() {
// check runs all checks and user-defined validators on the builder.
func (ec *EventCreate) check() error {
if _, ok := ec.mutation.Time(); !ok {
return &ValidationError{Name: "time", err: errors.New(`ent: missing required field "time"`)}
return &ValidationError{Name: "time", err: errors.New(`ent: missing required field "Event.time"`)}
}
if _, ok := ec.mutation.Serialized(); !ok {
return &ValidationError{Name: "serialized", err: errors.New(`ent: missing required field "serialized"`)}
return &ValidationError{Name: "serialized", err: errors.New(`ent: missing required field "Event.serialized"`)}
}
if v, ok := ec.mutation.Serialized(); ok {
if err := event.SerializedValidator(v); err != nil {
return &ValidationError{Name: "serialized", err: fmt.Errorf(`ent: validator failed for field "serialized": %w`, err)}
return &ValidationError{Name: "serialized", err: fmt.Errorf(`ent: validator failed for field "Event.serialized": %w`, err)}
}
}
return nil

View file

@ -28,6 +28,7 @@ type EventQuery struct {
// eager-loading edges.
withOwner *AlertQuery
withFKs bool
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@ -374,6 +375,9 @@ func (eq *EventQuery) sqlAll(ctx context.Context) ([]*Event, error) {
node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values)
}
if len(eq.modifiers) > 0 {
_spec.Modifiers = eq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, eq.driver, _spec); err != nil {
return nil, err
}
@ -415,6 +419,13 @@ func (eq *EventQuery) sqlAll(ctx context.Context) ([]*Event, error) {
func (eq *EventQuery) sqlCount(ctx context.Context) (int, error) {
_spec := eq.querySpec()
if len(eq.modifiers) > 0 {
_spec.Modifiers = eq.modifiers
}
_spec.Node.Columns = eq.fields
if len(eq.fields) > 0 {
_spec.Unique = eq.unique != nil && *eq.unique
}
return sqlgraph.CountNodes(ctx, eq.driver, _spec)
}
@ -486,6 +497,12 @@ func (eq *EventQuery) sqlQuery(ctx context.Context) *sql.Selector {
selector = eq.sql
selector.Select(selector.Columns(columns...)...)
}
if eq.unique != nil && *eq.unique {
selector.Distinct()
}
for _, m := range eq.modifiers {
m(selector)
}
for _, p := range eq.predicates {
p(selector)
}
@ -503,6 +520,12 @@ func (eq *EventQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector
}
// Modify adds a query modifier for attaching custom logic to queries.
func (eq *EventQuery) Modify(modifiers ...func(s *sql.Selector)) *EventSelect {
eq.modifiers = append(eq.modifiers, modifiers...)
return eq.Select()
}
// EventGroupBy is the group-by builder for Event entities.
type EventGroupBy struct {
config
@ -764,9 +787,7 @@ func (egb *EventGroupBy) sqlQuery() *sql.Selector {
for _, f := range egb.fields {
columns = append(columns, selector.C(f))
}
for _, c := range aggregation {
columns = append(columns, c)
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
return selector.GroupBy(selector.Columns(egb.fields...)...)
@ -992,3 +1013,9 @@ func (es *EventSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// Modify adds a query modifier for attaching custom logic to queries.
func (es *EventSelect) Modify(modifiers ...func(s *sql.Selector)) *EventSelect {
es.modifiers = append(es.modifiers, modifiers...)
return es
}

View file

@ -4,6 +4,7 @@ package ent
import (
"context"
"errors"
"fmt"
"time"
@ -171,7 +172,7 @@ func (eu *EventUpdate) defaults() {
func (eu *EventUpdate) check() error {
if v, ok := eu.mutation.Serialized(); ok {
if err := event.SerializedValidator(v); err != nil {
return &ValidationError{Name: "serialized", err: fmt.Errorf("ent: validator failed for field \"serialized\": %w", err)}
return &ValidationError{Name: "serialized", err: fmt.Errorf(`ent: validator failed for field "Event.serialized": %w`, err)}
}
}
return nil
@ -439,7 +440,7 @@ func (euo *EventUpdateOne) defaults() {
func (euo *EventUpdateOne) check() error {
if v, ok := euo.mutation.Serialized(); ok {
if err := event.SerializedValidator(v); err != nil {
return &ValidationError{Name: "serialized", err: fmt.Errorf("ent: validator failed for field \"serialized\": %w", err)}
return &ValidationError{Name: "serialized", err: fmt.Errorf(`ent: validator failed for field "Event.serialized": %w`, err)}
}
}
return nil
@ -458,7 +459,7 @@ func (euo *EventUpdateOne) sqlSave(ctx context.Context) (_node *Event, err error
}
id, ok := euo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "ID", err: fmt.Errorf("missing Event.ID for update")}
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Event.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := euo.fields; len(fields) > 0 {

View file

@ -244,21 +244,21 @@ func (mc *MachineCreate) defaults() {
// check runs all checks and user-defined validators on the builder.
func (mc *MachineCreate) check() error {
if _, ok := mc.mutation.MachineId(); !ok {
return &ValidationError{Name: "machineId", err: errors.New(`ent: missing required field "machineId"`)}
return &ValidationError{Name: "machineId", err: errors.New(`ent: missing required field "Machine.machineId"`)}
}
if _, ok := mc.mutation.Password(); !ok {
return &ValidationError{Name: "password", err: errors.New(`ent: missing required field "password"`)}
return &ValidationError{Name: "password", err: errors.New(`ent: missing required field "Machine.password"`)}
}
if _, ok := mc.mutation.IpAddress(); !ok {
return &ValidationError{Name: "ipAddress", err: errors.New(`ent: missing required field "ipAddress"`)}
return &ValidationError{Name: "ipAddress", err: errors.New(`ent: missing required field "Machine.ipAddress"`)}
}
if v, ok := mc.mutation.Scenarios(); ok {
if err := machine.ScenariosValidator(v); err != nil {
return &ValidationError{Name: "scenarios", err: fmt.Errorf(`ent: validator failed for field "scenarios": %w`, err)}
return &ValidationError{Name: "scenarios", err: fmt.Errorf(`ent: validator failed for field "Machine.scenarios": %w`, err)}
}
}
if _, ok := mc.mutation.IsValidated(); !ok {
return &ValidationError{Name: "isValidated", err: errors.New(`ent: missing required field "isValidated"`)}
return &ValidationError{Name: "isValidated", err: errors.New(`ent: missing required field "Machine.isValidated"`)}
}
return nil
}

View file

@ -28,6 +28,7 @@ type MachineQuery struct {
predicates []predicate.Machine
// eager-loading edges.
withAlerts *AlertQuery
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@ -367,6 +368,9 @@ func (mq *MachineQuery) sqlAll(ctx context.Context) ([]*Machine, error) {
node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values)
}
if len(mq.modifiers) > 0 {
_spec.Modifiers = mq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, mq.driver, _spec); err != nil {
return nil, err
}
@ -408,6 +412,13 @@ func (mq *MachineQuery) sqlAll(ctx context.Context) ([]*Machine, error) {
func (mq *MachineQuery) sqlCount(ctx context.Context) (int, error) {
_spec := mq.querySpec()
if len(mq.modifiers) > 0 {
_spec.Modifiers = mq.modifiers
}
_spec.Node.Columns = mq.fields
if len(mq.fields) > 0 {
_spec.Unique = mq.unique != nil && *mq.unique
}
return sqlgraph.CountNodes(ctx, mq.driver, _spec)
}
@ -479,6 +490,12 @@ func (mq *MachineQuery) sqlQuery(ctx context.Context) *sql.Selector {
selector = mq.sql
selector.Select(selector.Columns(columns...)...)
}
if mq.unique != nil && *mq.unique {
selector.Distinct()
}
for _, m := range mq.modifiers {
m(selector)
}
for _, p := range mq.predicates {
p(selector)
}
@ -496,6 +513,12 @@ func (mq *MachineQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector
}
// Modify adds a query modifier for attaching custom logic to queries.
func (mq *MachineQuery) Modify(modifiers ...func(s *sql.Selector)) *MachineSelect {
mq.modifiers = append(mq.modifiers, modifiers...)
return mq.Select()
}
// MachineGroupBy is the group-by builder for Machine entities.
type MachineGroupBy struct {
config
@ -757,9 +780,7 @@ func (mgb *MachineGroupBy) sqlQuery() *sql.Selector {
for _, f := range mgb.fields {
columns = append(columns, selector.C(f))
}
for _, c := range aggregation {
columns = append(columns, c)
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
return selector.GroupBy(selector.Columns(mgb.fields...)...)
@ -985,3 +1006,9 @@ func (ms *MachineSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// Modify adds a query modifier for attaching custom logic to queries.
func (ms *MachineSelect) Modify(modifiers ...func(s *sql.Selector)) *MachineSelect {
ms.modifiers = append(ms.modifiers, modifiers...)
return ms
}

View file

@ -4,6 +4,7 @@ package ent
import (
"context"
"errors"
"fmt"
"time"
@ -278,7 +279,7 @@ func (mu *MachineUpdate) defaults() {
func (mu *MachineUpdate) check() error {
if v, ok := mu.mutation.Scenarios(); ok {
if err := machine.ScenariosValidator(v); err != nil {
return &ValidationError{Name: "scenarios", err: fmt.Errorf("ent: validator failed for field \"scenarios\": %w", err)}
return &ValidationError{Name: "scenarios", err: fmt.Errorf(`ent: validator failed for field "Machine.scenarios": %w`, err)}
}
}
return nil
@ -738,7 +739,7 @@ func (muo *MachineUpdateOne) defaults() {
func (muo *MachineUpdateOne) check() error {
if v, ok := muo.mutation.Scenarios(); ok {
if err := machine.ScenariosValidator(v); err != nil {
return &ValidationError{Name: "scenarios", err: fmt.Errorf("ent: validator failed for field \"scenarios\": %w", err)}
return &ValidationError{Name: "scenarios", err: fmt.Errorf(`ent: validator failed for field "Machine.scenarios": %w`, err)}
}
}
return nil
@ -757,7 +758,7 @@ func (muo *MachineUpdateOne) sqlSave(ctx context.Context) (_node *Machine, err e
}
id, ok := muo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "ID", err: fmt.Errorf("missing Machine.ID for update")}
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Machine.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := muo.fields; len(fields) > 0 {

View file

@ -164,14 +164,14 @@ func (mc *MetaCreate) defaults() {
// check runs all checks and user-defined validators on the builder.
func (mc *MetaCreate) check() error {
if _, ok := mc.mutation.Key(); !ok {
return &ValidationError{Name: "key", err: errors.New(`ent: missing required field "key"`)}
return &ValidationError{Name: "key", err: errors.New(`ent: missing required field "Meta.key"`)}
}
if _, ok := mc.mutation.Value(); !ok {
return &ValidationError{Name: "value", err: errors.New(`ent: missing required field "value"`)}
return &ValidationError{Name: "value", err: errors.New(`ent: missing required field "Meta.value"`)}
}
if v, ok := mc.mutation.Value(); ok {
if err := meta.ValueValidator(v); err != nil {
return &ValidationError{Name: "value", err: fmt.Errorf(`ent: validator failed for field "value": %w`, err)}
return &ValidationError{Name: "value", err: fmt.Errorf(`ent: validator failed for field "Meta.value": %w`, err)}
}
}
return nil

View file

@ -28,6 +28,7 @@ type MetaQuery struct {
// eager-loading edges.
withOwner *AlertQuery
withFKs bool
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@ -374,6 +375,9 @@ func (mq *MetaQuery) sqlAll(ctx context.Context) ([]*Meta, error) {
node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values)
}
if len(mq.modifiers) > 0 {
_spec.Modifiers = mq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, mq.driver, _spec); err != nil {
return nil, err
}
@ -415,6 +419,13 @@ func (mq *MetaQuery) sqlAll(ctx context.Context) ([]*Meta, error) {
func (mq *MetaQuery) sqlCount(ctx context.Context) (int, error) {
_spec := mq.querySpec()
if len(mq.modifiers) > 0 {
_spec.Modifiers = mq.modifiers
}
_spec.Node.Columns = mq.fields
if len(mq.fields) > 0 {
_spec.Unique = mq.unique != nil && *mq.unique
}
return sqlgraph.CountNodes(ctx, mq.driver, _spec)
}
@ -486,6 +497,12 @@ func (mq *MetaQuery) sqlQuery(ctx context.Context) *sql.Selector {
selector = mq.sql
selector.Select(selector.Columns(columns...)...)
}
if mq.unique != nil && *mq.unique {
selector.Distinct()
}
for _, m := range mq.modifiers {
m(selector)
}
for _, p := range mq.predicates {
p(selector)
}
@ -503,6 +520,12 @@ func (mq *MetaQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector
}
// Modify adds a query modifier for attaching custom logic to queries.
func (mq *MetaQuery) Modify(modifiers ...func(s *sql.Selector)) *MetaSelect {
mq.modifiers = append(mq.modifiers, modifiers...)
return mq.Select()
}
// MetaGroupBy is the group-by builder for Meta entities.
type MetaGroupBy struct {
config
@ -764,9 +787,7 @@ func (mgb *MetaGroupBy) sqlQuery() *sql.Selector {
for _, f := range mgb.fields {
columns = append(columns, selector.C(f))
}
for _, c := range aggregation {
columns = append(columns, c)
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
return selector.GroupBy(selector.Columns(mgb.fields...)...)
@ -992,3 +1013,9 @@ func (ms *MetaSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// Modify adds a query modifier for attaching custom logic to queries.
func (ms *MetaSelect) Modify(modifiers ...func(s *sql.Selector)) *MetaSelect {
ms.modifiers = append(ms.modifiers, modifiers...)
return ms
}

View file

@ -4,6 +4,7 @@ package ent
import (
"context"
"errors"
"fmt"
"time"
@ -171,7 +172,7 @@ func (mu *MetaUpdate) defaults() {
func (mu *MetaUpdate) check() error {
if v, ok := mu.mutation.Value(); ok {
if err := meta.ValueValidator(v); err != nil {
return &ValidationError{Name: "value", err: fmt.Errorf("ent: validator failed for field \"value\": %w", err)}
return &ValidationError{Name: "value", err: fmt.Errorf(`ent: validator failed for field "Meta.value": %w`, err)}
}
}
return nil
@ -439,7 +440,7 @@ func (muo *MetaUpdateOne) defaults() {
func (muo *MetaUpdateOne) check() error {
if v, ok := muo.mutation.Value(); ok {
if err := meta.ValueValidator(v); err != nil {
return &ValidationError{Name: "value", err: fmt.Errorf("ent: validator failed for field \"value\": %w", err)}
return &ValidationError{Name: "value", err: fmt.Errorf(`ent: validator failed for field "Meta.value": %w`, err)}
}
}
return nil
@ -458,7 +459,7 @@ func (muo *MetaUpdateOne) sqlSave(ctx context.Context) (_node *Meta, err error)
}
id, ok := muo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "ID", err: fmt.Errorf("missing Meta.ID for update")}
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Meta.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := muo.fields; len(fields) > 0 {

View file

@ -38,7 +38,6 @@ var (
// Schema is the API for creating, migrating and dropping a schema.
type Schema struct {
drv dialect.Driver
universalID bool
}
// NewSchema creates a new schema client.

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,6 @@ package runtime
// The schema-stitching logic is generated in github.com/crowdsecurity/crowdsec/pkg/database/ent/runtime.go
const (
Version = "v0.9.1" // Version of ent codegen.
Sum = "h1:IG8andyeD79GG24U8Q+1Y45hQXj6gY5evSBcva5gtBk=" // Sum of ent codegen.
Version = "v0.10.0" // Version of ent codegen.
Sum = "h1:9cBomE1fh+WX34DPYQL7tDNAIvhKa3tXvwxuLyhYCMo=" // Sum of ent codegen.
)

View file

@ -40,7 +40,7 @@ type Tx struct {
}
type (
// Committer is the interface that wraps the Committer method.
// Committer is the interface that wraps the Commit method.
Committer interface {
Commit(context.Context, *Tx) error
}
@ -54,7 +54,7 @@ type (
// and returns a Committer. For example:
//
// hook := func(next ent.Committer) ent.Committer {
// return ent.CommitFunc(func(context.Context, tx *ent.Tx) error {
// return ent.CommitFunc(func(ctx context.Context, tx *ent.Tx) error {
// // Do some stuff before.
// if err := next.Commit(ctx, tx); err != nil {
// return err
@ -95,7 +95,7 @@ func (tx *Tx) OnCommit(f CommitHook) {
}
type (
// Rollbacker is the interface that wraps the Rollbacker method.
// Rollbacker is the interface that wraps the Rollback method.
Rollbacker interface {
Rollback(context.Context, *Tx) error
}
@ -109,7 +109,7 @@ type (
// and returns a Rollbacker. For example:
//
// hook := func(next ent.Rollbacker) ent.Rollbacker {
// return ent.RollbackFunc(func(context.Context, tx *ent.Tx) error {
// return ent.RollbackFunc(func(ctx context.Context, tx *ent.Tx) error {
// // Do some stuff before.
// if err := next.Rollback(ctx, tx); err != nil {
// return err