Polling API Integration (#1715)
Co-authored-by: alteredCoder <kevin@crowdsec.net> Co-authored-by: he2ss <hamza.essahely@gmail.com> Co-authored-by: Sebastien Blot <sebastien@crowdsec.net>
This commit is contained in:
parent
3bf95e1a83
commit
e927717fa0
71 changed files with 5890 additions and 347 deletions
|
@ -10,6 +10,7 @@ import (
|
|||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
@ -22,9 +23,9 @@ import (
|
|||
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/models"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
func DecisionsFromAlert(alert *models.Alert) string {
|
||||
ret := ""
|
||||
var decMap = make(map[string]int)
|
||||
|
@ -45,6 +46,50 @@ func DecisionsFromAlert(alert *models.Alert) string {
|
|||
return ret
|
||||
}
|
||||
|
||||
func DateFromAlert(alert *models.Alert) string {
|
||||
ts, err := time.Parse(time.RFC3339, alert.CreatedAt)
|
||||
if err != nil {
|
||||
log.Infof("while parsing %s with %s : %s", alert.CreatedAt, time.RFC3339, err)
|
||||
return alert.CreatedAt
|
||||
}
|
||||
return ts.Format(time.RFC822)
|
||||
}
|
||||
|
||||
func SourceFromAlert(alert *models.Alert) string {
|
||||
|
||||
//more than one item, just number and scope
|
||||
if len(alert.Decisions) > 1 {
|
||||
return fmt.Sprintf("%d %ss (%s)", len(alert.Decisions), *alert.Decisions[0].Scope, *alert.Decisions[0].Origin)
|
||||
}
|
||||
|
||||
//fallback on single decision information
|
||||
if len(alert.Decisions) == 1 {
|
||||
return fmt.Sprintf("%s:%s", *alert.Decisions[0].Scope, *alert.Decisions[0].Value)
|
||||
}
|
||||
|
||||
//try to compose a human friendly version
|
||||
if *alert.Source.Value != "" && *alert.Source.Scope != "" {
|
||||
scope := ""
|
||||
scope = fmt.Sprintf("%s:%s", *alert.Source.Scope, *alert.Source.Value)
|
||||
extra := ""
|
||||
if alert.Source.Cn != "" {
|
||||
extra = alert.Source.Cn
|
||||
}
|
||||
if alert.Source.AsNumber != "" {
|
||||
extra += fmt.Sprintf("/%s", alert.Source.AsNumber)
|
||||
}
|
||||
if alert.Source.AsName != "" {
|
||||
extra += fmt.Sprintf("/%s", alert.Source.AsName)
|
||||
}
|
||||
|
||||
if extra != "" {
|
||||
scope += " (" + extra + ")"
|
||||
}
|
||||
return scope
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func AlertsToTable(alerts *models.GetAlertsResponse, printMachine bool) error {
|
||||
|
||||
if csConfig.Cscli.Output == "raw" {
|
||||
|
@ -97,17 +142,18 @@ func DisplayOneAlert(alert *models.Alert, withDetail bool) error {
|
|||
if *alert.Source.Value != "" {
|
||||
scopeAndValue += ":" + *alert.Source.Value
|
||||
}
|
||||
fmt.Printf(" - ID : %d\n", alert.ID)
|
||||
fmt.Printf(" - Date : %s\n", alert.CreatedAt)
|
||||
fmt.Printf(" - Machine : %s\n", alert.MachineID)
|
||||
fmt.Printf(" - Simulation : %v\n", *alert.Simulated)
|
||||
fmt.Printf(" - Reason : %s\n", *alert.Scenario)
|
||||
fmt.Printf(" - ID : %d\n", alert.ID)
|
||||
fmt.Printf(" - Date : %s\n", alert.CreatedAt)
|
||||
fmt.Printf(" - Machine : %s\n", alert.MachineID)
|
||||
fmt.Printf(" - Simulation : %v\n", *alert.Simulated)
|
||||
fmt.Printf(" - Reason : %s\n", *alert.Scenario)
|
||||
fmt.Printf(" - Events Count : %d\n", *alert.EventsCount)
|
||||
fmt.Printf(" - Scope:Value: %s\n", scopeAndValue)
|
||||
fmt.Printf(" - Country : %s\n", alert.Source.Cn)
|
||||
fmt.Printf(" - AS : %s\n", alert.Source.AsName)
|
||||
fmt.Printf(" - Begin : %s\n", *alert.StartAt)
|
||||
fmt.Printf(" - End : %s\n\n", *alert.StopAt)
|
||||
fmt.Printf(" - Scope:Value : %s\n", scopeAndValue)
|
||||
fmt.Printf(" - Country : %s\n", alert.Source.Cn)
|
||||
fmt.Printf(" - AS : %s\n", alert.Source.AsName)
|
||||
fmt.Printf(" - Begin : %s\n", *alert.StartAt)
|
||||
fmt.Printf(" - End : %s\n", *alert.StopAt)
|
||||
fmt.Printf(" - UUID : %s\n\n", alert.UUID)
|
||||
|
||||
alertDecisionsTable(color.Output, alert)
|
||||
|
||||
|
@ -144,7 +190,6 @@ func DisplayOneAlert(alert *models.Alert, withDetail bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
|
||||
func NewAlertsCmd() *cobra.Command {
|
||||
var cmdAlerts = &cobra.Command{
|
||||
Use: "alerts [action]",
|
||||
|
@ -183,7 +228,6 @@ func NewAlertsCmd() *cobra.Command {
|
|||
return cmdAlerts
|
||||
}
|
||||
|
||||
|
||||
func NewAlertsListCmd() *cobra.Command {
|
||||
var alertListFilter = apiclient.AlertsListOpts{
|
||||
ScopeEquals: new(string),
|
||||
|
@ -195,6 +239,7 @@ func NewAlertsListCmd() *cobra.Command {
|
|||
Until: new(string),
|
||||
TypeEquals: new(string),
|
||||
IncludeCAPI: new(bool),
|
||||
OriginEquals: new(string),
|
||||
}
|
||||
var limit = new(int)
|
||||
contained := new(bool)
|
||||
|
@ -267,9 +312,15 @@ cscli alerts list --type ban`,
|
|||
if *alertListFilter.RangeEquals == "" {
|
||||
alertListFilter.RangeEquals = nil
|
||||
}
|
||||
|
||||
if *alertListFilter.OriginEquals == "" {
|
||||
alertListFilter.OriginEquals = nil
|
||||
}
|
||||
|
||||
if contained != nil && *contained {
|
||||
alertListFilter.Contains = new(bool)
|
||||
}
|
||||
|
||||
alerts, _, err := Client.Alerts.List(context.Background(), alertListFilter)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to list alerts : %v", err)
|
||||
|
@ -291,6 +342,7 @@ cscli alerts list --type ban`,
|
|||
cmdAlertsList.Flags().StringVar(alertListFilter.TypeEquals, "type", "", "restrict to alerts with given decision type (ie. ban, captcha)")
|
||||
cmdAlertsList.Flags().StringVar(alertListFilter.ScopeEquals, "scope", "", "restrict to alerts of this scope (ie. ip,range)")
|
||||
cmdAlertsList.Flags().StringVarP(alertListFilter.ValueEquals, "value", "v", "", "the value to match for in the specified scope")
|
||||
cmdAlertsList.Flags().StringVar(alertListFilter.OriginEquals, "origin", "", fmt.Sprintf("the value to match for the specified origin (%s ...)", strings.Join(types.GetOrigins(), ",")))
|
||||
cmdAlertsList.Flags().BoolVar(contained, "contained", false, "query decisions contained by range")
|
||||
cmdAlertsList.Flags().BoolVarP(&printMachine, "machine", "m", false, "print machines that sent alerts")
|
||||
cmdAlertsList.Flags().IntVarP(limit, "limit", "l", 50, "limit size of alerts list table (0 to view all alerts)")
|
||||
|
@ -396,7 +448,6 @@ cscli alerts delete -s crowdsecurity/ssh-bf"`,
|
|||
return cmdAlertsDelete
|
||||
}
|
||||
|
||||
|
||||
func NewAlertsInspectCmd() *cobra.Command {
|
||||
var details bool
|
||||
var cmdAlertsInspect = &cobra.Command{
|
||||
|
|
|
@ -23,7 +23,9 @@ func alertsTable(out io.Writer, alerts *models.GetAlertsResponse, printMachine b
|
|||
|
||||
for _, alertItem := range *alerts {
|
||||
displayVal := *alertItem.Source.Scope
|
||||
if *alertItem.Source.Value != "" {
|
||||
if len(alertItem.Decisions) > 1 {
|
||||
displayVal = fmt.Sprintf("%d %ss", len(alertItem.Decisions), *alertItem.Decisions[0].Scope)
|
||||
} else if *alertItem.Source.Value != "" {
|
||||
displayVal += ":" + *alertItem.Source.Value
|
||||
}
|
||||
|
||||
|
|
|
@ -6,17 +6,17 @@ import (
|
|||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/models"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
const CAPIBaseURL string = "https://api.crowdsec.net/"
|
||||
|
@ -64,9 +64,9 @@ func NewCapiRegisterCmd() *cobra.Command {
|
|||
log.Fatalf("unable to generate machine id: %s", err)
|
||||
}
|
||||
password := strfmt.Password(generatePassword(passwordLength))
|
||||
apiurl, err := url.Parse(CAPIBaseURL)
|
||||
apiurl, err := url.Parse(types.CAPIBaseURL)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to parse api url %s : %s", CAPIBaseURL, err)
|
||||
log.Fatalf("unable to parse api url %s : %s", types.CAPIBaseURL, err)
|
||||
}
|
||||
_, err = apiclient.RegisterClient(&apiclient.Config{
|
||||
MachineID: capiUser,
|
||||
|
@ -77,7 +77,7 @@ func NewCapiRegisterCmd() *cobra.Command {
|
|||
}, nil)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("api client register ('%s'): %s", CAPIBaseURL, err)
|
||||
log.Fatalf("api client register ('%s'): %s", types.CAPIBaseURL, err)
|
||||
}
|
||||
log.Printf("Successfully registered to Central API (CAPI)")
|
||||
|
||||
|
@ -93,7 +93,8 @@ func NewCapiRegisterCmd() *cobra.Command {
|
|||
apiCfg := csconfig.ApiCredentialsCfg{
|
||||
Login: capiUser,
|
||||
Password: password.String(),
|
||||
URL: CAPIBaseURL,
|
||||
URL: types.CAPIBaseURL,
|
||||
PapiURL: types.PAPIBaseURL,
|
||||
}
|
||||
apiConfigDump, err := yaml.Marshal(apiCfg)
|
||||
if err != nil {
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
func NewConfigCmd() *cobra.Command {
|
||||
cmdConfig := &cobra.Command{
|
||||
Use: "config [command]",
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/fflag"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
)
|
||||
|
||||
|
@ -209,10 +210,11 @@ Disable given information push to the central API.`,
|
|||
}
|
||||
|
||||
rows := [][]string{
|
||||
{"share_manual_decisions", fmt.Sprintf("%t", *csConfig.API.Server.ConsoleConfig.ShareManualDecisions)},
|
||||
{"share_custom", fmt.Sprintf("%t", *csConfig.API.Server.ConsoleConfig.ShareCustomScenarios)},
|
||||
{"share_tainted", fmt.Sprintf("%t", *csConfig.API.Server.ConsoleConfig.ShareTaintedScenarios)},
|
||||
{"share_context", fmt.Sprintf("%t", *csConfig.API.Server.ConsoleConfig.ShareContext)},
|
||||
{csconfig.SEND_MANUAL_SCENARIOS, fmt.Sprintf("%t", *csConfig.API.Server.ConsoleConfig.ShareManualDecisions)},
|
||||
{csconfig.SEND_CUSTOM_SCENARIOS, fmt.Sprintf("%t", *csConfig.API.Server.ConsoleConfig.ShareCustomScenarios)},
|
||||
{csconfig.SEND_TAINTED_SCENARIOS, fmt.Sprintf("%t", *csConfig.API.Server.ConsoleConfig.ShareTaintedScenarios)},
|
||||
{csconfig.SEND_CONTEXT, fmt.Sprintf("%t", *csConfig.API.Server.ConsoleConfig.ShareContext)},
|
||||
{csconfig.CONSOLE_MANAGEMENT, fmt.Sprintf("%t", *csConfig.API.Server.ConsoleConfig.ReceiveDecisions)},
|
||||
}
|
||||
for _, row := range rows {
|
||||
err = csvwriter.Write(row)
|
||||
|
@ -232,6 +234,22 @@ Disable given information push to the central API.`,
|
|||
func SetConsoleOpts(args []string, wanted bool) {
|
||||
for _, arg := range args {
|
||||
switch arg {
|
||||
case csconfig.CONSOLE_MANAGEMENT:
|
||||
if !fflag.PapiClient.IsEnabled() {
|
||||
log.Fatalf("Feature flag %s is disabled, cannot set %s", fflag.PapiClient.Name, csconfig.CONSOLE_MANAGEMENT)
|
||||
}
|
||||
/*for each flag check if it's already set before setting it*/
|
||||
if csConfig.API.Server.ConsoleConfig.ReceiveDecisions != nil {
|
||||
if *csConfig.API.Server.ConsoleConfig.ReceiveDecisions == wanted {
|
||||
log.Infof("%s already set to %t", csconfig.CONSOLE_MANAGEMENT, wanted)
|
||||
} else {
|
||||
log.Infof("%s set to %t", csconfig.CONSOLE_MANAGEMENT, wanted)
|
||||
*csConfig.API.Server.ConsoleConfig.ReceiveDecisions = wanted
|
||||
}
|
||||
} else {
|
||||
log.Infof("%s set to %t", csconfig.CONSOLE_MANAGEMENT, wanted)
|
||||
csConfig.API.Server.ConsoleConfig.ReceiveDecisions = types.BoolPtr(wanted)
|
||||
}
|
||||
case csconfig.SEND_CUSTOM_SCENARIOS:
|
||||
/*for each flag check if it's already set before setting it*/
|
||||
if csConfig.API.Server.ConsoleConfig.ShareCustomScenarios != nil {
|
||||
|
|
|
@ -47,6 +47,12 @@ func cmdConsoleStatusTable(out io.Writer, csConfig csconfig.Config) {
|
|||
activated = string(emoji.CheckMarkButton)
|
||||
}
|
||||
t.AddRow(option, activated, "Send context with alerts to the console")
|
||||
case csconfig.CONSOLE_MANAGEMENT:
|
||||
activated := string(emoji.CrossMark)
|
||||
if *csConfig.API.Server.ConsoleConfig.ReceiveDecisions {
|
||||
activated = string(emoji.CheckMarkButton)
|
||||
}
|
||||
t.AddRow(option, activated, "Receive decisions from console")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -139,7 +139,6 @@ func NewDecisionsCmd() *cobra.Command {
|
|||
return cmdDecisions
|
||||
}
|
||||
|
||||
|
||||
func NewDecisionsListCmd() *cobra.Command {
|
||||
var filter = apiclient.AlertsListOpts{
|
||||
ValueEquals: new(string),
|
||||
|
@ -252,7 +251,7 @@ cscli decisions list -t ban
|
|||
cmdDecisionsList.Flags().StringVar(filter.Until, "until", "", "restrict to alerts older than until (ie. 4h, 30d)")
|
||||
cmdDecisionsList.Flags().StringVarP(filter.TypeEquals, "type", "t", "", "restrict to this decision type (ie. ban,captcha)")
|
||||
cmdDecisionsList.Flags().StringVar(filter.ScopeEquals, "scope", "", "restrict to this scope (ie. ip,range,session)")
|
||||
cmdDecisionsList.Flags().StringVar(filter.OriginEquals, "origin", "", "restrict to this origin (ie. lists,CAPI,cscli,cscli-import,crowdsec)")
|
||||
cmdDecisionsList.Flags().StringVar(filter.OriginEquals, "origin", "", fmt.Sprintf("the value to match for the specified origin (%s ...)", strings.Join(types.GetOrigins(), ",")))
|
||||
cmdDecisionsList.Flags().StringVarP(filter.ValueEquals, "value", "v", "", "restrict to this value (ie. 1.2.3.4,userName)")
|
||||
cmdDecisionsList.Flags().StringVarP(filter.ScenarioEquals, "scenario", "s", "", "restrict to this scenario (ie. crowdsecurity/ssh-bf)")
|
||||
cmdDecisionsList.Flags().StringVarP(filter.IPEquals, "ip", "i", "", "restrict to alerts from this source ip (shorthand for --scope ip --value <IP>)")
|
||||
|
@ -265,7 +264,6 @@ cscli decisions list -t ban
|
|||
return cmdDecisionsList
|
||||
}
|
||||
|
||||
|
||||
func NewDecisionsAddCmd() *cobra.Command {
|
||||
var (
|
||||
addIP string
|
||||
|
@ -290,9 +288,8 @@ cscli decisions add --scope username --value foobar
|
|||
DisableAutoGenTag: true,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
var ipRange string
|
||||
alerts := models.AddAlertsRequest{}
|
||||
origin := "cscli"
|
||||
origin := types.CscliOrigin
|
||||
capacity := int32(0)
|
||||
leakSpeed := "0"
|
||||
eventsCount := int32(1)
|
||||
|
@ -340,12 +337,13 @@ cscli decisions add --scope username --value foobar
|
|||
Scenario: &addReason,
|
||||
ScenarioVersion: &empty,
|
||||
Simulated: &simulated,
|
||||
//setting empty scope/value broke plugins, and it didn't seem to be needed anymore w/ latest papi changes
|
||||
Source: &models.Source{
|
||||
AsName: empty,
|
||||
AsNumber: empty,
|
||||
Cn: empty,
|
||||
IP: addValue,
|
||||
Range: ipRange,
|
||||
Range: "",
|
||||
Scope: &addScope,
|
||||
Value: &addValue,
|
||||
},
|
||||
|
@ -376,7 +374,6 @@ cscli decisions add --scope username --value foobar
|
|||
return cmdDecisionsAdd
|
||||
}
|
||||
|
||||
|
||||
func NewDecisionsDeleteCmd() *cobra.Command {
|
||||
var delFilter = apiclient.DecisionsDeleteOpts{
|
||||
ScopeEquals: new(string),
|
||||
|
@ -476,18 +473,17 @@ cscli decisions delete --type captcha
|
|||
return cmdDecisionsDelete
|
||||
}
|
||||
|
||||
|
||||
func NewDecisionsImportCmd() *cobra.Command {
|
||||
var (
|
||||
defaultDuration = "4h"
|
||||
defaultScope = "ip"
|
||||
defaultType = "ban"
|
||||
defaultReason = "manual"
|
||||
importDuration string
|
||||
importScope string
|
||||
importReason string
|
||||
importType string
|
||||
importFile string
|
||||
importDuration string
|
||||
importScope string
|
||||
importReason string
|
||||
importType string
|
||||
importFile string
|
||||
)
|
||||
|
||||
var cmdDecisionImport = &cobra.Command{
|
||||
|
@ -551,7 +547,7 @@ decisions.json :
|
|||
decisionLine.Duration = importDuration
|
||||
log.Debugf("'duration' line %d, using supplied value: '%s'", line, importDuration)
|
||||
}
|
||||
decisionLine.Origin = "cscli-import"
|
||||
decisionLine.Origin = types.CscliImportOrigin
|
||||
|
||||
if decisionLine.Scenario == "" {
|
||||
decisionLine.Scenario = defaultReason
|
||||
|
@ -591,11 +587,11 @@ decisions.json :
|
|||
alerts := models.AddAlertsRequest{}
|
||||
importAlert := models.Alert{
|
||||
CreatedAt: time.Now().UTC().Format(time.RFC3339),
|
||||
Scenario: types.StrPtr(fmt.Sprintf("add: %d IPs", len(decisionsList))),
|
||||
Scenario: types.StrPtr(fmt.Sprintf("import %s : %d IPs", importFile, len(decisionsList))),
|
||||
Message: types.StrPtr(""),
|
||||
Events: []*models.Event{},
|
||||
Source: &models.Source{
|
||||
Scope: types.StrPtr("cscli/manual-import"),
|
||||
Scope: types.StrPtr(""),
|
||||
Value: types.StrPtr(""),
|
||||
},
|
||||
StartAt: types.StrPtr(time.Now().UTC().Format(time.RFC3339)),
|
||||
|
|
|
@ -78,7 +78,10 @@ func runOutput(input chan types.Event, overflow chan types.Event, buckets *leaky
|
|||
if err != nil {
|
||||
return errors.Wrapf(err, "parsing api url ('%s'): %s", apiConfig.URL, err)
|
||||
}
|
||||
|
||||
papiURL, err := url.Parse(apiConfig.PapiURL)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "parsing polling api url ('%s'): %s", apiConfig.PapiURL, err)
|
||||
}
|
||||
password := strfmt.Password(apiConfig.Password)
|
||||
|
||||
Client, err := apiclient.NewClient(&apiclient.Config{
|
||||
|
@ -87,6 +90,7 @@ func runOutput(input chan types.Event, overflow chan types.Event, buckets *leaky
|
|||
Scenarios: scenarios,
|
||||
UserAgent: fmt.Sprintf("crowdsec/%s", cwversion.VersionStr()),
|
||||
URL: apiURL,
|
||||
PapiURL: papiURL,
|
||||
VersionPrefix: "v1",
|
||||
UpdateScenario: cwhub.GetInstalledScenariosAsString,
|
||||
})
|
||||
|
|
11
go.mod
11
go.mod
|
@ -47,11 +47,11 @@ require (
|
|||
github.com/oschwald/geoip2-golang v1.4.0
|
||||
github.com/oschwald/maxminddb-golang v1.8.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.13.0
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
github.com/prometheus/client_golang v1.14.0
|
||||
github.com/prometheus/client_model v0.3.0
|
||||
github.com/prometheus/prom2json v1.3.0
|
||||
github.com/r3labs/diff/v2 v2.14.1
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/stretchr/testify v1.8.0
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
|
||||
|
@ -69,7 +69,10 @@ require (
|
|||
github.com/aquasecurity/table v1.8.0
|
||||
github.com/beevik/etree v1.1.0
|
||||
github.com/blackfireio/osinfo v1.0.3
|
||||
github.com/bluele/gcache v0.0.2
|
||||
github.com/goccy/go-yaml v1.9.7
|
||||
github.com/gofrs/uuid v4.0.0+incompatible
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0
|
||||
github.com/google/winops v0.0.0-20211216095627-f0e86eb1453b
|
||||
github.com/ivanpirog/coloredcobra v1.0.1
|
||||
github.com/mattn/go-isatty v0.0.14
|
||||
|
@ -91,7 +94,6 @@ require (
|
|||
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/bluele/gcache v0.0.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/containerd/containerd v1.6.12 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
|
@ -111,7 +113,6 @@ require (
|
|||
github.com/go-playground/validator/v10 v10.10.0 // indirect
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
|
||||
github.com/golang/glog v0.0.0-20210429001901-424d2337a529 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/go-cmp v0.5.8 // indirect
|
||||
|
|
11
go.sum
11
go.sum
|
@ -777,14 +777,15 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
|
|||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU=
|
||||
github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
|
||||
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
|
||||
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
||||
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
|
@ -845,8 +846,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
|
|||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
|
@ -1183,6 +1185,7 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
|
|
|
@ -27,15 +27,21 @@ type ApiClient struct {
|
|||
common service
|
||||
/*config stuff*/
|
||||
BaseURL *url.URL
|
||||
PapiURL *url.URL
|
||||
URLPrefix string
|
||||
UserAgent string
|
||||
/*exposed Services*/
|
||||
Decisions *DecisionsService
|
||||
Alerts *AlertsService
|
||||
Auth *AuthService
|
||||
Metrics *MetricsService
|
||||
Signal *SignalService
|
||||
HeartBeat *HeartBeatService
|
||||
Decisions *DecisionsService
|
||||
DecisionDelete *DecisionDeleteService
|
||||
Alerts *AlertsService
|
||||
Auth *AuthService
|
||||
Metrics *MetricsService
|
||||
Signal *SignalService
|
||||
HeartBeat *HeartBeatService
|
||||
}
|
||||
|
||||
func (a *ApiClient) GetClient() *http.Client {
|
||||
return a.client
|
||||
}
|
||||
|
||||
type service struct {
|
||||
|
@ -57,14 +63,17 @@ func NewClient(config *Config) (*ApiClient, error) {
|
|||
if Cert != nil {
|
||||
tlsconfig.Certificates = []tls.Certificate{*Cert}
|
||||
}
|
||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tlsconfig
|
||||
c := &ApiClient{client: t.Client(), BaseURL: config.URL, UserAgent: config.UserAgent, URLPrefix: config.VersionPrefix}
|
||||
if ht, ok := http.DefaultTransport.(*http.Transport); ok {
|
||||
ht.TLSClientConfig = &tlsconfig
|
||||
}
|
||||
c := &ApiClient{client: t.Client(), BaseURL: config.URL, UserAgent: config.UserAgent, URLPrefix: config.VersionPrefix, PapiURL: config.PapiURL}
|
||||
c.common.client = c
|
||||
c.Decisions = (*DecisionsService)(&c.common)
|
||||
c.Alerts = (*AlertsService)(&c.common)
|
||||
c.Auth = (*AuthService)(&c.common)
|
||||
c.Metrics = (*MetricsService)(&c.common)
|
||||
c.Signal = (*SignalService)(&c.common)
|
||||
c.DecisionDelete = (*DecisionDeleteService)(&c.common)
|
||||
c.HeartBeat = (*HeartBeatService)(&c.common)
|
||||
|
||||
return c, nil
|
||||
|
@ -90,6 +99,7 @@ func NewDefaultClient(URL *url.URL, prefix string, userAgent string, client *htt
|
|||
c.Auth = (*AuthService)(&c.common)
|
||||
c.Metrics = (*MetricsService)(&c.common)
|
||||
c.Signal = (*SignalService)(&c.common)
|
||||
c.DecisionDelete = (*DecisionDeleteService)(&c.common)
|
||||
c.HeartBeat = (*HeartBeatService)(&c.common)
|
||||
|
||||
return c, nil
|
||||
|
|
|
@ -11,6 +11,7 @@ type Config struct {
|
|||
Password strfmt.Password
|
||||
Scenarios []string
|
||||
URL *url.URL
|
||||
PapiURL *url.URL
|
||||
VersionPrefix string
|
||||
UserAgent string
|
||||
UpdateScenario func() ([]string, error)
|
||||
|
|
34
pkg/apiclient/decisions_sync_service.go
Normal file
34
pkg/apiclient/decisions_sync_service.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package apiclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/models"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type DecisionDeleteService service
|
||||
|
||||
// DecisionDeleteService purposely reuses AddSignalsRequestItemDecisions model
|
||||
func (d *DecisionDeleteService) Add(ctx context.Context, deletedDecisions *models.DecisionsDeleteRequest) (interface{}, *Response, error) {
|
||||
var response interface{}
|
||||
u := fmt.Sprintf("%s/decisions/delete", d.client.URLPrefix)
|
||||
req, err := d.client.NewRequest(http.MethodPost, u, &deletedDecisions)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "while building request")
|
||||
}
|
||||
|
||||
resp, err := d.client.Do(ctx, req, &response)
|
||||
if err != nil {
|
||||
return nil, resp, errors.Wrap(err, "while performing request")
|
||||
}
|
||||
if resp.Response.StatusCode != http.StatusOK {
|
||||
log.Warnf("Decisions delete response : http %s", resp.Response.Status)
|
||||
} else {
|
||||
log.Debugf("Decisions delete response : http %s", resp.Response.Status)
|
||||
}
|
||||
return &response, resp, nil
|
||||
}
|
|
@ -28,15 +28,13 @@ import (
|
|||
var (
|
||||
pullIntervalDefault = time.Hour * 2
|
||||
pullIntervalDelta = 5 * time.Minute
|
||||
pushIntervalDefault = time.Second * 30
|
||||
pushIntervalDelta = time.Second * 15
|
||||
pushIntervalDefault = time.Second * 10
|
||||
pushIntervalDelta = time.Second * 7
|
||||
metricsIntervalDefault = time.Minute * 30
|
||||
metricsIntervalDelta = time.Minute * 15
|
||||
)
|
||||
|
||||
var SCOPE_CAPI string = "CAPI"
|
||||
var SCOPE_CAPI_ALIAS string = "crowdsecurity/community-blocklist" //we don't use "CAPI" directly, to make it less confusing for the user
|
||||
var SCOPE_LISTS string = "lists"
|
||||
var SCOPE_CAPI_ALIAS_ALIAS string = "crowdsecurity/community-blocklist" //we don't use "CAPI" directly, to make it less confusing for the user
|
||||
|
||||
type apic struct {
|
||||
// when changing the intervals in tests, always set *First too
|
||||
|
@ -49,15 +47,16 @@ type apic struct {
|
|||
metricsIntervalFirst time.Duration
|
||||
dbClient *database.Client
|
||||
apiClient *apiclient.ApiClient
|
||||
alertToPush chan []*models.Alert
|
||||
mu sync.Mutex
|
||||
pushTomb tomb.Tomb
|
||||
pullTomb tomb.Tomb
|
||||
metricsTomb tomb.Tomb
|
||||
startup bool
|
||||
credentials *csconfig.ApiCredentialsCfg
|
||||
scenarioList []string
|
||||
consoleConfig *csconfig.ConsoleConfig
|
||||
AlertsAddChan chan []*models.Alert
|
||||
|
||||
mu sync.Mutex
|
||||
pushTomb tomb.Tomb
|
||||
pullTomb tomb.Tomb
|
||||
metricsTomb tomb.Tomb
|
||||
startup bool
|
||||
credentials *csconfig.ApiCredentialsCfg
|
||||
scenarioList []string
|
||||
consoleConfig *csconfig.ConsoleConfig
|
||||
}
|
||||
|
||||
// randomDuration returns a duration value between d-delta and d+delta
|
||||
|
@ -85,18 +84,54 @@ func (a *apic) FetchScenariosListFromDB() ([]string, error) {
|
|||
return scenarios, nil
|
||||
}
|
||||
|
||||
func decisionsToApiDecisions(decisions []*models.Decision) models.AddSignalsRequestItemDecisions {
|
||||
apiDecisions := models.AddSignalsRequestItemDecisions{}
|
||||
for _, decision := range decisions {
|
||||
x := &models.AddSignalsRequestItemDecisionsItem{
|
||||
Duration: types.StrPtr(*decision.Duration),
|
||||
ID: new(int64),
|
||||
Origin: types.StrPtr(*decision.Origin),
|
||||
Scenario: types.StrPtr(*decision.Scenario),
|
||||
Scope: types.StrPtr(*decision.Scope),
|
||||
//Simulated: *decision.Simulated,
|
||||
Type: types.StrPtr(*decision.Type),
|
||||
Until: decision.Until,
|
||||
Value: types.StrPtr(*decision.Value),
|
||||
UUID: decision.UUID,
|
||||
}
|
||||
*x.ID = decision.ID
|
||||
if decision.Simulated != nil {
|
||||
x.Simulated = *decision.Simulated
|
||||
}
|
||||
apiDecisions = append(apiDecisions, x)
|
||||
}
|
||||
return apiDecisions
|
||||
}
|
||||
|
||||
func alertToSignal(alert *models.Alert, scenarioTrust string, shareContext bool) *models.AddSignalsRequestItem {
|
||||
signal := &models.AddSignalsRequestItem{
|
||||
Message: alert.Message,
|
||||
Scenario: alert.Scenario,
|
||||
ScenarioHash: alert.ScenarioHash,
|
||||
ScenarioVersion: alert.ScenarioVersion,
|
||||
Source: alert.Source,
|
||||
StartAt: alert.StartAt,
|
||||
StopAt: alert.StopAt,
|
||||
CreatedAt: alert.CreatedAt,
|
||||
MachineID: alert.MachineID,
|
||||
ScenarioTrust: scenarioTrust,
|
||||
Source: &models.AddSignalsRequestItemSource{
|
||||
AsName: alert.Source.AsName,
|
||||
AsNumber: alert.Source.AsNumber,
|
||||
Cn: alert.Source.Cn,
|
||||
IP: alert.Source.IP,
|
||||
Latitude: alert.Source.Latitude,
|
||||
Longitude: alert.Source.Longitude,
|
||||
Range: alert.Source.Range,
|
||||
Scope: alert.Source.Scope,
|
||||
Value: alert.Source.Value,
|
||||
},
|
||||
StartAt: alert.StartAt,
|
||||
StopAt: alert.StopAt,
|
||||
CreatedAt: alert.CreatedAt,
|
||||
MachineID: alert.MachineID,
|
||||
ScenarioTrust: scenarioTrust,
|
||||
Decisions: decisionsToApiDecisions(alert.Decisions),
|
||||
UUID: alert.UUID,
|
||||
}
|
||||
if shareContext {
|
||||
signal.Context = make([]*models.AddSignalsRequestItemContextItems0, 0)
|
||||
|
@ -114,7 +149,8 @@ func alertToSignal(alert *models.Alert, scenarioTrust string, shareContext bool)
|
|||
func NewAPIC(config *csconfig.OnlineApiClientCfg, dbClient *database.Client, consoleConfig *csconfig.ConsoleConfig) (*apic, error) {
|
||||
var err error
|
||||
ret := &apic{
|
||||
alertToPush: make(chan []*models.Alert),
|
||||
|
||||
AlertsAddChan: make(chan []*models.Alert),
|
||||
dbClient: dbClient,
|
||||
mu: sync.Mutex{},
|
||||
startup: true,
|
||||
|
@ -137,6 +173,11 @@ func NewAPIC(config *csconfig.OnlineApiClientCfg, dbClient *database.Client, con
|
|||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "while parsing '%s'", config.Credentials.URL)
|
||||
}
|
||||
papiURL, err := url.Parse(config.Credentials.PapiURL)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "while parsing '%s'", config.Credentials.PapiURL)
|
||||
}
|
||||
|
||||
ret.scenarioList, err = ret.FetchScenariosListFromDB()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "while fetching scenarios from db")
|
||||
|
@ -146,10 +187,28 @@ func NewAPIC(config *csconfig.OnlineApiClientCfg, dbClient *database.Client, con
|
|||
Password: password,
|
||||
UserAgent: fmt.Sprintf("crowdsec/%s", cwversion.VersionStr()),
|
||||
URL: apiURL,
|
||||
PapiURL: papiURL,
|
||||
VersionPrefix: "v2",
|
||||
Scenarios: ret.scenarioList,
|
||||
UpdateScenario: ret.FetchScenariosListFromDB,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "while creating api client")
|
||||
}
|
||||
|
||||
scenarios, err := ret.FetchScenariosListFromDB()
|
||||
if err != nil {
|
||||
return ret, errors.Wrapf(err, "get scenario in db: %s", err)
|
||||
}
|
||||
|
||||
if _, err = ret.apiClient.Auth.AuthenticateWatcher(context.Background(), models.WatcherAuthRequest{
|
||||
MachineID: &config.Credentials.Login,
|
||||
Password: &password,
|
||||
Scenarios: scenarios,
|
||||
}); err != nil {
|
||||
return ret, errors.Wrapf(err, "authenticate watcher (%s)", config.Credentials.Login)
|
||||
}
|
||||
|
||||
return ret, err
|
||||
}
|
||||
|
||||
|
@ -183,7 +242,7 @@ func (a *apic) Push() error {
|
|||
log.Infof("Signal push: %d signals to push", len(cacheCopy))
|
||||
go a.Send(&cacheCopy)
|
||||
}
|
||||
case alerts := <-a.alertToPush:
|
||||
case alerts := <-a.AlertsAddChan:
|
||||
var signals []*models.AddSignalsRequestItem
|
||||
for _, alert := range alerts {
|
||||
if ok := shouldShareAlert(alert, a.consoleConfig); ok {
|
||||
|
@ -205,7 +264,7 @@ func getScenarioTrustOfAlert(alert *models.Alert) string {
|
|||
scenarioTrust = "tainted"
|
||||
}
|
||||
if len(alert.Decisions) > 0 {
|
||||
if *alert.Decisions[0].Origin == "cscli" {
|
||||
if *alert.Decisions[0].Origin == types.CscliOrigin {
|
||||
scenarioTrust = "manual"
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +323,7 @@ func (a *apic) Send(cacheOrig *models.AddSignalsRequest) {
|
|||
defer cancel()
|
||||
_, _, err := a.apiClient.Signal.Add(ctx, &send)
|
||||
if err != nil {
|
||||
log.Errorf("Error while sending final chunk to central API : %s", err)
|
||||
log.Errorf("sending signal to central API: %s", err)
|
||||
return
|
||||
}
|
||||
break
|
||||
|
@ -275,7 +334,7 @@ func (a *apic) Send(cacheOrig *models.AddSignalsRequest) {
|
|||
_, _, err := a.apiClient.Signal.Add(ctx, &send)
|
||||
if err != nil {
|
||||
//we log it here as well, because the return value of func might be discarded
|
||||
log.Errorf("Error while sending chunk to central API : %s", err)
|
||||
log.Errorf("sending signal to central API: %s", err)
|
||||
}
|
||||
pageStart += bulkSize
|
||||
pageEnd += bulkSize
|
||||
|
@ -313,7 +372,7 @@ func (a *apic) HandleDeletedDecisions(deletedDecisions []*models.Decision, delet
|
|||
}
|
||||
filter["origin"] = []string{*decision.Origin}
|
||||
|
||||
dbCliRet, err := a.dbClient.SoftDeleteDecisionsWithFilter(filter)
|
||||
dbCliRet, _, err := a.dbClient.SoftDeleteDecisionsWithFilter(filter)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "deleting decisions error")
|
||||
}
|
||||
|
@ -337,12 +396,12 @@ func createAlertsForDecisions(decisions []*models.Decision) []*models.Alert {
|
|||
log.Warningf("nil scope in %+v", sub)
|
||||
continue
|
||||
}
|
||||
if *decision.Origin == SCOPE_CAPI {
|
||||
if *sub.Source.Scope == SCOPE_CAPI {
|
||||
if *decision.Origin == types.CAPIOrigin {
|
||||
if *sub.Source.Scope == types.CAPIOrigin {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
} else if *decision.Origin == SCOPE_LISTS {
|
||||
} else if *decision.Origin == types.ListOrigin {
|
||||
if *sub.Source.Scope == *decision.Origin {
|
||||
if sub.Scenario == nil {
|
||||
log.Warningf("nil scenario in %+v", sub)
|
||||
|
@ -368,12 +427,12 @@ func createAlertForDecision(decision *models.Decision) *models.Alert {
|
|||
newAlert := &models.Alert{}
|
||||
newAlert.Source = &models.Source{}
|
||||
newAlert.Source.Scope = types.StrPtr("")
|
||||
if *decision.Origin == SCOPE_CAPI { //to make things more user friendly, we replace CAPI with community-blocklist
|
||||
newAlert.Scenario = types.StrPtr(SCOPE_CAPI)
|
||||
newAlert.Source.Scope = types.StrPtr(SCOPE_CAPI)
|
||||
} else if *decision.Origin == SCOPE_LISTS {
|
||||
if *decision.Origin == types.CAPIOrigin { //to make things more user friendly, we replace CAPI with community-blocklist
|
||||
newAlert.Scenario = types.StrPtr(types.CAPIOrigin)
|
||||
newAlert.Source.Scope = types.StrPtr(types.CAPIOrigin)
|
||||
} else if *decision.Origin == types.ListOrigin {
|
||||
newAlert.Scenario = types.StrPtr(*decision.Scenario)
|
||||
newAlert.Source.Scope = types.StrPtr(SCOPE_LISTS)
|
||||
newAlert.Source.Scope = types.StrPtr(types.ListOrigin)
|
||||
} else {
|
||||
log.Warningf("unknown origin %s", *decision.Origin)
|
||||
}
|
||||
|
@ -407,14 +466,14 @@ func fillAlertsWithDecisions(alerts []*models.Alert, decisions []*models.Decisio
|
|||
found := false
|
||||
//add the individual decisions to the right list
|
||||
for idx, alert := range alerts {
|
||||
if *decision.Origin == SCOPE_CAPI {
|
||||
if *alert.Source.Scope == SCOPE_CAPI {
|
||||
if *decision.Origin == types.CAPIOrigin {
|
||||
if *alert.Source.Scope == types.CAPIOrigin {
|
||||
alerts[idx].Decisions = append(alerts[idx].Decisions, decision)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
} else if *decision.Origin == SCOPE_LISTS {
|
||||
if *alert.Source.Scope == SCOPE_LISTS && *alert.Scenario == *decision.Scenario {
|
||||
} else if *decision.Origin == types.ListOrigin {
|
||||
if *alert.Source.Scope == types.ListOrigin && *alert.Scenario == *decision.Scenario {
|
||||
alerts[idx].Decisions = append(alerts[idx].Decisions, decision)
|
||||
found = true
|
||||
break
|
||||
|
@ -489,12 +548,12 @@ func (a *apic) PullTop() error {
|
|||
}
|
||||
|
||||
func setAlertScenario(add_counters map[string]map[string]int, delete_counters map[string]map[string]int, alert *models.Alert) *models.Alert {
|
||||
if *alert.Source.Scope == SCOPE_CAPI {
|
||||
*alert.Source.Scope = SCOPE_CAPI_ALIAS
|
||||
alert.Scenario = types.StrPtr(fmt.Sprintf("update : +%d/-%d IPs", add_counters[SCOPE_CAPI]["all"], delete_counters[SCOPE_CAPI]["all"]))
|
||||
} else if *alert.Source.Scope == SCOPE_LISTS {
|
||||
*alert.Source.Scope = fmt.Sprintf("%s:%s", SCOPE_LISTS, *alert.Scenario)
|
||||
alert.Scenario = types.StrPtr(fmt.Sprintf("update : +%d/-%d IPs", add_counters[SCOPE_LISTS][*alert.Scenario], delete_counters[SCOPE_LISTS][*alert.Scenario]))
|
||||
if *alert.Source.Scope == types.CAPIOrigin {
|
||||
*alert.Source.Scope = SCOPE_CAPI_ALIAS_ALIAS
|
||||
alert.Scenario = types.StrPtr(fmt.Sprintf("update : +%d/-%d IPs", add_counters[types.CAPIOrigin]["all"], delete_counters[types.CAPIOrigin]["all"]))
|
||||
} else if *alert.Source.Scope == types.ListOrigin {
|
||||
*alert.Source.Scope = fmt.Sprintf("%s:%s", types.ListOrigin, *alert.Scenario)
|
||||
alert.Scenario = types.StrPtr(fmt.Sprintf("update : +%d/-%d IPs", add_counters[types.ListOrigin][*alert.Scenario], delete_counters[types.ListOrigin][*alert.Scenario]))
|
||||
}
|
||||
return alert
|
||||
}
|
||||
|
@ -622,20 +681,20 @@ func (a *apic) Shutdown() {
|
|||
|
||||
func makeAddAndDeleteCounters() (map[string]map[string]int, map[string]map[string]int) {
|
||||
add_counters := make(map[string]map[string]int)
|
||||
add_counters[SCOPE_CAPI] = make(map[string]int)
|
||||
add_counters[SCOPE_LISTS] = make(map[string]int)
|
||||
add_counters[types.CAPIOrigin] = make(map[string]int)
|
||||
add_counters[types.ListOrigin] = make(map[string]int)
|
||||
|
||||
delete_counters := make(map[string]map[string]int)
|
||||
delete_counters[SCOPE_CAPI] = make(map[string]int)
|
||||
delete_counters[SCOPE_LISTS] = make(map[string]int)
|
||||
delete_counters[types.CAPIOrigin] = make(map[string]int)
|
||||
delete_counters[types.ListOrigin] = make(map[string]int)
|
||||
|
||||
return add_counters, delete_counters
|
||||
}
|
||||
|
||||
func updateCounterForDecision(counter map[string]map[string]int, decision *models.Decision, totalDecisions int) {
|
||||
if *decision.Origin == SCOPE_CAPI {
|
||||
if *decision.Origin == types.CAPIOrigin {
|
||||
counter[*decision.Origin]["all"] += totalDecisions
|
||||
} else if *decision.Origin == SCOPE_LISTS {
|
||||
} else if *decision.Origin == types.ListOrigin {
|
||||
counter[*decision.Origin][*decision.Scenario] += totalDecisions
|
||||
} else {
|
||||
log.Warningf("Unknown origin %s", *decision.Origin)
|
||||
|
|
|
@ -46,7 +46,8 @@ func getAPIC(t *testing.T) *apic {
|
|||
t.Helper()
|
||||
dbClient := getDBClient(t)
|
||||
return &apic{
|
||||
alertToPush: make(chan []*models.Alert),
|
||||
AlertsAddChan: make(chan []*models.Alert),
|
||||
//DecisionDeleteChan: make(chan []*models.Decision),
|
||||
dbClient: dbClient,
|
||||
mu: sync.Mutex{},
|
||||
startup: true,
|
||||
|
@ -108,7 +109,7 @@ func TestAPICCAPIPullIsOld(t *testing.T) {
|
|||
SetType("IP").
|
||||
SetScope("Country").
|
||||
SetValue("Blah").
|
||||
SetOrigin(SCOPE_CAPI).
|
||||
SetOrigin(types.CAPIOrigin).
|
||||
SaveX(context.Background())
|
||||
|
||||
api.dbClient.Ent.Alert.Create().
|
||||
|
@ -178,12 +179,13 @@ func TestNewAPIC(t *testing.T) {
|
|||
setConfig := func() {
|
||||
testConfig = &csconfig.OnlineApiClientCfg{
|
||||
Credentials: &csconfig.ApiCredentialsCfg{
|
||||
URL: "foobar",
|
||||
URL: "http://foobar/",
|
||||
Login: "foo",
|
||||
Password: "bar",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type args struct {
|
||||
dbClient *database.Client
|
||||
consoleConfig *csconfig.ConsoleConfig
|
||||
|
@ -216,6 +218,17 @@ func TestNewAPIC(t *testing.T) {
|
|||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
setConfig()
|
||||
httpmock.Activate()
|
||||
defer httpmock.DeactivateAndReset()
|
||||
httpmock.RegisterResponder("POST", "http://foobar/v2/watchers/login", httpmock.NewBytesResponder(
|
||||
200, jsonMarshalX(
|
||||
models.WatcherAuthResponse{
|
||||
Code: 200,
|
||||
Expire: "2023-01-12T22:51:43Z",
|
||||
Token: "MyToken",
|
||||
},
|
||||
),
|
||||
))
|
||||
tc.action()
|
||||
_, err := NewAPIC(testConfig, tc.args.dbClient, tc.args.consoleConfig)
|
||||
cstest.RequireErrorContains(t, err, tc.expectedErr)
|
||||
|
@ -233,7 +246,7 @@ func TestAPICHandleDeletedDecisions(t *testing.T) {
|
|||
SetType("ban").
|
||||
SetScope("IP").
|
||||
SetValue("1.2.3.4").
|
||||
SetOrigin(SCOPE_CAPI).
|
||||
SetOrigin(types.CAPIOrigin).
|
||||
SaveX(context.Background())
|
||||
|
||||
api.dbClient.Ent.Decision.Create().
|
||||
|
@ -242,14 +255,14 @@ func TestAPICHandleDeletedDecisions(t *testing.T) {
|
|||
SetType("ban").
|
||||
SetScope("IP").
|
||||
SetValue("1.2.3.4").
|
||||
SetOrigin(SCOPE_CAPI).
|
||||
SetOrigin(types.CAPIOrigin).
|
||||
SaveX(context.Background())
|
||||
|
||||
assertTotalDecisionCount(t, api.dbClient, 2)
|
||||
|
||||
nbDeleted, err := api.HandleDeletedDecisions([]*models.Decision{{
|
||||
Value: types.StrPtr("1.2.3.4"),
|
||||
Origin: &SCOPE_CAPI,
|
||||
Origin: types.StrPtr(types.CAPIOrigin),
|
||||
Type: &decision1.Type,
|
||||
Scenario: types.StrPtr("crowdsec/test"),
|
||||
Scope: types.StrPtr("IP"),
|
||||
|
@ -257,7 +270,7 @@ func TestAPICHandleDeletedDecisions(t *testing.T) {
|
|||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 2, nbDeleted)
|
||||
assert.Equal(t, 2, deleteCounters[SCOPE_CAPI]["all"])
|
||||
assert.Equal(t, 2, deleteCounters[types.CAPIOrigin]["all"])
|
||||
}
|
||||
|
||||
func TestAPICGetMetrics(t *testing.T) {
|
||||
|
@ -347,22 +360,22 @@ func TestAPICGetMetrics(t *testing.T) {
|
|||
|
||||
func TestCreateAlertsForDecision(t *testing.T) {
|
||||
httpBfDecisionList := &models.Decision{
|
||||
Origin: &SCOPE_LISTS,
|
||||
Origin: types.StrPtr(types.ListOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/http-bf"),
|
||||
}
|
||||
|
||||
sshBfDecisionList := &models.Decision{
|
||||
Origin: &SCOPE_LISTS,
|
||||
Origin: types.StrPtr(types.ListOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/ssh-bf"),
|
||||
}
|
||||
|
||||
httpBfDecisionCommunity := &models.Decision{
|
||||
Origin: &SCOPE_CAPI,
|
||||
Origin: types.StrPtr(types.CAPIOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/http-bf"),
|
||||
}
|
||||
|
||||
sshBfDecisionCommunity := &models.Decision{
|
||||
Origin: &SCOPE_CAPI,
|
||||
Origin: types.StrPtr(types.CAPIOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/ssh-bf"),
|
||||
}
|
||||
type args struct {
|
||||
|
@ -426,25 +439,25 @@ func TestCreateAlertsForDecision(t *testing.T) {
|
|||
|
||||
func TestFillAlertsWithDecisions(t *testing.T) {
|
||||
httpBfDecisionCommunity := &models.Decision{
|
||||
Origin: &SCOPE_CAPI,
|
||||
Origin: types.StrPtr(types.CAPIOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/http-bf"),
|
||||
Scope: types.StrPtr("ip"),
|
||||
}
|
||||
|
||||
sshBfDecisionCommunity := &models.Decision{
|
||||
Origin: &SCOPE_CAPI,
|
||||
Origin: types.StrPtr(types.CAPIOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/ssh-bf"),
|
||||
Scope: types.StrPtr("ip"),
|
||||
}
|
||||
|
||||
httpBfDecisionList := &models.Decision{
|
||||
Origin: &SCOPE_LISTS,
|
||||
Origin: types.StrPtr(types.ListOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/http-bf"),
|
||||
Scope: types.StrPtr("ip"),
|
||||
}
|
||||
|
||||
sshBfDecisionList := &models.Decision{
|
||||
Origin: &SCOPE_LISTS,
|
||||
Origin: types.StrPtr(types.ListOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/ssh-bf"),
|
||||
Scope: types.StrPtr("ip"),
|
||||
}
|
||||
|
@ -505,7 +518,7 @@ func TestFillAlertsWithDecisions(t *testing.T) {
|
|||
func TestAPICPullTop(t *testing.T) {
|
||||
api := getAPIC(t)
|
||||
api.dbClient.Ent.Decision.Create().
|
||||
SetOrigin(SCOPE_LISTS).
|
||||
SetOrigin(types.ListOrigin).
|
||||
SetType("ban").
|
||||
SetValue("9.9.9.9").
|
||||
SetScope("Ip").
|
||||
|
@ -521,7 +534,7 @@ func TestAPICPullTop(t *testing.T) {
|
|||
models.DecisionsStreamResponse{
|
||||
Deleted: models.GetDecisionsResponse{
|
||||
&models.Decision{
|
||||
Origin: &SCOPE_LISTS,
|
||||
Origin: types.StrPtr(types.ListOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/ssh-bf"),
|
||||
Value: types.StrPtr("9.9.9.9"),
|
||||
Scope: types.StrPtr("Ip"),
|
||||
|
@ -529,7 +542,7 @@ func TestAPICPullTop(t *testing.T) {
|
|||
Type: types.StrPtr("ban"),
|
||||
}, // This is already present in DB
|
||||
&models.Decision{
|
||||
Origin: &SCOPE_LISTS,
|
||||
Origin: types.StrPtr(types.ListOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/ssh-bf"),
|
||||
Value: types.StrPtr("9.1.9.9"),
|
||||
Scope: types.StrPtr("Ip"),
|
||||
|
@ -539,7 +552,7 @@ func TestAPICPullTop(t *testing.T) {
|
|||
},
|
||||
New: models.GetDecisionsResponse{
|
||||
&models.Decision{
|
||||
Origin: &SCOPE_CAPI,
|
||||
Origin: types.StrPtr(types.CAPIOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/test1"),
|
||||
Value: types.StrPtr("1.2.3.4"),
|
||||
Scope: types.StrPtr("Ip"),
|
||||
|
@ -547,7 +560,7 @@ func TestAPICPullTop(t *testing.T) {
|
|||
Type: types.StrPtr("ban"),
|
||||
},
|
||||
&models.Decision{
|
||||
Origin: &SCOPE_CAPI,
|
||||
Origin: types.StrPtr(types.CAPIOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/test2"),
|
||||
Value: types.StrPtr("1.2.3.5"),
|
||||
Scope: types.StrPtr("Ip"),
|
||||
|
@ -555,7 +568,7 @@ func TestAPICPullTop(t *testing.T) {
|
|||
Type: types.StrPtr("ban"),
|
||||
}, // These two are from community list.
|
||||
&models.Decision{
|
||||
Origin: &SCOPE_LISTS,
|
||||
Origin: types.StrPtr(types.ListOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/http-bf"),
|
||||
Value: types.StrPtr("1.2.3.6"),
|
||||
Scope: types.StrPtr("Ip"),
|
||||
|
@ -563,7 +576,7 @@ func TestAPICPullTop(t *testing.T) {
|
|||
Type: types.StrPtr("ban"),
|
||||
},
|
||||
&models.Decision{
|
||||
Origin: &SCOPE_LISTS,
|
||||
Origin: types.StrPtr(types.ListOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/ssh-bf"),
|
||||
Value: types.StrPtr("1.2.3.7"),
|
||||
Scope: types.StrPtr("Ip"),
|
||||
|
@ -604,7 +617,7 @@ func TestAPICPullTop(t *testing.T) {
|
|||
alertScenario[alert.SourceScope]++
|
||||
}
|
||||
assert.Equal(t, 3, len(alertScenario))
|
||||
assert.Equal(t, 1, alertScenario[SCOPE_CAPI_ALIAS])
|
||||
assert.Equal(t, 1, alertScenario[SCOPE_CAPI_ALIAS_ALIAS])
|
||||
assert.Equal(t, 1, alertScenario["lists:crowdsecurity/ssh-bf"])
|
||||
assert.Equal(t, 1, alertScenario["lists:crowdsecurity/http-bf"])
|
||||
|
||||
|
@ -632,6 +645,7 @@ func TestAPICPush(t *testing.T) {
|
|||
ScenarioHash: types.StrPtr("certified"),
|
||||
ScenarioVersion: types.StrPtr("v1.0"),
|
||||
Simulated: types.BoolPtr(false),
|
||||
Source: &models.Source{},
|
||||
},
|
||||
},
|
||||
expectedCalls: 1,
|
||||
|
@ -644,6 +658,7 @@ func TestAPICPush(t *testing.T) {
|
|||
ScenarioHash: types.StrPtr("certified"),
|
||||
ScenarioVersion: types.StrPtr("v1.0"),
|
||||
Simulated: types.BoolPtr(true),
|
||||
Source: &models.Source{},
|
||||
},
|
||||
},
|
||||
expectedCalls: 0,
|
||||
|
@ -659,6 +674,7 @@ func TestAPICPush(t *testing.T) {
|
|||
ScenarioHash: types.StrPtr("certified"),
|
||||
ScenarioVersion: types.StrPtr("v1.0"),
|
||||
Simulated: types.BoolPtr(false),
|
||||
Source: &models.Source{},
|
||||
}
|
||||
}
|
||||
return alerts
|
||||
|
@ -688,7 +704,7 @@ func TestAPICPush(t *testing.T) {
|
|||
api.apiClient = apic
|
||||
httpmock.RegisterResponder("POST", "http://api.crowdsec.net/api/signals", httpmock.NewBytesResponder(200, []byte{}))
|
||||
go func() {
|
||||
api.alertToPush <- tc.alerts
|
||||
api.AlertsAddChan <- tc.alerts
|
||||
time.Sleep(time.Second)
|
||||
api.Shutdown()
|
||||
}()
|
||||
|
@ -832,7 +848,7 @@ func TestAPICPull(t *testing.T) {
|
|||
models.DecisionsStreamResponse{
|
||||
New: models.GetDecisionsResponse{
|
||||
&models.Decision{
|
||||
Origin: &SCOPE_CAPI,
|
||||
Origin: types.StrPtr(types.CAPIOrigin),
|
||||
Scenario: types.StrPtr("crowdsecurity/test2"),
|
||||
Value: types.StrPtr("1.2.3.5"),
|
||||
Scope: types.StrPtr("Ip"),
|
||||
|
@ -892,7 +908,7 @@ func TestShouldShareAlert(t *testing.T) {
|
|||
},
|
||||
alert: &models.Alert{
|
||||
Simulated: types.BoolPtr(false),
|
||||
Decisions: []*models.Decision{{Origin: types.StrPtr("cscli")}},
|
||||
Decisions: []*models.Decision{{Origin: types.StrPtr(types.CscliOrigin)}},
|
||||
},
|
||||
expectedRet: true,
|
||||
expectedTrust: "manual",
|
||||
|
@ -904,7 +920,7 @@ func TestShouldShareAlert(t *testing.T) {
|
|||
},
|
||||
alert: &models.Alert{
|
||||
Simulated: types.BoolPtr(false),
|
||||
Decisions: []*models.Decision{{Origin: types.StrPtr("cscli")}},
|
||||
Decisions: []*models.Decision{{Origin: types.StrPtr(types.CscliOrigin)}},
|
||||
},
|
||||
expectedRet: false,
|
||||
expectedTrust: "manual",
|
||||
|
|
|
@ -12,14 +12,17 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/apiserver/controllers"
|
||||
v1 "github.com/crowdsecurity/crowdsec/pkg/apiserver/middlewares/v1"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/fflag"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-co-op/gocron"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
|
@ -40,8 +43,10 @@ type APIServer struct {
|
|||
router *gin.Engine
|
||||
httpServer *http.Server
|
||||
apic *apic
|
||||
papi *Papi
|
||||
httpServerTomb tomb.Tomb
|
||||
consoleConfig *csconfig.ConsoleConfig
|
||||
isEnrolled bool
|
||||
}
|
||||
|
||||
// RecoveryWithWriter returns a middleware for a given writer that recovers from any panics and writes a 500 if there was one.
|
||||
|
@ -206,18 +211,34 @@ func NewServer(config *csconfig.LocalApiServerCfg) (*APIServer, error) {
|
|||
}
|
||||
|
||||
var apiClient *apic
|
||||
var papiClient *Papi
|
||||
var isMachineEnrolled = false
|
||||
|
||||
if config.OnlineClient != nil && config.OnlineClient.Credentials != nil {
|
||||
log.Printf("Loading CAPI pusher")
|
||||
log.Printf("Loading CAPI manager")
|
||||
apiClient, err = NewAPIC(config.OnlineClient, dbClient, config.ConsoleConfig)
|
||||
if err != nil {
|
||||
return &APIServer{}, err
|
||||
}
|
||||
controller.CAPIChan = apiClient.alertToPush
|
||||
log.Infof("CAPI manager configured successfully")
|
||||
isMachineEnrolled = isEnrolled(apiClient.apiClient)
|
||||
if isMachineEnrolled {
|
||||
log.Infof("Machine is enrolled in the console, Loading PAPI Client")
|
||||
papiClient, err = NewPAPI(apiClient, dbClient, config.ConsoleConfig, *config.PapiLogLevel)
|
||||
if err != nil {
|
||||
return &APIServer{}, err
|
||||
}
|
||||
controller.DecisionDeleteChan = papiClient.Channels.DeleteDecisionChannel
|
||||
controller.AlertsAddChan = apiClient.AlertsAddChan
|
||||
} else {
|
||||
log.Errorf("Machine is not enrolled in the console, can't synchronize with the console")
|
||||
}
|
||||
} else {
|
||||
apiClient = nil
|
||||
controller.CAPIChan = nil
|
||||
controller.AlertsAddChan = nil
|
||||
controller.DecisionDeleteChan = nil
|
||||
}
|
||||
|
||||
if trustedIPs, err := config.GetTrustedIPs(); err == nil {
|
||||
controller.TrustedIPs = trustedIPs
|
||||
} else {
|
||||
|
@ -233,12 +254,29 @@ func NewServer(config *csconfig.LocalApiServerCfg) (*APIServer, error) {
|
|||
flushScheduler: flushScheduler,
|
||||
router: router,
|
||||
apic: apiClient,
|
||||
papi: papiClient,
|
||||
httpServerTomb: tomb.Tomb{},
|
||||
consoleConfig: config.ConsoleConfig,
|
||||
isEnrolled: isMachineEnrolled,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func isEnrolled(client *apiclient.ApiClient) bool {
|
||||
apiHTTPClient := client.GetClient()
|
||||
jwtTransport := apiHTTPClient.Transport.(*apiclient.JWTTransport)
|
||||
tokenStr := jwtTransport.Token
|
||||
|
||||
token, _ := jwt.Parse(tokenStr, nil)
|
||||
if token == nil {
|
||||
return false
|
||||
}
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
_, ok := claims["organization_id"]
|
||||
|
||||
return ok
|
||||
}
|
||||
|
||||
func (s *APIServer) Router() (*gin.Engine, error) {
|
||||
return s.router, nil
|
||||
}
|
||||
|
@ -303,6 +341,7 @@ func (s *APIServer) Run(apiReady chan bool) error {
|
|||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
s.apic.pullTomb.Go(func() error {
|
||||
if err := s.apic.Pull(); err != nil {
|
||||
log.Errorf("capi pull: %s", err)
|
||||
|
@ -310,6 +349,33 @@ func (s *APIServer) Run(apiReady chan bool) error {
|
|||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
//csConfig.API.Server.ConsoleConfig.ShareCustomScenarios
|
||||
if s.isEnrolled {
|
||||
if fflag.PapiClient.IsEnabled() {
|
||||
if s.consoleConfig.ReceiveDecisions != nil && *s.consoleConfig.ReceiveDecisions {
|
||||
log.Infof("Starting PAPI decision receiver")
|
||||
s.papi.pullTomb.Go(func() error {
|
||||
if err := s.papi.Pull(); err != nil {
|
||||
log.Errorf("papi pull: %s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
s.papi.syncTomb.Go(func() error {
|
||||
if err := s.papi.SyncDecisions(); err != nil {
|
||||
log.Errorf("capi decisions sync: %s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
} else {
|
||||
log.Warningf("Machine is not allowed to synchronize decisions, you can enable it with `cscli console enable console_management`")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s.apic.metricsTomb.Go(func() error {
|
||||
s.apic.SendMetrics(make(chan bool))
|
||||
return nil
|
||||
|
|
|
@ -16,16 +16,17 @@ import (
|
|||
)
|
||||
|
||||
type Controller struct {
|
||||
Ectx context.Context
|
||||
DBClient *database.Client
|
||||
Router *gin.Engine
|
||||
Profiles []*csconfig.ProfileCfg
|
||||
CAPIChan chan []*models.Alert
|
||||
PluginChannel chan csplugin.ProfileAlert
|
||||
Log *log.Logger
|
||||
ConsoleConfig *csconfig.ConsoleConfig
|
||||
TrustedIPs []net.IPNet
|
||||
HandlerV1 *v1.Controller
|
||||
Ectx context.Context
|
||||
DBClient *database.Client
|
||||
Router *gin.Engine
|
||||
Profiles []*csconfig.ProfileCfg
|
||||
AlertsAddChan chan []*models.Alert
|
||||
DecisionDeleteChan chan []*models.Decision
|
||||
PluginChannel chan csplugin.ProfileAlert
|
||||
Log *log.Logger
|
||||
ConsoleConfig *csconfig.ConsoleConfig
|
||||
TrustedIPs []net.IPNet
|
||||
HandlerV1 *v1.Controller
|
||||
}
|
||||
|
||||
func (c *Controller) Init() error {
|
||||
|
@ -59,13 +60,14 @@ func (c *Controller) NewV1() error {
|
|||
var err error
|
||||
|
||||
v1Config := v1.ControllerV1Config{
|
||||
DbClient: c.DBClient,
|
||||
Ctx: c.Ectx,
|
||||
ProfilesCfg: c.Profiles,
|
||||
CapiChan: c.CAPIChan,
|
||||
PluginChannel: c.PluginChannel,
|
||||
ConsoleConfig: *c.ConsoleConfig,
|
||||
TrustedIPs: c.TrustedIPs,
|
||||
DbClient: c.DBClient,
|
||||
Ctx: c.Ectx,
|
||||
ProfilesCfg: c.Profiles,
|
||||
DecisionDeleteChan: c.DecisionDeleteChan,
|
||||
AlertsAddChan: c.AlertsAddChan,
|
||||
PluginChannel: c.PluginChannel,
|
||||
ConsoleConfig: *c.ConsoleConfig,
|
||||
TrustedIPs: c.TrustedIPs,
|
||||
}
|
||||
|
||||
c.HandlerV1, err = v1.New(&v1Config)
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"time"
|
||||
|
||||
jwt "github.com/appleboy/gin-jwt/v2"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent"
|
||||
|
@ -44,6 +45,7 @@ func FormatOneAlert(alert *ent.Alert) *models.Alert {
|
|||
Capacity: &alert.Capacity,
|
||||
Leakspeed: &alert.LeakSpeed,
|
||||
Simulated: &alert.Simulated,
|
||||
UUID: alert.UUID,
|
||||
Source: &models.Source{
|
||||
Scope: &alert.SourceScope,
|
||||
Value: &alert.SourceValue,
|
||||
|
@ -159,8 +161,15 @@ func (c *Controller) CreateAlert(gctx *gin.Context) {
|
|||
}
|
||||
|
||||
alert.MachineID = machineID
|
||||
//generate uuid here for alert
|
||||
alert.UUID = uuid.NewString()
|
||||
|
||||
//if coming from cscli, alert already has decisions
|
||||
if len(alert.Decisions) != 0 {
|
||||
//alert already has a decision (cscli decisions add etc.), generate uuid here
|
||||
for _, decision := range alert.Decisions {
|
||||
decision.UUID = uuid.NewString()
|
||||
}
|
||||
for pIdx, profile := range c.Profiles {
|
||||
_, matched, err := profile.EvaluateProfile(alert)
|
||||
if err != nil {
|
||||
|
@ -176,7 +185,7 @@ func (c *Controller) CreateAlert(gctx *gin.Context) {
|
|||
}
|
||||
}
|
||||
decision := alert.Decisions[0]
|
||||
if decision.Origin != nil && *decision.Origin == "cscli-import" {
|
||||
if decision.Origin != nil && *decision.Origin == types.CscliImportOrigin {
|
||||
stopFlush = true
|
||||
}
|
||||
continue
|
||||
|
@ -201,11 +210,13 @@ func (c *Controller) CreateAlert(gctx *gin.Context) {
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !matched {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, decision := range profileDecisions {
|
||||
decision.UUID = uuid.NewString()
|
||||
}
|
||||
//generate uuid here for alert
|
||||
if len(alert.Decisions) == 0 { // non manual decision
|
||||
alert.Decisions = append(alert.Decisions, profileDecisions...)
|
||||
}
|
||||
|
@ -229,9 +240,9 @@ func (c *Controller) CreateAlert(gctx *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if c.CAPIChan != nil {
|
||||
if c.AlertsAddChan != nil {
|
||||
select {
|
||||
case c.CAPIChan <- input:
|
||||
case c.AlertsAddChan <- input:
|
||||
log.Debug("alert sent to CAPI channel")
|
||||
default:
|
||||
log.Warning("Cannot send alert to Central API channel")
|
||||
|
|
|
@ -16,22 +16,28 @@ import (
|
|||
)
|
||||
|
||||
type Controller struct {
|
||||
Ectx context.Context
|
||||
DBClient *database.Client
|
||||
APIKeyHeader string
|
||||
Middlewares *middlewares.Middlewares
|
||||
Profiles []*csprofiles.Runtime
|
||||
CAPIChan chan []*models.Alert
|
||||
Ectx context.Context
|
||||
DBClient *database.Client
|
||||
APIKeyHeader string
|
||||
Middlewares *middlewares.Middlewares
|
||||
Profiles []*csprofiles.Runtime
|
||||
|
||||
AlertsAddChan chan []*models.Alert
|
||||
DecisionDeleteChan chan []*models.Decision
|
||||
|
||||
PluginChannel chan csplugin.ProfileAlert
|
||||
ConsoleConfig csconfig.ConsoleConfig
|
||||
TrustedIPs []net.IPNet
|
||||
}
|
||||
|
||||
type ControllerV1Config struct {
|
||||
DbClient *database.Client
|
||||
Ctx context.Context
|
||||
ProfilesCfg []*csconfig.ProfileCfg
|
||||
CapiChan chan []*models.Alert
|
||||
DbClient *database.Client
|
||||
Ctx context.Context
|
||||
ProfilesCfg []*csconfig.ProfileCfg
|
||||
|
||||
AlertsAddChan chan []*models.Alert
|
||||
DecisionDeleteChan chan []*models.Decision
|
||||
|
||||
PluginChannel chan csplugin.ProfileAlert
|
||||
ConsoleConfig csconfig.ConsoleConfig
|
||||
TrustedIPs []net.IPNet
|
||||
|
@ -46,14 +52,15 @@ func New(cfg *ControllerV1Config) (*Controller, error) {
|
|||
}
|
||||
|
||||
v1 := &Controller{
|
||||
Ectx: cfg.Ctx,
|
||||
DBClient: cfg.DbClient,
|
||||
APIKeyHeader: middlewares.APIKeyHeader,
|
||||
Profiles: profiles,
|
||||
CAPIChan: cfg.CapiChan,
|
||||
PluginChannel: cfg.PluginChannel,
|
||||
ConsoleConfig: cfg.ConsoleConfig,
|
||||
TrustedIPs: cfg.TrustedIPs,
|
||||
Ectx: cfg.Ctx,
|
||||
DBClient: cfg.DbClient,
|
||||
APIKeyHeader: middlewares.APIKeyHeader,
|
||||
Profiles: profiles,
|
||||
AlertsAddChan: cfg.AlertsAddChan,
|
||||
DecisionDeleteChan: cfg.DecisionDeleteChan,
|
||||
PluginChannel: cfg.PluginChannel,
|
||||
ConsoleConfig: cfg.ConsoleConfig,
|
||||
TrustedIPs: cfg.TrustedIPs,
|
||||
}
|
||||
v1.Middlewares, err = middlewares.NewMiddlewares(cfg.DbClient)
|
||||
if err != nil {
|
||||
|
|
|
@ -34,6 +34,7 @@ func FormatDecisions(decisions []*ent.Decision, dedup bool) ([]*models.Decision,
|
|||
Value: &dbDecision.Value,
|
||||
Type: &dbDecision.Type,
|
||||
Origin: &dbDecision.Origin,
|
||||
UUID: dbDecision.UUID,
|
||||
}
|
||||
results = append(results, &decision)
|
||||
}
|
||||
|
@ -93,11 +94,20 @@ func (c *Controller) DeleteDecisionById(gctx *gin.Context) {
|
|||
gctx.JSON(http.StatusBadRequest, gin.H{"message": "decision_id must be valid integer"})
|
||||
return
|
||||
}
|
||||
nbDeleted, err := c.DBClient.SoftDeleteDecisionByID(decisionID)
|
||||
nbDeleted, deletedFromDB, err := c.DBClient.SoftDeleteDecisionByID(decisionID)
|
||||
if err != nil {
|
||||
c.HandleDBErrors(gctx, err)
|
||||
return
|
||||
}
|
||||
//transform deleted decisions to be sendable to capi
|
||||
deletedDecisions, err := FormatDecisions(deletedFromDB, false)
|
||||
if err != nil {
|
||||
log.Warningf("failed to format decisions: %v", err)
|
||||
}
|
||||
|
||||
if c.DecisionDeleteChan != nil {
|
||||
c.DecisionDeleteChan <- deletedDecisions
|
||||
}
|
||||
|
||||
deleteDecisionResp := models.DeleteDecisionResponse{
|
||||
NbDeleted: strconv.Itoa(nbDeleted),
|
||||
|
@ -108,16 +118,24 @@ func (c *Controller) DeleteDecisionById(gctx *gin.Context) {
|
|||
|
||||
func (c *Controller) DeleteDecisions(gctx *gin.Context) {
|
||||
var err error
|
||||
|
||||
nbDeleted, err := c.DBClient.SoftDeleteDecisionsWithFilter(gctx.Request.URL.Query())
|
||||
nbDeleted, deletedFromDB, err := c.DBClient.SoftDeleteDecisionsWithFilter(gctx.Request.URL.Query())
|
||||
if err != nil {
|
||||
c.HandleDBErrors(gctx, err)
|
||||
return
|
||||
}
|
||||
//transform deleted decisions to be sendable to capi
|
||||
deletedDecisions, err := FormatDecisions(deletedFromDB, false)
|
||||
if err != nil {
|
||||
log.Warningf("failed to format decisions: %v", err)
|
||||
}
|
||||
|
||||
if c.DecisionDeleteChan != nil {
|
||||
c.DecisionDeleteChan <- deletedDecisions
|
||||
}
|
||||
|
||||
deleteDecisionResp := models.DeleteDecisionResponse{
|
||||
NbDeleted: nbDeleted,
|
||||
}
|
||||
|
||||
gctx.JSON(http.StatusOK, deleteDecisionResp)
|
||||
}
|
||||
|
||||
|
|
263
pkg/apiserver/papi.go
Normal file
263
pkg/apiserver/papi.go
Normal file
|
@ -0,0 +1,263 @@
|
|||
package apiserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/longpollclient"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/models"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gopkg.in/tomb.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
SyncInterval = time.Second * 10
|
||||
)
|
||||
|
||||
const (
|
||||
PapiPullKey = "papi:last_pull"
|
||||
)
|
||||
|
||||
var (
|
||||
operationMap = map[string]func(*Message, *Papi) error{
|
||||
"decision": DecisionCmd,
|
||||
"alert": AlertCmd,
|
||||
}
|
||||
)
|
||||
|
||||
type Header struct {
|
||||
OperationType string `json:"operation_type"`
|
||||
OperationCmd string `json:"operation_cmd"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Message string `json:"message"`
|
||||
UUID string `json:"uuid"`
|
||||
Source *Source `json:"source"`
|
||||
Destination string `json:"destination"`
|
||||
}
|
||||
|
||||
type Source struct {
|
||||
User string `json:"user"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Header *Header
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
type OperationChannels struct {
|
||||
AddAlertChannel chan []*models.Alert
|
||||
DeleteDecisionChannel chan []*models.Decision
|
||||
}
|
||||
|
||||
type Papi struct {
|
||||
URL string
|
||||
Client *longpollclient.LongPollClient
|
||||
DBClient *database.Client
|
||||
apiClient *apiclient.ApiClient
|
||||
Channels *OperationChannels
|
||||
mu sync.Mutex
|
||||
pullTomb tomb.Tomb
|
||||
syncTomb tomb.Tomb
|
||||
SyncInterval time.Duration
|
||||
consoleConfig *csconfig.ConsoleConfig
|
||||
Logger *log.Entry
|
||||
}
|
||||
|
||||
func NewPAPI(apic *apic, dbClient *database.Client, consoleConfig *csconfig.ConsoleConfig, logLevel log.Level) (*Papi, error) {
|
||||
|
||||
logger := logrus.New()
|
||||
if err := types.ConfigureLogger(logger); err != nil {
|
||||
return &Papi{}, fmt.Errorf("creating papi logger: %s", err)
|
||||
}
|
||||
logger.SetLevel(logLevel)
|
||||
|
||||
longPollClient, err := longpollclient.NewLongPollClient(longpollclient.LongPollClientConfig{
|
||||
Url: *apic.apiClient.PapiURL,
|
||||
Logger: logger,
|
||||
HttpClient: apic.apiClient.GetClient(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return &Papi{}, errors.Wrap(err, "failed to create PAPI client")
|
||||
}
|
||||
|
||||
channels := &OperationChannels{
|
||||
AddAlertChannel: apic.AlertsAddChan,
|
||||
DeleteDecisionChannel: make(chan []*models.Decision),
|
||||
}
|
||||
|
||||
papi := &Papi{
|
||||
URL: apic.apiClient.PapiURL.String(),
|
||||
Client: longPollClient,
|
||||
DBClient: dbClient,
|
||||
Channels: channels,
|
||||
SyncInterval: SyncInterval,
|
||||
mu: sync.Mutex{},
|
||||
pullTomb: tomb.Tomb{},
|
||||
syncTomb: tomb.Tomb{},
|
||||
apiClient: apic.apiClient,
|
||||
consoleConfig: consoleConfig,
|
||||
Logger: logger.WithFields(log.Fields{"interval": SyncInterval.Seconds(), "source": "papi"}),
|
||||
}
|
||||
|
||||
return papi, nil
|
||||
}
|
||||
|
||||
// PullPAPI is the long polling client for real-time decisions from PAPI
|
||||
func (p *Papi) Pull() error {
|
||||
|
||||
defer types.CatchPanic("lapi/PullPAPI")
|
||||
p.Logger.Infof("Starting Polling API Pull")
|
||||
|
||||
lastTimestamp := time.Time{}
|
||||
lastTimestampStr, err := p.DBClient.GetConfigItem(PapiPullKey)
|
||||
if err != nil {
|
||||
p.Logger.Warningf("failed to get last timestamp for papi pull: %s", err)
|
||||
}
|
||||
//value doesn't exist, it's first time we're pulling
|
||||
if lastTimestampStr == nil {
|
||||
binTime, err := lastTimestamp.MarshalText()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to marshal last timestamp")
|
||||
}
|
||||
if err := p.DBClient.SetConfigItem(PapiPullKey, string(binTime)); err != nil {
|
||||
p.Logger.Errorf("error setting papi pull last key: %s", err)
|
||||
} else {
|
||||
p.Logger.Debugf("config item '%s' set in database with value '%s'", PapiPullKey, string(binTime))
|
||||
}
|
||||
} else {
|
||||
if err := lastTimestamp.UnmarshalText([]byte(*lastTimestampStr)); err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal last timestamp")
|
||||
}
|
||||
}
|
||||
|
||||
p.Logger.Infof("Starting PAPI pull (since:%s)", lastTimestamp)
|
||||
for event := range p.Client.Start(lastTimestamp) {
|
||||
logger := p.Logger.WithField("request-id", event.RequestId)
|
||||
//update last timestamp in database
|
||||
newTime := time.Now().UTC()
|
||||
binTime, err := newTime.MarshalText()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to marshal last timestamp")
|
||||
}
|
||||
logger.Debugf("message received: %+v", event.Data)
|
||||
message := &Message{}
|
||||
if err := json.Unmarshal([]byte(event.Data), message); err != nil {
|
||||
logger.Errorf("polling papi message format is not compatible: %+v: %s", event.Data, err)
|
||||
// do we want to continue or exit ?
|
||||
continue
|
||||
}
|
||||
|
||||
if message.Header == nil {
|
||||
logger.Errorf("no header in message, skipping")
|
||||
continue
|
||||
}
|
||||
|
||||
if message.Header.Source == nil {
|
||||
logger.Errorf("no source user in header message, skipping")
|
||||
continue
|
||||
}
|
||||
|
||||
if operationFunc, ok := operationMap[message.Header.OperationType]; ok {
|
||||
logger.Debugf("Calling operation '%s'", message.Header.OperationType)
|
||||
err := operationFunc(message, p)
|
||||
if err != nil {
|
||||
logger.Errorf("'%s %s failed: %s", message.Header.OperationType, message.Header.OperationCmd, err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
logger.Errorf("operation '%s' unknown, continue", message.Header.OperationType)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := p.DBClient.SetConfigItem(PapiPullKey, string(binTime)); err != nil {
|
||||
return errors.Wrap(err, "failed to update last timestamp")
|
||||
} else {
|
||||
logger.Debugf("set last timestamp to %s", newTime)
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Papi) SyncDecisions() error {
|
||||
defer types.CatchPanic("lapi/syncDecisionsToCAPI")
|
||||
|
||||
var cache models.DecisionsDeleteRequest
|
||||
ticker := time.NewTicker(p.SyncInterval)
|
||||
p.Logger.Infof("Start decisions sync to CrowdSec Central API (interval: %s)", p.SyncInterval)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-p.syncTomb.Dying(): // if one apic routine is dying, do we kill the others?
|
||||
p.Logger.Infof("sync decisions tomb is dying, sending cache (%d elements) before exiting", len(cache))
|
||||
if len(cache) == 0 {
|
||||
return nil
|
||||
}
|
||||
go p.SendDeletedDecisions(&cache)
|
||||
return nil
|
||||
case <-ticker.C:
|
||||
if len(cache) > 0 {
|
||||
p.mu.Lock()
|
||||
cacheCopy := cache
|
||||
cache = make([]models.DecisionsDeleteRequestItem, 0)
|
||||
p.mu.Unlock()
|
||||
p.Logger.Infof("sync decisions: %d deleted decisions to push", len(cacheCopy))
|
||||
go p.SendDeletedDecisions(&cacheCopy)
|
||||
}
|
||||
case deletedDecisions := <-p.Channels.DeleteDecisionChannel:
|
||||
if (p.consoleConfig.ShareManualDecisions != nil && *p.consoleConfig.ShareManualDecisions) || (p.consoleConfig.ReceiveDecisions != nil && *p.consoleConfig.ReceiveDecisions) {
|
||||
var tmpDecisions []models.DecisionsDeleteRequestItem
|
||||
p.Logger.Debugf("%d decisions deletion to add in cache", len(deletedDecisions))
|
||||
for _, decision := range deletedDecisions {
|
||||
tmpDecisions = append(tmpDecisions, models.DecisionsDeleteRequestItem(decision.UUID))
|
||||
}
|
||||
p.mu.Lock()
|
||||
cache = append(cache, tmpDecisions...)
|
||||
p.mu.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Papi) SendDeletedDecisions(cacheOrig *models.DecisionsDeleteRequest) {
|
||||
|
||||
var cache []models.DecisionsDeleteRequestItem = *cacheOrig
|
||||
var send models.DecisionsDeleteRequest
|
||||
|
||||
bulkSize := 50
|
||||
pageStart := 0
|
||||
pageEnd := bulkSize
|
||||
for {
|
||||
if pageEnd >= len(cache) {
|
||||
send = cache[pageStart:]
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
_, _, err := p.apiClient.DecisionDelete.Add(ctx, &send)
|
||||
if err != nil {
|
||||
p.Logger.Errorf("sending deleted decisions to central API: %s", err)
|
||||
return
|
||||
}
|
||||
break
|
||||
}
|
||||
send = cache[pageStart:pageEnd]
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
_, _, err := p.apiClient.DecisionDelete.Add(ctx, &send)
|
||||
if err != nil {
|
||||
//we log it here as well, because the return value of func might be discarded
|
||||
p.Logger.Errorf("sending deleted decisions to central API: %s", err)
|
||||
}
|
||||
pageStart += bulkSize
|
||||
pageEnd += bulkSize
|
||||
}
|
||||
}
|
132
pkg/apiserver/papi_cmd.go
Normal file
132
pkg/apiserver/papi_cmd.go
Normal file
|
@ -0,0 +1,132 @@
|
|||
package apiserver
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/models"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type deleteDecisions struct {
|
||||
UUID string `json:"uuid"`
|
||||
Decisions []string `json:"decisions"`
|
||||
}
|
||||
|
||||
func DecisionCmd(message *Message, p *Papi) error {
|
||||
switch message.Header.OperationCmd {
|
||||
case "delete":
|
||||
|
||||
data, err := json.Marshal(message.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
UUIDs := make([]string, 0)
|
||||
deleteDecisionMsg := deleteDecisions{
|
||||
Decisions: make([]string, 0),
|
||||
}
|
||||
if err := json.Unmarshal(data, &deleteDecisionMsg); err != nil {
|
||||
return fmt.Errorf("message for '%s' contains bad data format: %s", message.Header.OperationType, err)
|
||||
}
|
||||
|
||||
UUIDs = append(UUIDs, deleteDecisionMsg.Decisions...)
|
||||
log.Infof("Decisions UUIDs to remove: %+v", UUIDs)
|
||||
|
||||
filter := make(map[string][]string)
|
||||
filter["uuid"] = UUIDs
|
||||
_, deletedDecisions, err := p.DBClient.SoftDeleteDecisionsWithFilter(filter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to delete decisions %+v : %s", UUIDs, err)
|
||||
}
|
||||
decisions := make([]*models.Decision, 0)
|
||||
for _, deletedDecision := range deletedDecisions {
|
||||
log.Infof("Decision from '%s' for '%s' (%s) has been deleted", deletedDecision.Origin, deletedDecision.Value, deletedDecision.Type)
|
||||
dec := &models.Decision{
|
||||
UUID: deletedDecision.UUID,
|
||||
Origin: &deletedDecision.Origin,
|
||||
Scenario: &deletedDecision.Scenario,
|
||||
Scope: &deletedDecision.Scope,
|
||||
Value: &deletedDecision.Value,
|
||||
ID: int64(deletedDecision.ID),
|
||||
Until: deletedDecision.Until.String(),
|
||||
Type: &deletedDecision.Type,
|
||||
}
|
||||
decisions = append(decisions, dec)
|
||||
}
|
||||
p.Channels.DeleteDecisionChannel <- decisions
|
||||
default:
|
||||
return fmt.Errorf("unknown command '%s' for operation type '%s'", message.Header.OperationCmd, message.Header.OperationType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func AlertCmd(message *Message, p *Papi) error {
|
||||
switch message.Header.OperationCmd {
|
||||
case "add":
|
||||
data, err := json.Marshal(message.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
alert := &models.Alert{}
|
||||
|
||||
if err := json.Unmarshal(data, alert); err != nil {
|
||||
return errors.Wrapf(err, "message for '%s' contains bad alert format", message.Header.OperationType)
|
||||
}
|
||||
|
||||
log.Infof("Received order %s from PAPI (%d decisions)", alert.UUID, len(alert.Decisions))
|
||||
|
||||
/*Fix the alert with missing mandatory items*/
|
||||
if alert.StartAt == nil || *alert.StartAt == "" {
|
||||
log.Warnf("Alert %d has no StartAt, setting it to now", alert.ID)
|
||||
alert.StartAt = types.StrPtr(time.Now().UTC().Format(time.RFC3339))
|
||||
}
|
||||
if alert.StopAt == nil || *alert.StopAt == "" {
|
||||
log.Warnf("Alert %d has no StopAt, setting it to now", alert.ID)
|
||||
alert.StopAt = types.StrPtr(time.Now().UTC().Format(time.RFC3339))
|
||||
}
|
||||
alert.EventsCount = types.Int32Ptr(0)
|
||||
alert.Capacity = types.Int32Ptr(0)
|
||||
alert.Leakspeed = types.StrPtr("")
|
||||
alert.Simulated = types.BoolPtr(false)
|
||||
alert.ScenarioHash = types.StrPtr("")
|
||||
alert.ScenarioVersion = types.StrPtr("")
|
||||
alert.Message = types.StrPtr("")
|
||||
alert.Scenario = types.StrPtr("")
|
||||
alert.Source = &models.Source{}
|
||||
|
||||
//if we're setting Source.Scope to types.ConsoleOrigin, it messes up the alert's value
|
||||
if len(alert.Decisions) >= 1 {
|
||||
alert.Source.Scope = alert.Decisions[0].Scope
|
||||
alert.Source.Value = alert.Decisions[0].Value
|
||||
} else {
|
||||
log.Warningf("No decision found in alert for Polling API (%s : %s)", message.Header.Source.User, message.Header.Message)
|
||||
alert.Source.Scope = types.StrPtr(types.ConsoleOrigin)
|
||||
alert.Source.Value = &message.Header.Source.User
|
||||
}
|
||||
alert.Scenario = &message.Header.Message
|
||||
|
||||
for _, decision := range alert.Decisions {
|
||||
if *decision.Scenario == "" {
|
||||
decision.Scenario = &message.Header.Message
|
||||
}
|
||||
log.Infof("Adding decision for '%s' with UUID: %s", *decision.Value, decision.UUID)
|
||||
}
|
||||
|
||||
//use a different method : alert and/or decision might already be partially present in the database
|
||||
_, err = p.DBClient.CreateOrUpdateAlert("", alert)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to create alerts in DB: %s", err)
|
||||
} else {
|
||||
p.Channels.AddAlertChannel <- []*models.Alert{alert}
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown command '%s' for operation type '%s'", message.Header.OperationCmd, message.Header.OperationType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -25,6 +25,7 @@ type APICfg struct {
|
|||
}
|
||||
|
||||
type ApiCredentialsCfg struct {
|
||||
PapiURL string `yaml:"papi_url,omitempty" json:"papi_url,omitempty"`
|
||||
URL string `yaml:"url,omitempty" json:"url,omitempty"`
|
||||
Login string `yaml:"login,omitempty" json:"login,omitempty"`
|
||||
Password string `yaml:"password,omitempty" json:"-"`
|
||||
|
@ -91,6 +92,7 @@ func (o *OnlineApiClientCfg) Load() error {
|
|||
log.Warningf("can't load CAPI credentials from '%s' (missing field)", o.CredentialsFilePath)
|
||||
o.Credentials = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -192,6 +194,7 @@ type LocalApiServerCfg struct {
|
|||
LogMaxAge int `yaml:"-"`
|
||||
LogMaxFiles int `yaml:"-"`
|
||||
TrustedIPs []string `yaml:"trusted_ips,omitempty"`
|
||||
PapiLogLevel *log.Level `yaml:"papi_log_level"`
|
||||
}
|
||||
|
||||
type TLSCfg struct {
|
||||
|
@ -211,8 +214,35 @@ func (c *Config) LoadAPIServer() error {
|
|||
log.Warning("crowdsec local API is disabled from flag")
|
||||
}
|
||||
|
||||
if c.API.Server == nil {
|
||||
log.Warning("crowdsec local API is disabled because its configuration is not present")
|
||||
if c.API.Server != nil {
|
||||
|
||||
//inherit log level from common, then api->server
|
||||
var logLevel log.Level
|
||||
if c.API.Server.LogLevel != nil {
|
||||
logLevel = *c.API.Server.LogLevel
|
||||
} else if c.Common.LogLevel != nil {
|
||||
logLevel = *c.Common.LogLevel
|
||||
} else {
|
||||
logLevel = log.InfoLevel
|
||||
}
|
||||
|
||||
if c.API.Server.PapiLogLevel == nil {
|
||||
c.API.Server.PapiLogLevel = &logLevel
|
||||
}
|
||||
|
||||
if c.API.Server.OnlineClient != nil && c.API.Server.OnlineClient.CredentialsFilePath != "" {
|
||||
if err := c.API.Server.OnlineClient.Load(); err != nil {
|
||||
return errors.Wrap(err, "loading online client credentials")
|
||||
}
|
||||
}
|
||||
if c.API.Server.OnlineClient == nil || c.API.Server.OnlineClient.Credentials == nil {
|
||||
log.Printf("push and pull to Central API disabled")
|
||||
}
|
||||
if err := c.LoadDBConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Warning("crowdsec local API is disabled")
|
||||
c.DisableAPI = true
|
||||
return nil
|
||||
}
|
||||
|
@ -272,10 +302,6 @@ func (c *Config) LoadAPIServer() error {
|
|||
}
|
||||
}
|
||||
|
||||
if err := c.LoadDBConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
package csconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/cstest"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
)
|
||||
|
||||
func TestLoadLocalApiClientCfg(t *testing.T) {
|
||||
|
@ -143,7 +146,7 @@ func TestLoadAPIServer(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
logLevel := log.InfoLevel
|
||||
config := &Config{}
|
||||
fcontent, err := os.ReadFile("./tests/config.yaml")
|
||||
if err != nil {
|
||||
|
@ -171,6 +174,7 @@ func TestLoadAPIServer(t *testing.T) {
|
|||
CredentialsFilePath: "./tests/online-api-secrets.yaml",
|
||||
},
|
||||
ProfilesPath: "./tests/profiles.yaml",
|
||||
PapiLogLevel: &logLevel,
|
||||
},
|
||||
},
|
||||
DbConfig: &DatabaseCfg{
|
||||
|
@ -198,6 +202,7 @@ func TestLoadAPIServer(t *testing.T) {
|
|||
ShareTaintedScenarios: types.BoolPtr(true),
|
||||
ShareCustomScenarios: types.BoolPtr(true),
|
||||
ShareContext: types.BoolPtr(false),
|
||||
ReceiveDecisions: types.BoolPtr(false),
|
||||
},
|
||||
LogDir: LogDirFullPath,
|
||||
LogMedia: "stdout",
|
||||
|
@ -212,6 +217,7 @@ func TestLoadAPIServer(t *testing.T) {
|
|||
Profiles: tmpLAPI.Profiles,
|
||||
ProfilesPath: "./tests/profiles.yaml",
|
||||
UseForwardedForHeaders: false,
|
||||
PapiLogLevel: &logLevel,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -228,24 +234,27 @@ func TestLoadAPIServer(t *testing.T) {
|
|||
DisableAPI: false,
|
||||
},
|
||||
expected: &LocalApiServerCfg{
|
||||
Enable: types.BoolPtr(true),
|
||||
LogDir: LogDirFullPath,
|
||||
LogMedia: "stdout",
|
||||
PapiLogLevel: &logLevel,
|
||||
},
|
||||
expectedErr: "while loading profiles for LAPI",
|
||||
expectedErr: "no database configuration provided",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := tc.input.LoadAPIServer()
|
||||
cstest.RequireErrorContains(t, err, tc.expectedErr)
|
||||
if tc.expectedErr != "" {
|
||||
return
|
||||
for idx, test := range tests {
|
||||
err := test.input.LoadAPIServer()
|
||||
if err == nil && test.expectedErr != "" {
|
||||
fmt.Printf("TEST '%s': NOK\n", test.name)
|
||||
t.Fatalf("Test number %d/%d expected error, didn't get it", idx+1, len(tests))
|
||||
} else if test.expectedErr != "" {
|
||||
fmt.Printf("ERR: %+v\n", err)
|
||||
if !strings.HasPrefix(fmt.Sprintf("%s", err), test.expectedErr) {
|
||||
fmt.Printf("TEST '%s': NOK\n", test.name)
|
||||
t.Fatalf("%d/%d expected '%s' got '%s'", idx, len(tests),
|
||||
test.expectedErr,
|
||||
fmt.Sprintf("%s", err))
|
||||
}
|
||||
|
||||
assert.Equal(t, tc.expected, tc.input.API.Server)
|
||||
})
|
||||
assert.Equal(t, test.expected, test.input.API.Server)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/fflag"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
@ -14,10 +15,11 @@ const (
|
|||
SEND_CUSTOM_SCENARIOS = "custom"
|
||||
SEND_TAINTED_SCENARIOS = "tainted"
|
||||
SEND_MANUAL_SCENARIOS = "manual"
|
||||
CONSOLE_MANAGEMENT = "console_management"
|
||||
SEND_CONTEXT = "context"
|
||||
)
|
||||
|
||||
var CONSOLE_CONFIGS = []string{SEND_CUSTOM_SCENARIOS, SEND_MANUAL_SCENARIOS, SEND_TAINTED_SCENARIOS, SEND_CONTEXT}
|
||||
var CONSOLE_CONFIGS = []string{SEND_CUSTOM_SCENARIOS, SEND_MANUAL_SCENARIOS, SEND_TAINTED_SCENARIOS, SEND_CONTEXT, CONSOLE_MANAGEMENT}
|
||||
|
||||
var DefaultConsoleConfigFilePath = DefaultConfigPath("console.yaml")
|
||||
|
||||
|
@ -25,6 +27,7 @@ type ConsoleConfig struct {
|
|||
ShareManualDecisions *bool `yaml:"share_manual_decisions"`
|
||||
ShareTaintedScenarios *bool `yaml:"share_tainted"`
|
||||
ShareCustomScenarios *bool `yaml:"share_custom"`
|
||||
ReceiveDecisions *bool `yaml:"console_management"`
|
||||
ShareContext *bool `yaml:"share_context"`
|
||||
}
|
||||
|
||||
|
@ -35,6 +38,7 @@ func (c *LocalApiServerCfg) LoadConsoleConfig() error {
|
|||
c.ConsoleConfig.ShareCustomScenarios = types.BoolPtr(true)
|
||||
c.ConsoleConfig.ShareTaintedScenarios = types.BoolPtr(true)
|
||||
c.ConsoleConfig.ShareManualDecisions = types.BoolPtr(false)
|
||||
c.ConsoleConfig.ReceiveDecisions = types.BoolPtr(false)
|
||||
c.ConsoleConfig.ShareContext = types.BoolPtr(false)
|
||||
return nil
|
||||
}
|
||||
|
@ -61,6 +65,13 @@ func (c *LocalApiServerCfg) LoadConsoleConfig() error {
|
|||
c.ConsoleConfig.ShareManualDecisions = types.BoolPtr(false)
|
||||
}
|
||||
|
||||
if !fflag.PapiClient.IsEnabled() {
|
||||
c.ConsoleConfig.ReceiveDecisions = types.BoolPtr(false)
|
||||
} else if c.ConsoleConfig.ReceiveDecisions == nil {
|
||||
log.Debugf("no console_management found, setting to false")
|
||||
c.ConsoleConfig.ReceiveDecisions = types.BoolPtr(false)
|
||||
}
|
||||
|
||||
if c.ConsoleConfig.ShareContext == nil {
|
||||
log.Debugf("no 'context' found, setting to false")
|
||||
c.ConsoleConfig.ShareContext = types.BoolPtr(false)
|
||||
|
|
|
@ -147,7 +147,7 @@ func (Profile *Runtime) GenerateDecisionFromProfile(Alert *models.Alert) ([]*mod
|
|||
decision.Value = new(string)
|
||||
*decision.Value = *Alert.Source.Value
|
||||
decision.Origin = new(string)
|
||||
*decision.Origin = "crowdsec"
|
||||
*decision.Origin = types.CrowdSecOrigin
|
||||
if refDecision.Origin != nil {
|
||||
*decision.Origin = fmt.Sprintf("%s/%s", *decision.Origin, *refDecision.Origin)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -64,16 +65,19 @@ func formatAlertAsString(machineId string, alert *models.Alert) []string {
|
|||
|
||||
/**/
|
||||
reason := ""
|
||||
if *alert.Scenario != "" {
|
||||
reason = fmt.Sprintf("%s by %s", *alert.Scenario, src)
|
||||
} else if *alert.Message != "" {
|
||||
reason = fmt.Sprintf("%s by %s", *alert.Scenario, src)
|
||||
msg := ""
|
||||
if alert.Scenario != nil && *alert.Scenario != "" {
|
||||
msg = *alert.Scenario
|
||||
} else if alert.Message != nil && *alert.Message != "" {
|
||||
msg = *alert.Message
|
||||
} else {
|
||||
reason = fmt.Sprintf("empty scenario by %s", src)
|
||||
msg = fmt.Sprintf("empty scenario by %s", src)
|
||||
}
|
||||
|
||||
reason = fmt.Sprintf("%s by %s", msg, src)
|
||||
|
||||
if len(alert.Decisions) > 0 {
|
||||
for _, decisionItem := range alert.Decisions {
|
||||
for i, decisionItem := range alert.Decisions {
|
||||
decision := ""
|
||||
if alert.Simulated != nil && *alert.Simulated {
|
||||
decision = "(simulated alert)"
|
||||
|
@ -84,11 +88,20 @@ func formatAlertAsString(machineId string, alert *models.Alert) []string {
|
|||
/*spew is expensive*/
|
||||
log.Debugf("%s", spew.Sdump(decisionItem))
|
||||
}
|
||||
if len(alert.Decisions) > 1 {
|
||||
reason = fmt.Sprintf("%s for %d/%d decisions", msg, i+1, len(alert.Decisions))
|
||||
}
|
||||
machineIdOrigin := ""
|
||||
if machineId == "" {
|
||||
machineIdOrigin = *decisionItem.Origin
|
||||
} else {
|
||||
machineIdOrigin = fmt.Sprintf("%s/%s", machineId, *decisionItem.Origin)
|
||||
}
|
||||
|
||||
decision += fmt.Sprintf("%s %s on %s %s", *decisionItem.Duration,
|
||||
*decisionItem.Type, *decisionItem.Scope, *decisionItem.Value)
|
||||
retStr = append(retStr,
|
||||
fmt.Sprintf("(%s/%s) %s : %s", machineId,
|
||||
*decisionItem.Origin, reason, decision))
|
||||
fmt.Sprintf("(%s) %s : %s", machineIdOrigin, reason, decision))
|
||||
}
|
||||
} else {
|
||||
retStr = append(retStr, fmt.Sprintf("(%s) alert : %s", machineId, reason))
|
||||
|
@ -96,6 +109,149 @@ func formatAlertAsString(machineId string, alert *models.Alert) []string {
|
|||
return retStr
|
||||
}
|
||||
|
||||
// CreateOrUpdateAlert is specific to PAPI : It checks if alert already exists, otherwise inserts it
|
||||
// if alert already exists, it checks it associated decisions already exists
|
||||
// if some associated decisions are missing (ie. previous insert ended up in error) it inserts them
|
||||
func (c *Client) CreateOrUpdateAlert(machineID string, alertItem *models.Alert) (string, error) {
|
||||
|
||||
if alertItem.UUID == "" {
|
||||
return "", fmt.Errorf("alert UUID is empty")
|
||||
}
|
||||
|
||||
alerts, err := c.Ent.Alert.Query().Where(alert.UUID(alertItem.UUID)).WithDecisions().All(c.CTX)
|
||||
|
||||
if err != nil && !ent.IsNotFound(err) {
|
||||
return "", errors.Wrap(err, "unable to query alerts for uuid %s")
|
||||
}
|
||||
|
||||
//alert wasn't found, insert it (expected hotpath)
|
||||
if ent.IsNotFound(err) || len(alerts) == 0 {
|
||||
ret, err := c.CreateAlert(machineID, []*models.Alert{alertItem})
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "unable to create alert")
|
||||
}
|
||||
return ret[0], nil
|
||||
}
|
||||
|
||||
//this should never happen
|
||||
if len(alerts) > 1 {
|
||||
return "", fmt.Errorf("multiple alerts found for uuid %s", alertItem.UUID)
|
||||
}
|
||||
|
||||
log.Infof("Alert %s already exists, checking associated decisions", alertItem.UUID)
|
||||
//alert is found, check for any missing decisions
|
||||
missingUuids := []string{}
|
||||
newUuids := []string{}
|
||||
for _, decItem := range alertItem.Decisions {
|
||||
newUuids = append(newUuids, decItem.UUID)
|
||||
}
|
||||
|
||||
foundAlert := alerts[0]
|
||||
foundUuids := []string{}
|
||||
for _, decItem := range foundAlert.Edges.Decisions {
|
||||
foundUuids = append(foundUuids, decItem.UUID)
|
||||
}
|
||||
|
||||
sort.Strings(foundUuids)
|
||||
sort.Strings(newUuids)
|
||||
|
||||
for idx, uuid := range newUuids {
|
||||
if len(foundUuids) < idx+1 || uuid != foundUuids[idx] {
|
||||
log.Warningf("Decision with uuid %s not found in alert %s", uuid, foundAlert.UUID)
|
||||
missingUuids = append(missingUuids, uuid)
|
||||
}
|
||||
}
|
||||
|
||||
//add any and all missing decisions based on their uuids
|
||||
if len(missingUuids) > 0 {
|
||||
//prepare missing decisions
|
||||
missingDecisions := []*models.Decision{}
|
||||
for _, uuid := range missingUuids {
|
||||
for _, newDecision := range alertItem.Decisions {
|
||||
if newDecision.UUID == uuid {
|
||||
missingDecisions = append(missingDecisions, newDecision)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//add missing decisions
|
||||
log.Debugf("Adding %d missing decisions to alert %s", len(missingDecisions), foundAlert.UUID)
|
||||
|
||||
decisions := make([]*ent.Decision, 0)
|
||||
decisionBulk := make([]*ent.DecisionCreate, 0, decisionBulkSize)
|
||||
|
||||
for i, decisionItem := range missingDecisions {
|
||||
var start_ip, start_sfx, end_ip, end_sfx int64
|
||||
var sz int
|
||||
|
||||
/*if the scope is IP or Range, convert the value to integers */
|
||||
if strings.ToLower(*decisionItem.Scope) == "ip" || strings.ToLower(*decisionItem.Scope) == "range" {
|
||||
sz, start_ip, start_sfx, end_ip, end_sfx, err = types.Addr2Ints(*decisionItem.Value)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(ParseDurationFail, "invalid addr/range %s : %s", *decisionItem.Value, err)
|
||||
}
|
||||
}
|
||||
decisionDuration, err := time.ParseDuration(*decisionItem.Duration)
|
||||
if err != nil {
|
||||
log.Warningf("invalid duration %s for decision %s", *decisionItem.Duration, decisionItem.UUID)
|
||||
continue
|
||||
}
|
||||
//use the created_at from the alert instead
|
||||
alertTime, err := time.Parse(time.RFC3339, alertItem.CreatedAt)
|
||||
if err != nil {
|
||||
log.Errorf("unable to parse alert time %s : %s", alertItem.CreatedAt, err)
|
||||
alertTime = time.Now()
|
||||
}
|
||||
decisionUntil := alertTime.UTC().Add(decisionDuration)
|
||||
|
||||
decisionCreate := c.Ent.Decision.Create().
|
||||
SetUntil(decisionUntil).
|
||||
SetScenario(*decisionItem.Scenario).
|
||||
SetType(*decisionItem.Type).
|
||||
SetStartIP(start_ip).
|
||||
SetStartSuffix(start_sfx).
|
||||
SetEndIP(end_ip).
|
||||
SetEndSuffix(end_sfx).
|
||||
SetIPSize(int64(sz)).
|
||||
SetValue(*decisionItem.Value).
|
||||
SetScope(*decisionItem.Scope).
|
||||
SetOrigin(*decisionItem.Origin).
|
||||
SetSimulated(*alertItem.Simulated).
|
||||
SetUUID(decisionItem.UUID)
|
||||
|
||||
decisionBulk = append(decisionBulk, decisionCreate)
|
||||
if len(decisionBulk) == decisionBulkSize {
|
||||
decisionsCreateRet, err := c.Ent.Decision.CreateBulk(decisionBulk...).Save(c.CTX)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(BulkError, "creating alert decisions: %s", err)
|
||||
|
||||
}
|
||||
decisions = append(decisions, decisionsCreateRet...)
|
||||
if len(missingDecisions)-i <= decisionBulkSize {
|
||||
decisionBulk = make([]*ent.DecisionCreate, 0, (len(missingDecisions) - i))
|
||||
} else {
|
||||
decisionBulk = make([]*ent.DecisionCreate, 0, decisionBulkSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
decisionsCreateRet, err := c.Ent.Decision.CreateBulk(decisionBulk...).Save(c.CTX)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(BulkError, "creating alert decisions: %s", err)
|
||||
}
|
||||
decisions = append(decisions, decisionsCreateRet...)
|
||||
//now that we bulk created missing decisions, let's update the alert
|
||||
err = c.Ent.Alert.Update().Where(alert.UUID(alertItem.UUID)).AddDecisions(decisions...).Exec(c.CTX)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "updating alert %s : %s", alertItem.UUID, err)
|
||||
}
|
||||
} else {
|
||||
log.Warningf("alert %s was already complete with decisions %+v", alertItem.UUID, foundUuids)
|
||||
}
|
||||
|
||||
return "", nil
|
||||
|
||||
}
|
||||
|
||||
func (c *Client) CreateAlert(machineID string, alertList []*models.Alert) ([]string, error) {
|
||||
pageStart := 0
|
||||
pageEnd := bulkSize
|
||||
|
@ -337,6 +493,21 @@ func chunkDecisions(decisions []*ent.Decision, chunkSize int) [][]*ent.Decision
|
|||
func (c *Client) CreateAlertBulk(machineId string, alertList []*models.Alert) ([]string, error) {
|
||||
ret := []string{}
|
||||
bulkSize := 20
|
||||
var owner *ent.Machine
|
||||
var err error
|
||||
|
||||
if machineId != "" {
|
||||
owner, err = c.QueryMachineByID(machineId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) != UserNotExists {
|
||||
return []string{}, errors.Wrapf(QueryFail, "machine '%s': %s", machineId, err)
|
||||
}
|
||||
c.Log.Debugf("CreateAlertBulk: Machine Id %s doesn't exist", machineId)
|
||||
owner = nil
|
||||
}
|
||||
} else {
|
||||
owner = nil
|
||||
}
|
||||
|
||||
c.Log.Debugf("writing %d items", len(alertList))
|
||||
bulk := make([]*ent.AlertCreate, 0, bulkSize)
|
||||
|
@ -346,14 +517,6 @@ func (c *Client) CreateAlertBulk(machineId string, alertList []*models.Alert) ([
|
|||
var metas []*ent.Meta
|
||||
var events []*ent.Event
|
||||
|
||||
owner, err := c.QueryMachineByID(machineId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) != UserNotExists {
|
||||
return []string{}, errors.Wrapf(QueryFail, "machine '%s': %s", alertItem.MachineID, err)
|
||||
}
|
||||
c.Log.Debugf("CreateAlertBulk: Machine Id %s doesn't exist", machineId)
|
||||
owner = nil
|
||||
}
|
||||
startAtTime, err := time.Parse(time.RFC3339, *alertItem.StartAt)
|
||||
if err != nil {
|
||||
c.Log.Errorf("CreateAlertBulk: Failed to parse startAtTime '%s', defaulting to now: %s", *alertItem.StartAt, err)
|
||||
|
@ -480,7 +643,8 @@ func (c *Client) CreateAlertBulk(machineId string, alertList []*models.Alert) ([
|
|||
SetValue(*decisionItem.Value).
|
||||
SetScope(*decisionItem.Scope).
|
||||
SetOrigin(*decisionItem.Origin).
|
||||
SetSimulated(*alertItem.Simulated)
|
||||
SetSimulated(*alertItem.Simulated).
|
||||
SetUUID(decisionItem.UUID)
|
||||
|
||||
decisionBulk = append(decisionBulk, decisionCreate)
|
||||
if len(decisionBulk) == decisionBulkSize {
|
||||
|
@ -525,6 +689,7 @@ func (c *Client) CreateAlertBulk(machineId string, alertList []*models.Alert) ([
|
|||
SetSimulated(*alertItem.Simulated).
|
||||
SetScenarioVersion(*alertItem.ScenarioVersion).
|
||||
SetScenarioHash(*alertItem.ScenarioHash).
|
||||
SetUUID(alertItem.UUID).
|
||||
AddEvents(events...).
|
||||
AddMetas(metas...)
|
||||
|
||||
|
@ -661,7 +826,11 @@ func AlertPredicatesFromFilter(filter map[string][]string) ([]predicate.Alert, e
|
|||
predicates = append(predicates, alert.HasDecisionsWith(decision.OriginEQ(value[0])))
|
||||
case "include_capi": //allows to exclude one or more specific origins
|
||||
if value[0] == "false" {
|
||||
predicates = append(predicates, alert.HasDecisionsWith(decision.Or(decision.OriginEQ("crowdsec"), decision.OriginEQ("cscli"))))
|
||||
predicates = append(predicates, alert.HasDecisionsWith(
|
||||
decision.Or(decision.OriginEQ(types.CrowdSecOrigin),
|
||||
decision.OriginEQ(types.CscliOrigin),
|
||||
decision.OriginEQ(types.ConsoleOrigin),
|
||||
decision.OriginEQ(types.CscliImportOrigin))))
|
||||
} else if value[0] != "true" {
|
||||
log.Errorf("Invalid bool '%s' for include_capi", value[0])
|
||||
}
|
||||
|
|
33
pkg/database/config.go
Normal file
33
pkg/database/config.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/configitem"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (c *Client) GetConfigItem(key string) (*string, error) {
|
||||
result, err := c.Ent.ConfigItem.Query().Where(configitem.NameEQ(key)).First(c.CTX)
|
||||
if err != nil && ent.IsNotFound(err) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(QueryFail, "select config item: %s", err)
|
||||
}
|
||||
|
||||
return &result.Value, nil
|
||||
}
|
||||
|
||||
func (c *Client) SetConfigItem(key string, value string) error {
|
||||
|
||||
nbUpdated, err := c.Ent.ConfigItem.Update().SetValue(value).Where(configitem.NameEQ(key)).Save(c.CTX)
|
||||
if (err != nil && ent.IsNotFound(err)) || nbUpdated == 0 { //not found, create
|
||||
err := c.Ent.ConfigItem.Create().SetName(key).SetValue(value).Exec(c.CTX)
|
||||
if err != nil {
|
||||
return errors.Wrapf(QueryFail, "insert config item: %s", err)
|
||||
}
|
||||
} else if err != nil {
|
||||
return errors.Wrapf(QueryFail, "update config item: %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -269,16 +269,18 @@ func (c *Client) QueryNewDecisionsSinceWithFilters(since time.Time, filters map[
|
|||
return data, nil
|
||||
}
|
||||
|
||||
func (c *Client) DeleteDecisionById(decisionId int) error {
|
||||
err := c.Ent.Decision.DeleteOneID(decisionId).Exec(c.CTX)
|
||||
func (c *Client) DeleteDecisionById(decisionId int) ([]*ent.Decision, error) {
|
||||
toDelete, err := c.Ent.Decision.Query().Where(decision.IDEQ(decisionId)).All(c.CTX)
|
||||
if err != nil {
|
||||
c.Log.Warningf("DeleteDecisionById : %s", err)
|
||||
return errors.Wrapf(DeleteFail, "decision with id '%d' doesn't exist", decisionId)
|
||||
return nil, errors.Wrapf(DeleteFail, "decision with id '%d' doesn't exist", decisionId)
|
||||
}
|
||||
return nil
|
||||
count, err := c.BulkDeleteDecisions(toDelete, false)
|
||||
c.Log.Debugf("deleted %d decisions", count)
|
||||
return toDelete, err
|
||||
}
|
||||
|
||||
func (c *Client) DeleteDecisionsWithFilter(filter map[string][]string) (string, error) {
|
||||
func (c *Client) DeleteDecisionsWithFilter(filter map[string][]string) (string, []*ent.Decision, error) {
|
||||
var err error
|
||||
var start_ip, start_sfx, end_ip, end_sfx int64
|
||||
var ip_sz int
|
||||
|
@ -286,13 +288,13 @@ func (c *Client) DeleteDecisionsWithFilter(filter map[string][]string) (string,
|
|||
/*if contains is true, return bans that *contains* the given value (value is the inner)
|
||||
else, return bans that are *contained* by the given value (value is the outer) */
|
||||
|
||||
decisions := c.Ent.Decision.Delete()
|
||||
decisions := c.Ent.Decision.Query()
|
||||
for param, value := range filter {
|
||||
switch param {
|
||||
case "contains":
|
||||
contains, err = strconv.ParseBool(value[0])
|
||||
if err != nil {
|
||||
return "0", errors.Wrapf(InvalidFilter, "invalid contains value : %s", err)
|
||||
return "0", nil, errors.Wrapf(InvalidFilter, "invalid contains value : %s", err)
|
||||
}
|
||||
case "scope":
|
||||
decisions = decisions.Where(decision.ScopeEQ(value[0]))
|
||||
|
@ -303,12 +305,12 @@ func (c *Client) DeleteDecisionsWithFilter(filter map[string][]string) (string,
|
|||
case "ip", "range":
|
||||
ip_sz, start_ip, start_sfx, end_ip, end_sfx, err = types.Addr2Ints(value[0])
|
||||
if err != nil {
|
||||
return "0", errors.Wrapf(InvalidIPOrRange, "unable to convert '%s' to int: %s", value[0], err)
|
||||
return "0", nil, errors.Wrapf(InvalidIPOrRange, "unable to convert '%s' to int: %s", value[0], err)
|
||||
}
|
||||
case "scenario":
|
||||
decisions = decisions.Where(decision.ScenarioEQ(value[0]))
|
||||
default:
|
||||
return "0", errors.Wrap(InvalidFilter, fmt.Sprintf("'%s' doesn't exist", param))
|
||||
return "0", nil, errors.Wrap(InvalidFilter, fmt.Sprintf("'%s' doesn't exist", param))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,35 +379,42 @@ func (c *Client) DeleteDecisionsWithFilter(filter map[string][]string) (string,
|
|||
))
|
||||
}
|
||||
} else if ip_sz != 0 {
|
||||
return "0", errors.Wrapf(InvalidFilter, "Unknown ip size %d", ip_sz)
|
||||
return "0", nil, errors.Wrapf(InvalidFilter, "Unknown ip size %d", ip_sz)
|
||||
}
|
||||
|
||||
nbDeleted, err := decisions.Exec(c.CTX)
|
||||
toDelete, err := decisions.All(c.CTX)
|
||||
if err != nil {
|
||||
c.Log.Warningf("DeleteDecisionsWithFilter : %s", err)
|
||||
return "0", errors.Wrap(DeleteFail, "decisions with provided filter")
|
||||
return "0", nil, errors.Wrap(DeleteFail, "decisions with provided filter")
|
||||
}
|
||||
return strconv.Itoa(nbDeleted), nil
|
||||
count, err := c.BulkDeleteDecisions(toDelete, false)
|
||||
if err != nil {
|
||||
c.Log.Warningf("While deleting decisions : %s", err)
|
||||
return "0", nil, errors.Wrap(DeleteFail, "decisions with provided filter")
|
||||
}
|
||||
return strconv.Itoa(count), toDelete, nil
|
||||
}
|
||||
|
||||
// SoftDeleteDecisionsWithFilter updates the expiration time to now() for the decisions matching the filter
|
||||
func (c *Client) SoftDeleteDecisionsWithFilter(filter map[string][]string) (string, error) {
|
||||
// SoftDeleteDecisionsWithFilter updates the expiration time to now() for the decisions matching the filter, and returns the updated items
|
||||
func (c *Client) SoftDeleteDecisionsWithFilter(filter map[string][]string) (string, []*ent.Decision, error) {
|
||||
var err error
|
||||
var start_ip, start_sfx, end_ip, end_sfx int64
|
||||
var ip_sz int
|
||||
var contains bool = true
|
||||
/*if contains is true, return bans that *contains* the given value (value is the inner)
|
||||
else, return bans that are *contained* by the given value (value is the outer)*/
|
||||
decisions := c.Ent.Decision.Update().Where(decision.UntilGT(time.Now().UTC()))
|
||||
decisions := c.Ent.Decision.Query().Where(decision.UntilGT(time.Now().UTC()))
|
||||
for param, value := range filter {
|
||||
switch param {
|
||||
case "contains":
|
||||
contains, err = strconv.ParseBool(value[0])
|
||||
if err != nil {
|
||||
return "0", errors.Wrapf(InvalidFilter, "invalid contains value : %s", err)
|
||||
return "0", nil, errors.Wrapf(InvalidFilter, "invalid contains value : %s", err)
|
||||
}
|
||||
case "scopes":
|
||||
decisions = decisions.Where(decision.ScopeEQ(value[0]))
|
||||
case "uuid":
|
||||
decisions = decisions.Where(decision.UUIDIn(value...))
|
||||
case "origin":
|
||||
decisions = decisions.Where(decision.OriginEQ(value[0]))
|
||||
case "value":
|
||||
|
@ -415,12 +424,12 @@ func (c *Client) SoftDeleteDecisionsWithFilter(filter map[string][]string) (stri
|
|||
case "ip", "range":
|
||||
ip_sz, start_ip, start_sfx, end_ip, end_sfx, err = types.Addr2Ints(value[0])
|
||||
if err != nil {
|
||||
return "0", errors.Wrapf(InvalidIPOrRange, "unable to convert '%s' to int: %s", value[0], err)
|
||||
return "0", nil, errors.Wrapf(InvalidIPOrRange, "unable to convert '%s' to int: %s", value[0], err)
|
||||
}
|
||||
case "scenario":
|
||||
decisions = decisions.Where(decision.ScenarioEQ(value[0]))
|
||||
default:
|
||||
return "0", errors.Wrapf(InvalidFilter, "'%s' doesn't exist", param)
|
||||
return "0", nil, errors.Wrapf(InvalidFilter, "'%s' doesn't exist", param)
|
||||
}
|
||||
}
|
||||
if ip_sz == 4 {
|
||||
|
@ -492,28 +501,89 @@ func (c *Client) SoftDeleteDecisionsWithFilter(filter map[string][]string) (stri
|
|||
))
|
||||
}
|
||||
} else if ip_sz != 0 {
|
||||
return "0", errors.Wrapf(InvalidFilter, "Unknown ip size %d", ip_sz)
|
||||
return "0", nil, errors.Wrapf(InvalidFilter, "Unknown ip size %d", ip_sz)
|
||||
}
|
||||
nbDeleted, err := decisions.SetUntil(time.Now().UTC()).Save(c.CTX)
|
||||
DecisionsToDelete, err := decisions.All(c.CTX)
|
||||
if err != nil {
|
||||
c.Log.Warningf("SoftDeleteDecisionsWithFilter : %s", err)
|
||||
return "0", errors.Wrap(DeleteFail, "soft delete decisions with provided filter")
|
||||
return "0", nil, errors.Wrap(DeleteFail, "soft delete decisions with provided filter")
|
||||
}
|
||||
return strconv.Itoa(nbDeleted), nil
|
||||
|
||||
count, err := c.BulkDeleteDecisions(DecisionsToDelete, true)
|
||||
if err != nil {
|
||||
return "0", nil, errors.Wrapf(DeleteFail, "soft delete decisions with provided filter : %s", err)
|
||||
}
|
||||
return strconv.Itoa(count), DecisionsToDelete, err
|
||||
}
|
||||
|
||||
// BulkDeleteDecisions set the expiration of a bulk of decisions to now() or hard deletes them.
|
||||
// We are doing it this way so we can return impacted decisions for sync with CAPI/PAPI
|
||||
func (c *Client) BulkDeleteDecisions(DecisionsToDelete []*ent.Decision, softDelete bool) (int, error) {
|
||||
bulkSize := 256 //scientifically proven to be the best value for bulk delete
|
||||
idsToDelete := make([]int, 0, bulkSize)
|
||||
totalUpdates := 0
|
||||
for i := 0; i < len(DecisionsToDelete); i++ {
|
||||
idsToDelete = append(idsToDelete, DecisionsToDelete[i].ID)
|
||||
if len(idsToDelete) == bulkSize {
|
||||
|
||||
if softDelete {
|
||||
nbUpdates, err := c.Ent.Decision.Update().Where(
|
||||
decision.IDIn(idsToDelete...),
|
||||
).SetUntil(time.Now().UTC()).Save(c.CTX)
|
||||
if err != nil {
|
||||
return totalUpdates, errors.Wrap(err, "soft delete decisions with provided filter")
|
||||
}
|
||||
totalUpdates += nbUpdates
|
||||
} else {
|
||||
nbUpdates, err := c.Ent.Decision.Delete().Where(
|
||||
decision.IDIn(idsToDelete...),
|
||||
).Exec(c.CTX)
|
||||
if err != nil {
|
||||
return totalUpdates, errors.Wrap(err, "hard delete decisions with provided filter")
|
||||
}
|
||||
totalUpdates += nbUpdates
|
||||
}
|
||||
idsToDelete = make([]int, 0, bulkSize)
|
||||
}
|
||||
}
|
||||
|
||||
if len(idsToDelete) > 0 {
|
||||
if softDelete {
|
||||
nbUpdates, err := c.Ent.Decision.Update().Where(
|
||||
decision.IDIn(idsToDelete...),
|
||||
).SetUntil(time.Now().UTC()).Save(c.CTX)
|
||||
if err != nil {
|
||||
return totalUpdates, errors.Wrap(err, "soft delete decisions with provided filter")
|
||||
}
|
||||
totalUpdates += nbUpdates
|
||||
} else {
|
||||
nbUpdates, err := c.Ent.Decision.Delete().Where(
|
||||
decision.IDIn(idsToDelete...),
|
||||
).Exec(c.CTX)
|
||||
if err != nil {
|
||||
return totalUpdates, errors.Wrap(err, "hard delete decisions with provided filter")
|
||||
}
|
||||
totalUpdates += nbUpdates
|
||||
}
|
||||
|
||||
}
|
||||
return totalUpdates, nil
|
||||
}
|
||||
|
||||
// SoftDeleteDecisionByID set the expiration of a decision to now()
|
||||
func (c *Client) SoftDeleteDecisionByID(decisionID int) (int, error) {
|
||||
nbUpdated, err := c.Ent.Decision.Update().Where(decision.IDEQ(decisionID)).SetUntil(time.Now().UTC()).Save(c.CTX)
|
||||
if err != nil || nbUpdated == 0 {
|
||||
c.Log.Warningf("SoftDeleteDecisionByID : %v (nb soft deleted: %d)", err, nbUpdated)
|
||||
return 0, errors.Wrapf(DeleteFail, "decision with id '%d' doesn't exist", decisionID)
|
||||
func (c *Client) SoftDeleteDecisionByID(decisionID int) (int, []*ent.Decision, error) {
|
||||
toUpdate, err := c.Ent.Decision.Query().Where(decision.IDEQ(decisionID)).All(c.CTX)
|
||||
|
||||
if err != nil || len(toUpdate) == 0 {
|
||||
c.Log.Warningf("SoftDeleteDecisionByID : %v (nb soft deleted: %d)", err, len(toUpdate))
|
||||
return 0, nil, errors.Wrapf(DeleteFail, "decision with id '%d' doesn't exist", decisionID)
|
||||
}
|
||||
|
||||
if nbUpdated == 0 {
|
||||
return 0, ItemNotFound
|
||||
if len(toUpdate) == 0 {
|
||||
return 0, nil, ItemNotFound
|
||||
}
|
||||
return nbUpdated, nil
|
||||
count, err := c.BulkDeleteDecisions(toUpdate, true)
|
||||
return count, toUpdate, err
|
||||
}
|
||||
|
||||
func (c *Client) CountDecisionsByValue(decisionValue string) (int, error) {
|
||||
|
|
|
@ -61,6 +61,8 @@ type Alert struct {
|
|||
ScenarioHash string `json:"scenarioHash,omitempty"`
|
||||
// Simulated holds the value of the "simulated" field.
|
||||
Simulated bool `json:"simulated,omitempty"`
|
||||
// UUID holds the value of the "uuid" field.
|
||||
UUID string `json:"uuid,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the AlertQuery when eager-loading is set.
|
||||
Edges AlertEdges `json:"edges"`
|
||||
|
@ -133,7 +135,7 @@ func (*Alert) scanValues(columns []string) ([]any, error) {
|
|||
values[i] = new(sql.NullFloat64)
|
||||
case alert.FieldID, alert.FieldEventsCount, alert.FieldCapacity:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case alert.FieldScenario, alert.FieldBucketId, alert.FieldMessage, alert.FieldSourceIp, alert.FieldSourceRange, alert.FieldSourceAsNumber, alert.FieldSourceAsName, alert.FieldSourceCountry, alert.FieldSourceScope, alert.FieldSourceValue, alert.FieldLeakSpeed, alert.FieldScenarioVersion, alert.FieldScenarioHash:
|
||||
case alert.FieldScenario, alert.FieldBucketId, alert.FieldMessage, alert.FieldSourceIp, alert.FieldSourceRange, alert.FieldSourceAsNumber, alert.FieldSourceAsName, alert.FieldSourceCountry, alert.FieldSourceScope, alert.FieldSourceValue, alert.FieldLeakSpeed, alert.FieldScenarioVersion, alert.FieldScenarioHash, alert.FieldUUID:
|
||||
values[i] = new(sql.NullString)
|
||||
case alert.FieldCreatedAt, alert.FieldUpdatedAt, alert.FieldStartedAt, alert.FieldStoppedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
|
@ -294,6 +296,12 @@ func (a *Alert) assignValues(columns []string, values []any) error {
|
|||
} else if value.Valid {
|
||||
a.Simulated = value.Bool
|
||||
}
|
||||
case alert.FieldUUID:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field uuid", values[i])
|
||||
} else if value.Valid {
|
||||
a.UUID = value.String
|
||||
}
|
||||
case alert.ForeignKeys[0]:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for edge-field machine_alerts", value)
|
||||
|
@ -418,6 +426,8 @@ func (a *Alert) String() string {
|
|||
builder.WriteString(", ")
|
||||
builder.WriteString("simulated=")
|
||||
builder.WriteString(fmt.Sprintf("%v", a.Simulated))
|
||||
builder.WriteString(", uuid=")
|
||||
builder.WriteString(a.UUID)
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@ const (
|
|||
FieldScenarioHash = "scenario_hash"
|
||||
// FieldSimulated holds the string denoting the simulated field in the database.
|
||||
FieldSimulated = "simulated"
|
||||
// FieldUUID holds the string denoting the uuid field in the database.
|
||||
FieldUUID = "uuid"
|
||||
// EdgeOwner holds the string denoting the owner edge name in mutations.
|
||||
EdgeOwner = "owner"
|
||||
// EdgeDecisions holds the string denoting the decisions edge name in mutations.
|
||||
|
@ -120,6 +122,7 @@ var Columns = []string{
|
|||
FieldScenarioVersion,
|
||||
FieldScenarioHash,
|
||||
FieldSimulated,
|
||||
FieldUUID,
|
||||
}
|
||||
|
||||
// ForeignKeys holds the SQL foreign-keys that are owned by the "alerts"
|
||||
|
|
|
@ -235,6 +235,13 @@ func Simulated(v bool) predicate.Alert {
|
|||
})
|
||||
}
|
||||
|
||||
// UUID applies equality check predicate on the "uuid" field. It's identical to UUIDEQ.
|
||||
func UUID(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
|
@ -2328,6 +2335,131 @@ func SimulatedNEQ(v bool) predicate.Alert {
|
|||
})
|
||||
}
|
||||
|
||||
// UUIDEQ applies the EQ predicate on the "uuid" field.
|
||||
func UUIDEQ(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDNEQ applies the NEQ predicate on the "uuid" field.
|
||||
func UUIDNEQ(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.NEQ(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDIn applies the In predicate on the "uuid" field.
|
||||
func UUIDIn(vs ...string) predicate.Alert {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.In(s.C(FieldUUID), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDNotIn applies the NotIn predicate on the "uuid" field.
|
||||
func UUIDNotIn(vs ...string) predicate.Alert {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.NotIn(s.C(FieldUUID), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDGT applies the GT predicate on the "uuid" field.
|
||||
func UUIDGT(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.GT(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDGTE applies the GTE predicate on the "uuid" field.
|
||||
func UUIDGTE(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.GTE(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDLT applies the LT predicate on the "uuid" field.
|
||||
func UUIDLT(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.LT(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDLTE applies the LTE predicate on the "uuid" field.
|
||||
func UUIDLTE(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.LTE(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDContains applies the Contains predicate on the "uuid" field.
|
||||
func UUIDContains(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.Contains(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDHasPrefix applies the HasPrefix predicate on the "uuid" field.
|
||||
func UUIDHasPrefix(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.HasPrefix(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDHasSuffix applies the HasSuffix predicate on the "uuid" field.
|
||||
func UUIDHasSuffix(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.HasSuffix(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDIsNil applies the IsNil predicate on the "uuid" field.
|
||||
func UUIDIsNil() predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.IsNull(s.C(FieldUUID)))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDNotNil applies the NotNil predicate on the "uuid" field.
|
||||
func UUIDNotNil() predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.NotNull(s.C(FieldUUID)))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDEqualFold applies the EqualFold predicate on the "uuid" field.
|
||||
func UUIDEqualFold(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.EqualFold(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDContainsFold applies the ContainsFold predicate on the "uuid" field.
|
||||
func UUIDContainsFold(v string) predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
s.Where(sql.ContainsFold(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// HasOwner applies the HasEdge predicate on the "owner" edge.
|
||||
func HasOwner() predicate.Alert {
|
||||
return predicate.Alert(func(s *sql.Selector) {
|
||||
|
|
|
@ -324,6 +324,20 @@ func (ac *AlertCreate) SetNillableSimulated(b *bool) *AlertCreate {
|
|||
return ac
|
||||
}
|
||||
|
||||
// SetUUID sets the "uuid" field.
|
||||
func (ac *AlertCreate) SetUUID(s string) *AlertCreate {
|
||||
ac.mutation.SetUUID(s)
|
||||
return ac
|
||||
}
|
||||
|
||||
// SetNillableUUID sets the "uuid" field if the given value is not nil.
|
||||
func (ac *AlertCreate) SetNillableUUID(s *string) *AlertCreate {
|
||||
if s != nil {
|
||||
ac.SetUUID(*s)
|
||||
}
|
||||
return ac
|
||||
}
|
||||
|
||||
// SetOwnerID sets the "owner" edge to the Machine entity by ID.
|
||||
func (ac *AlertCreate) SetOwnerID(id int) *AlertCreate {
|
||||
ac.mutation.SetOwnerID(id)
|
||||
|
@ -710,6 +724,14 @@ func (ac *AlertCreate) createSpec() (*Alert, *sqlgraph.CreateSpec) {
|
|||
})
|
||||
_node.Simulated = value
|
||||
}
|
||||
if value, ok := ac.mutation.UUID(); ok {
|
||||
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: alert.FieldUUID,
|
||||
})
|
||||
_node.UUID = value
|
||||
}
|
||||
if nodes := ac.mutation.OwnerIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
|
|
|
@ -464,6 +464,26 @@ func (au *AlertUpdate) SetNillableSimulated(b *bool) *AlertUpdate {
|
|||
return au
|
||||
}
|
||||
|
||||
// SetUUID sets the "uuid" field.
|
||||
func (au *AlertUpdate) SetUUID(s string) *AlertUpdate {
|
||||
au.mutation.SetUUID(s)
|
||||
return au
|
||||
}
|
||||
|
||||
// SetNillableUUID sets the "uuid" field if the given value is not nil.
|
||||
func (au *AlertUpdate) SetNillableUUID(s *string) *AlertUpdate {
|
||||
if s != nil {
|
||||
au.SetUUID(*s)
|
||||
}
|
||||
return au
|
||||
}
|
||||
|
||||
// ClearUUID clears the value of the "uuid" field.
|
||||
func (au *AlertUpdate) ClearUUID() *AlertUpdate {
|
||||
au.mutation.ClearUUID()
|
||||
return au
|
||||
}
|
||||
|
||||
// SetOwnerID sets the "owner" edge to the Machine entity by ID.
|
||||
func (au *AlertUpdate) SetOwnerID(id int) *AlertUpdate {
|
||||
au.mutation.SetOwnerID(id)
|
||||
|
@ -989,6 +1009,19 @@ func (au *AlertUpdate) sqlSave(ctx context.Context) (n int, err error) {
|
|||
Column: alert.FieldSimulated,
|
||||
})
|
||||
}
|
||||
if value, ok := au.mutation.UUID(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: alert.FieldUUID,
|
||||
})
|
||||
}
|
||||
if au.mutation.UUIDCleared() {
|
||||
_spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Column: alert.FieldUUID,
|
||||
})
|
||||
}
|
||||
if au.mutation.OwnerCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
|
@ -1637,6 +1670,26 @@ func (auo *AlertUpdateOne) SetNillableSimulated(b *bool) *AlertUpdateOne {
|
|||
return auo
|
||||
}
|
||||
|
||||
// SetUUID sets the "uuid" field.
|
||||
func (auo *AlertUpdateOne) SetUUID(s string) *AlertUpdateOne {
|
||||
auo.mutation.SetUUID(s)
|
||||
return auo
|
||||
}
|
||||
|
||||
// SetNillableUUID sets the "uuid" field if the given value is not nil.
|
||||
func (auo *AlertUpdateOne) SetNillableUUID(s *string) *AlertUpdateOne {
|
||||
if s != nil {
|
||||
auo.SetUUID(*s)
|
||||
}
|
||||
return auo
|
||||
}
|
||||
|
||||
// ClearUUID clears the value of the "uuid" field.
|
||||
func (auo *AlertUpdateOne) ClearUUID() *AlertUpdateOne {
|
||||
auo.mutation.ClearUUID()
|
||||
return auo
|
||||
}
|
||||
|
||||
// SetOwnerID sets the "owner" edge to the Machine entity by ID.
|
||||
func (auo *AlertUpdateOne) SetOwnerID(id int) *AlertUpdateOne {
|
||||
auo.mutation.SetOwnerID(id)
|
||||
|
@ -2192,6 +2245,19 @@ func (auo *AlertUpdateOne) sqlSave(ctx context.Context) (_node *Alert, err error
|
|||
Column: alert.FieldSimulated,
|
||||
})
|
||||
}
|
||||
if value, ok := auo.mutation.UUID(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: alert.FieldUUID,
|
||||
})
|
||||
}
|
||||
if auo.mutation.UUIDCleared() {
|
||||
_spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Column: alert.FieldUUID,
|
||||
})
|
||||
}
|
||||
if auo.mutation.OwnerCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/alert"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/bouncer"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/configitem"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/decision"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/event"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/machine"
|
||||
|
@ -31,6 +32,8 @@ type Client struct {
|
|||
Alert *AlertClient
|
||||
// Bouncer is the client for interacting with the Bouncer builders.
|
||||
Bouncer *BouncerClient
|
||||
// ConfigItem is the client for interacting with the ConfigItem builders.
|
||||
ConfigItem *ConfigItemClient
|
||||
// Decision is the client for interacting with the Decision builders.
|
||||
Decision *DecisionClient
|
||||
// Event is the client for interacting with the Event builders.
|
||||
|
@ -54,6 +57,7 @@ func (c *Client) init() {
|
|||
c.Schema = migrate.NewSchema(c.driver)
|
||||
c.Alert = NewAlertClient(c.config)
|
||||
c.Bouncer = NewBouncerClient(c.config)
|
||||
c.ConfigItem = NewConfigItemClient(c.config)
|
||||
c.Decision = NewDecisionClient(c.config)
|
||||
c.Event = NewEventClient(c.config)
|
||||
c.Machine = NewMachineClient(c.config)
|
||||
|
@ -89,14 +93,15 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
|
|||
cfg := c.config
|
||||
cfg.driver = tx
|
||||
return &Tx{
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
Alert: NewAlertClient(cfg),
|
||||
Bouncer: NewBouncerClient(cfg),
|
||||
Decision: NewDecisionClient(cfg),
|
||||
Event: NewEventClient(cfg),
|
||||
Machine: NewMachineClient(cfg),
|
||||
Meta: NewMetaClient(cfg),
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
Alert: NewAlertClient(cfg),
|
||||
Bouncer: NewBouncerClient(cfg),
|
||||
ConfigItem: NewConfigItemClient(cfg),
|
||||
Decision: NewDecisionClient(cfg),
|
||||
Event: NewEventClient(cfg),
|
||||
Machine: NewMachineClient(cfg),
|
||||
Meta: NewMetaClient(cfg),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -114,14 +119,15 @@ 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),
|
||||
Decision: NewDecisionClient(cfg),
|
||||
Event: NewEventClient(cfg),
|
||||
Machine: NewMachineClient(cfg),
|
||||
Meta: NewMetaClient(cfg),
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
Alert: NewAlertClient(cfg),
|
||||
Bouncer: NewBouncerClient(cfg),
|
||||
ConfigItem: NewConfigItemClient(cfg),
|
||||
Decision: NewDecisionClient(cfg),
|
||||
Event: NewEventClient(cfg),
|
||||
Machine: NewMachineClient(cfg),
|
||||
Meta: NewMetaClient(cfg),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -152,6 +158,7 @@ func (c *Client) Close() error {
|
|||
func (c *Client) Use(hooks ...Hook) {
|
||||
c.Alert.Use(hooks...)
|
||||
c.Bouncer.Use(hooks...)
|
||||
c.ConfigItem.Use(hooks...)
|
||||
c.Decision.Use(hooks...)
|
||||
c.Event.Use(hooks...)
|
||||
c.Machine.Use(hooks...)
|
||||
|
@ -402,6 +409,96 @@ func (c *BouncerClient) Hooks() []Hook {
|
|||
return c.hooks.Bouncer
|
||||
}
|
||||
|
||||
// ConfigItemClient is a client for the ConfigItem schema.
|
||||
type ConfigItemClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewConfigItemClient returns a client for the ConfigItem from the given config.
|
||||
func NewConfigItemClient(c config) *ConfigItemClient {
|
||||
return &ConfigItemClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `configitem.Hooks(f(g(h())))`.
|
||||
func (c *ConfigItemClient) Use(hooks ...Hook) {
|
||||
c.hooks.ConfigItem = append(c.hooks.ConfigItem, hooks...)
|
||||
}
|
||||
|
||||
// Create returns a create builder for ConfigItem.
|
||||
func (c *ConfigItemClient) Create() *ConfigItemCreate {
|
||||
mutation := newConfigItemMutation(c.config, OpCreate)
|
||||
return &ConfigItemCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of ConfigItem entities.
|
||||
func (c *ConfigItemClient) CreateBulk(builders ...*ConfigItemCreate) *ConfigItemCreateBulk {
|
||||
return &ConfigItemCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for ConfigItem.
|
||||
func (c *ConfigItemClient) Update() *ConfigItemUpdate {
|
||||
mutation := newConfigItemMutation(c.config, OpUpdate)
|
||||
return &ConfigItemUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *ConfigItemClient) UpdateOne(ci *ConfigItem) *ConfigItemUpdateOne {
|
||||
mutation := newConfigItemMutation(c.config, OpUpdateOne, withConfigItem(ci))
|
||||
return &ConfigItemUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *ConfigItemClient) UpdateOneID(id int) *ConfigItemUpdateOne {
|
||||
mutation := newConfigItemMutation(c.config, OpUpdateOne, withConfigItemID(id))
|
||||
return &ConfigItemUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for ConfigItem.
|
||||
func (c *ConfigItemClient) Delete() *ConfigItemDelete {
|
||||
mutation := newConfigItemMutation(c.config, OpDelete)
|
||||
return &ConfigItemDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a delete builder for the given entity.
|
||||
func (c *ConfigItemClient) DeleteOne(ci *ConfigItem) *ConfigItemDeleteOne {
|
||||
return c.DeleteOneID(ci.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a delete builder for the given id.
|
||||
func (c *ConfigItemClient) DeleteOneID(id int) *ConfigItemDeleteOne {
|
||||
builder := c.Delete().Where(configitem.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &ConfigItemDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for ConfigItem.
|
||||
func (c *ConfigItemClient) Query() *ConfigItemQuery {
|
||||
return &ConfigItemQuery{
|
||||
config: c.config,
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a ConfigItem entity by its id.
|
||||
func (c *ConfigItemClient) Get(ctx context.Context, id int) (*ConfigItem, error) {
|
||||
return c.Query().Where(configitem.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *ConfigItemClient) GetX(ctx context.Context, id int) *ConfigItem {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *ConfigItemClient) Hooks() []Hook {
|
||||
return c.hooks.ConfigItem
|
||||
}
|
||||
|
||||
// DecisionClient is a client for the Decision schema.
|
||||
type DecisionClient struct {
|
||||
config
|
||||
|
|
|
@ -24,12 +24,13 @@ type config struct {
|
|||
|
||||
// hooks per client, for fast access.
|
||||
type hooks struct {
|
||||
Alert []ent.Hook
|
||||
Bouncer []ent.Hook
|
||||
Decision []ent.Hook
|
||||
Event []ent.Hook
|
||||
Machine []ent.Hook
|
||||
Meta []ent.Hook
|
||||
Alert []ent.Hook
|
||||
Bouncer []ent.Hook
|
||||
ConfigItem []ent.Hook
|
||||
Decision []ent.Hook
|
||||
Event []ent.Hook
|
||||
Machine []ent.Hook
|
||||
Meta []ent.Hook
|
||||
}
|
||||
|
||||
// Options applies the options on the config object.
|
||||
|
|
138
pkg/database/ent/configitem.go
Normal file
138
pkg/database/ent/configitem.go
Normal file
|
@ -0,0 +1,138 @@
|
|||
// Code generated by entc, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/configitem"
|
||||
)
|
||||
|
||||
// ConfigItem is the model entity for the ConfigItem schema.
|
||||
type ConfigItem struct {
|
||||
config `json:"-"`
|
||||
// ID of the ent.
|
||||
ID int `json:"id,omitempty"`
|
||||
// CreatedAt holds the value of the "created_at" field.
|
||||
CreatedAt *time.Time `json:"created_at"`
|
||||
// UpdatedAt holds the value of the "updated_at" field.
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
// Name holds the value of the "name" field.
|
||||
Name string `json:"name"`
|
||||
// Value holds the value of the "value" field.
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// scanValues returns the types for scanning values from sql.Rows.
|
||||
func (*ConfigItem) scanValues(columns []string) ([]interface{}, error) {
|
||||
values := make([]interface{}, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case configitem.FieldID:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case configitem.FieldName, configitem.FieldValue:
|
||||
values[i] = new(sql.NullString)
|
||||
case configitem.FieldCreatedAt, configitem.FieldUpdatedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected column %q for type ConfigItem", columns[i])
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
||||
// to the ConfigItem fields.
|
||||
func (ci *ConfigItem) assignValues(columns []string, values []interface{}) error {
|
||||
if m, n := len(values), len(columns); m < n {
|
||||
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
|
||||
}
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case configitem.FieldID:
|
||||
value, ok := values[i].(*sql.NullInt64)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field id", value)
|
||||
}
|
||||
ci.ID = int(value.Int64)
|
||||
case configitem.FieldCreatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
||||
} else if value.Valid {
|
||||
ci.CreatedAt = new(time.Time)
|
||||
*ci.CreatedAt = value.Time
|
||||
}
|
||||
case configitem.FieldUpdatedAt:
|
||||
if value, ok := values[i].(*sql.NullTime); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
|
||||
} else if value.Valid {
|
||||
ci.UpdatedAt = new(time.Time)
|
||||
*ci.UpdatedAt = value.Time
|
||||
}
|
||||
case configitem.FieldName:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field name", values[i])
|
||||
} else if value.Valid {
|
||||
ci.Name = value.String
|
||||
}
|
||||
case configitem.FieldValue:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field value", values[i])
|
||||
} else if value.Valid {
|
||||
ci.Value = value.String
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update returns a builder for updating this ConfigItem.
|
||||
// Note that you need to call ConfigItem.Unwrap() before calling this method if this ConfigItem
|
||||
// was returned from a transaction, and the transaction was committed or rolled back.
|
||||
func (ci *ConfigItem) Update() *ConfigItemUpdateOne {
|
||||
return (&ConfigItemClient{config: ci.config}).UpdateOne(ci)
|
||||
}
|
||||
|
||||
// Unwrap unwraps the ConfigItem entity that was returned from a transaction after it was closed,
|
||||
// so that all future queries will be executed through the driver which created the transaction.
|
||||
func (ci *ConfigItem) Unwrap() *ConfigItem {
|
||||
tx, ok := ci.config.driver.(*txDriver)
|
||||
if !ok {
|
||||
panic("ent: ConfigItem is not a transactional entity")
|
||||
}
|
||||
ci.config.driver = tx.drv
|
||||
return ci
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer.
|
||||
func (ci *ConfigItem) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("ConfigItem(")
|
||||
builder.WriteString(fmt.Sprintf("id=%v", ci.ID))
|
||||
if v := ci.CreatedAt; v != nil {
|
||||
builder.WriteString(", created_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
if v := ci.UpdatedAt; v != nil {
|
||||
builder.WriteString(", updated_at=")
|
||||
builder.WriteString(v.Format(time.ANSIC))
|
||||
}
|
||||
builder.WriteString(", name=")
|
||||
builder.WriteString(ci.Name)
|
||||
builder.WriteString(", value=")
|
||||
builder.WriteString(ci.Value)
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// ConfigItems is a parsable slice of ConfigItem.
|
||||
type ConfigItems []*ConfigItem
|
||||
|
||||
func (ci ConfigItems) config(cfg config) {
|
||||
for _i := range ci {
|
||||
ci[_i].config = cfg
|
||||
}
|
||||
}
|
54
pkg/database/ent/configitem/configitem.go
Normal file
54
pkg/database/ent/configitem/configitem.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Code generated by entc, DO NOT EDIT.
|
||||
|
||||
package configitem
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// Label holds the string label denoting the configitem type in the database.
|
||||
Label = "config_item"
|
||||
// FieldID holds the string denoting the id field in the database.
|
||||
FieldID = "id"
|
||||
// FieldCreatedAt holds the string denoting the created_at field in the database.
|
||||
FieldCreatedAt = "created_at"
|
||||
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
|
||||
FieldUpdatedAt = "updated_at"
|
||||
// FieldName holds the string denoting the name field in the database.
|
||||
FieldName = "name"
|
||||
// FieldValue holds the string denoting the value field in the database.
|
||||
FieldValue = "value"
|
||||
// Table holds the table name of the configitem in the database.
|
||||
Table = "config_items"
|
||||
)
|
||||
|
||||
// Columns holds all SQL columns for configitem fields.
|
||||
var Columns = []string{
|
||||
FieldID,
|
||||
FieldCreatedAt,
|
||||
FieldUpdatedAt,
|
||||
FieldName,
|
||||
FieldValue,
|
||||
}
|
||||
|
||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||
func ValidColumn(column string) bool {
|
||||
for i := range Columns {
|
||||
if column == Columns[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
|
||||
DefaultCreatedAt func() time.Time
|
||||
// UpdateDefaultCreatedAt holds the default value on update for the "created_at" field.
|
||||
UpdateDefaultCreatedAt func() time.Time
|
||||
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
|
||||
DefaultUpdatedAt func() time.Time
|
||||
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
|
||||
UpdateDefaultUpdatedAt func() time.Time
|
||||
)
|
555
pkg/database/ent/configitem/where.go
Normal file
555
pkg/database/ent/configitem/where.go
Normal file
|
@ -0,0 +1,555 @@
|
|||
// Code generated by entc, DO NOT EDIT.
|
||||
|
||||
package configitem
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/predicate"
|
||||
)
|
||||
|
||||
// ID filters vertices based on their ID field.
|
||||
func ID(id int) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldID), id))
|
||||
})
|
||||
}
|
||||
|
||||
// IDEQ applies the EQ predicate on the ID field.
|
||||
func IDEQ(id int) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldID), id))
|
||||
})
|
||||
}
|
||||
|
||||
// IDNEQ applies the NEQ predicate on the ID field.
|
||||
func IDNEQ(id int) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.NEQ(s.C(FieldID), id))
|
||||
})
|
||||
}
|
||||
|
||||
// IDIn applies the In predicate on the ID field.
|
||||
func IDIn(ids ...int) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(ids) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
v := make([]interface{}, len(ids))
|
||||
for i := range v {
|
||||
v[i] = ids[i]
|
||||
}
|
||||
s.Where(sql.In(s.C(FieldID), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// IDNotIn applies the NotIn predicate on the ID field.
|
||||
func IDNotIn(ids ...int) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(ids) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
v := make([]interface{}, len(ids))
|
||||
for i := range v {
|
||||
v[i] = ids[i]
|
||||
}
|
||||
s.Where(sql.NotIn(s.C(FieldID), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// IDGT applies the GT predicate on the ID field.
|
||||
func IDGT(id int) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.GT(s.C(FieldID), id))
|
||||
})
|
||||
}
|
||||
|
||||
// IDGTE applies the GTE predicate on the ID field.
|
||||
func IDGTE(id int) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.GTE(s.C(FieldID), id))
|
||||
})
|
||||
}
|
||||
|
||||
// IDLT applies the LT predicate on the ID field.
|
||||
func IDLT(id int) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.LT(s.C(FieldID), id))
|
||||
})
|
||||
}
|
||||
|
||||
// IDLTE applies the LTE predicate on the ID field.
|
||||
func IDLTE(id int) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.LTE(s.C(FieldID), id))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
|
||||
func CreatedAt(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldCreatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
|
||||
func UpdatedAt(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldUpdatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
|
||||
func Name(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// Value applies equality check predicate on the "value" field. It's identical to ValueEQ.
|
||||
func Value(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldCreatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
|
||||
func CreatedAtNEQ(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.NEQ(s.C(FieldCreatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtIn applies the In predicate on the "created_at" field.
|
||||
func CreatedAtIn(vs ...time.Time) predicate.ConfigItem {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.In(s.C(FieldCreatedAt), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
|
||||
func CreatedAtNotIn(vs ...time.Time) predicate.ConfigItem {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.NotIn(s.C(FieldCreatedAt), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtGT applies the GT predicate on the "created_at" field.
|
||||
func CreatedAtGT(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.GT(s.C(FieldCreatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
|
||||
func CreatedAtGTE(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.GTE(s.C(FieldCreatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtLT applies the LT predicate on the "created_at" field.
|
||||
func CreatedAtLT(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.LT(s.C(FieldCreatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
|
||||
func CreatedAtLTE(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.LTE(s.C(FieldCreatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtIsNil applies the IsNil predicate on the "created_at" field.
|
||||
func CreatedAtIsNil() predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.IsNull(s.C(FieldCreatedAt)))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtNotNil applies the NotNil predicate on the "created_at" field.
|
||||
func CreatedAtNotNil() predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.NotNull(s.C(FieldCreatedAt)))
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
|
||||
func UpdatedAtEQ(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldUpdatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
|
||||
func UpdatedAtNEQ(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.NEQ(s.C(FieldUpdatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatedAtIn applies the In predicate on the "updated_at" field.
|
||||
func UpdatedAtIn(vs ...time.Time) predicate.ConfigItem {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.In(s.C(FieldUpdatedAt), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
|
||||
func UpdatedAtNotIn(vs ...time.Time) predicate.ConfigItem {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.NotIn(s.C(FieldUpdatedAt), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
|
||||
func UpdatedAtGT(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.GT(s.C(FieldUpdatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
|
||||
func UpdatedAtGTE(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.GTE(s.C(FieldUpdatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
|
||||
func UpdatedAtLT(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.LT(s.C(FieldUpdatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
|
||||
func UpdatedAtLTE(v time.Time) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.LTE(s.C(FieldUpdatedAt), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatedAtIsNil applies the IsNil predicate on the "updated_at" field.
|
||||
func UpdatedAtIsNil() predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.IsNull(s.C(FieldUpdatedAt)))
|
||||
})
|
||||
}
|
||||
|
||||
// UpdatedAtNotNil applies the NotNil predicate on the "updated_at" field.
|
||||
func UpdatedAtNotNil() predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.NotNull(s.C(FieldUpdatedAt)))
|
||||
})
|
||||
}
|
||||
|
||||
// NameEQ applies the EQ predicate on the "name" field.
|
||||
func NameEQ(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// NameNEQ applies the NEQ predicate on the "name" field.
|
||||
func NameNEQ(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.NEQ(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// NameIn applies the In predicate on the "name" field.
|
||||
func NameIn(vs ...string) predicate.ConfigItem {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.In(s.C(FieldName), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// NameNotIn applies the NotIn predicate on the "name" field.
|
||||
func NameNotIn(vs ...string) predicate.ConfigItem {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.NotIn(s.C(FieldName), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// NameGT applies the GT predicate on the "name" field.
|
||||
func NameGT(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.GT(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// NameGTE applies the GTE predicate on the "name" field.
|
||||
func NameGTE(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.GTE(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// NameLT applies the LT predicate on the "name" field.
|
||||
func NameLT(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.LT(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// NameLTE applies the LTE predicate on the "name" field.
|
||||
func NameLTE(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.LTE(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// NameContains applies the Contains predicate on the "name" field.
|
||||
func NameContains(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.Contains(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
|
||||
func NameHasPrefix(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.HasPrefix(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
|
||||
func NameHasSuffix(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.HasSuffix(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// NameEqualFold applies the EqualFold predicate on the "name" field.
|
||||
func NameEqualFold(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EqualFold(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// NameContainsFold applies the ContainsFold predicate on the "name" field.
|
||||
func NameContainsFold(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.ContainsFold(s.C(FieldName), v))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueEQ applies the EQ predicate on the "value" field.
|
||||
func ValueEQ(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueNEQ applies the NEQ predicate on the "value" field.
|
||||
func ValueNEQ(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.NEQ(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueIn applies the In predicate on the "value" field.
|
||||
func ValueIn(vs ...string) predicate.ConfigItem {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.In(s.C(FieldValue), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueNotIn applies the NotIn predicate on the "value" field.
|
||||
func ValueNotIn(vs ...string) predicate.ConfigItem {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.NotIn(s.C(FieldValue), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueGT applies the GT predicate on the "value" field.
|
||||
func ValueGT(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.GT(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueGTE applies the GTE predicate on the "value" field.
|
||||
func ValueGTE(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.GTE(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueLT applies the LT predicate on the "value" field.
|
||||
func ValueLT(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.LT(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueLTE applies the LTE predicate on the "value" field.
|
||||
func ValueLTE(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.LTE(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueContains applies the Contains predicate on the "value" field.
|
||||
func ValueContains(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.Contains(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueHasPrefix applies the HasPrefix predicate on the "value" field.
|
||||
func ValueHasPrefix(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.HasPrefix(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueHasSuffix applies the HasSuffix predicate on the "value" field.
|
||||
func ValueHasSuffix(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.HasSuffix(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueEqualFold applies the EqualFold predicate on the "value" field.
|
||||
func ValueEqualFold(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.EqualFold(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// ValueContainsFold applies the ContainsFold predicate on the "value" field.
|
||||
func ValueContainsFold(v string) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s.Where(sql.ContainsFold(s.C(FieldValue), v))
|
||||
})
|
||||
}
|
||||
|
||||
// And groups predicates with the AND operator between them.
|
||||
func And(predicates ...predicate.ConfigItem) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s1 := s.Clone().SetP(nil)
|
||||
for _, p := range predicates {
|
||||
p(s1)
|
||||
}
|
||||
s.Where(s1.P())
|
||||
})
|
||||
}
|
||||
|
||||
// Or groups predicates with the OR operator between them.
|
||||
func Or(predicates ...predicate.ConfigItem) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
s1 := s.Clone().SetP(nil)
|
||||
for i, p := range predicates {
|
||||
if i > 0 {
|
||||
s1.Or()
|
||||
}
|
||||
p(s1)
|
||||
}
|
||||
s.Where(s1.P())
|
||||
})
|
||||
}
|
||||
|
||||
// Not applies the not operator on the given predicate.
|
||||
func Not(p predicate.ConfigItem) predicate.ConfigItem {
|
||||
return predicate.ConfigItem(func(s *sql.Selector) {
|
||||
p(s.Not())
|
||||
})
|
||||
}
|
296
pkg/database/ent/configitem_create.go
Normal file
296
pkg/database/ent/configitem_create.go
Normal file
|
@ -0,0 +1,296 @@
|
|||
// Code generated by entc, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/configitem"
|
||||
)
|
||||
|
||||
// ConfigItemCreate is the builder for creating a ConfigItem entity.
|
||||
type ConfigItemCreate struct {
|
||||
config
|
||||
mutation *ConfigItemMutation
|
||||
hooks []Hook
|
||||
}
|
||||
|
||||
// SetCreatedAt sets the "created_at" field.
|
||||
func (cic *ConfigItemCreate) SetCreatedAt(t time.Time) *ConfigItemCreate {
|
||||
cic.mutation.SetCreatedAt(t)
|
||||
return cic
|
||||
}
|
||||
|
||||
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
|
||||
func (cic *ConfigItemCreate) SetNillableCreatedAt(t *time.Time) *ConfigItemCreate {
|
||||
if t != nil {
|
||||
cic.SetCreatedAt(*t)
|
||||
}
|
||||
return cic
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (cic *ConfigItemCreate) SetUpdatedAt(t time.Time) *ConfigItemCreate {
|
||||
cic.mutation.SetUpdatedAt(t)
|
||||
return cic
|
||||
}
|
||||
|
||||
// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
|
||||
func (cic *ConfigItemCreate) SetNillableUpdatedAt(t *time.Time) *ConfigItemCreate {
|
||||
if t != nil {
|
||||
cic.SetUpdatedAt(*t)
|
||||
}
|
||||
return cic
|
||||
}
|
||||
|
||||
// SetName sets the "name" field.
|
||||
func (cic *ConfigItemCreate) SetName(s string) *ConfigItemCreate {
|
||||
cic.mutation.SetName(s)
|
||||
return cic
|
||||
}
|
||||
|
||||
// SetValue sets the "value" field.
|
||||
func (cic *ConfigItemCreate) SetValue(s string) *ConfigItemCreate {
|
||||
cic.mutation.SetValue(s)
|
||||
return cic
|
||||
}
|
||||
|
||||
// Mutation returns the ConfigItemMutation object of the builder.
|
||||
func (cic *ConfigItemCreate) Mutation() *ConfigItemMutation {
|
||||
return cic.mutation
|
||||
}
|
||||
|
||||
// Save creates the ConfigItem in the database.
|
||||
func (cic *ConfigItemCreate) Save(ctx context.Context) (*ConfigItem, error) {
|
||||
var (
|
||||
err error
|
||||
node *ConfigItem
|
||||
)
|
||||
cic.defaults()
|
||||
if len(cic.hooks) == 0 {
|
||||
if err = cic.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node, err = cic.sqlSave(ctx)
|
||||
} else {
|
||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||
mutation, ok := m.(*ConfigItemMutation)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
||||
}
|
||||
if err = cic.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cic.mutation = mutation
|
||||
if node, err = cic.sqlSave(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mutation.id = &node.ID
|
||||
mutation.done = true
|
||||
return node, err
|
||||
})
|
||||
for i := len(cic.hooks) - 1; i >= 0; i-- {
|
||||
if cic.hooks[i] == nil {
|
||||
return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)")
|
||||
}
|
||||
mut = cic.hooks[i](mut)
|
||||
}
|
||||
if _, err := mut.Mutate(ctx, cic.mutation); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return node, err
|
||||
}
|
||||
|
||||
// SaveX calls Save and panics if Save returns an error.
|
||||
func (cic *ConfigItemCreate) SaveX(ctx context.Context) *ConfigItem {
|
||||
v, err := cic.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (cic *ConfigItemCreate) Exec(ctx context.Context) error {
|
||||
_, err := cic.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (cic *ConfigItemCreate) ExecX(ctx context.Context) {
|
||||
if err := cic.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (cic *ConfigItemCreate) defaults() {
|
||||
if _, ok := cic.mutation.CreatedAt(); !ok {
|
||||
v := configitem.DefaultCreatedAt()
|
||||
cic.mutation.SetCreatedAt(v)
|
||||
}
|
||||
if _, ok := cic.mutation.UpdatedAt(); !ok {
|
||||
v := configitem.DefaultUpdatedAt()
|
||||
cic.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (cic *ConfigItemCreate) check() error {
|
||||
if _, ok := cic.mutation.Name(); !ok {
|
||||
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "ConfigItem.name"`)}
|
||||
}
|
||||
if _, ok := cic.mutation.Value(); !ok {
|
||||
return &ValidationError{Name: "value", err: errors.New(`ent: missing required field "ConfigItem.value"`)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cic *ConfigItemCreate) sqlSave(ctx context.Context) (*ConfigItem, error) {
|
||||
_node, _spec := cic.createSpec()
|
||||
if err := sqlgraph.CreateNode(ctx, cic.driver, _spec); err != nil {
|
||||
if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{err.Error(), err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
id := _spec.ID.Value.(int64)
|
||||
_node.ID = int(id)
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
func (cic *ConfigItemCreate) createSpec() (*ConfigItem, *sqlgraph.CreateSpec) {
|
||||
var (
|
||||
_node = &ConfigItem{config: cic.config}
|
||||
_spec = &sqlgraph.CreateSpec{
|
||||
Table: configitem.Table,
|
||||
ID: &sqlgraph.FieldSpec{
|
||||
Type: field.TypeInt,
|
||||
Column: configitem.FieldID,
|
||||
},
|
||||
}
|
||||
)
|
||||
if value, ok := cic.mutation.CreatedAt(); ok {
|
||||
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeTime,
|
||||
Value: value,
|
||||
Column: configitem.FieldCreatedAt,
|
||||
})
|
||||
_node.CreatedAt = &value
|
||||
}
|
||||
if value, ok := cic.mutation.UpdatedAt(); ok {
|
||||
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeTime,
|
||||
Value: value,
|
||||
Column: configitem.FieldUpdatedAt,
|
||||
})
|
||||
_node.UpdatedAt = &value
|
||||
}
|
||||
if value, ok := cic.mutation.Name(); ok {
|
||||
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: configitem.FieldName,
|
||||
})
|
||||
_node.Name = value
|
||||
}
|
||||
if value, ok := cic.mutation.Value(); ok {
|
||||
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: configitem.FieldValue,
|
||||
})
|
||||
_node.Value = value
|
||||
}
|
||||
return _node, _spec
|
||||
}
|
||||
|
||||
// ConfigItemCreateBulk is the builder for creating many ConfigItem entities in bulk.
|
||||
type ConfigItemCreateBulk struct {
|
||||
config
|
||||
builders []*ConfigItemCreate
|
||||
}
|
||||
|
||||
// Save creates the ConfigItem entities in the database.
|
||||
func (cicb *ConfigItemCreateBulk) Save(ctx context.Context) ([]*ConfigItem, error) {
|
||||
specs := make([]*sqlgraph.CreateSpec, len(cicb.builders))
|
||||
nodes := make([]*ConfigItem, len(cicb.builders))
|
||||
mutators := make([]Mutator, len(cicb.builders))
|
||||
for i := range cicb.builders {
|
||||
func(i int, root context.Context) {
|
||||
builder := cicb.builders[i]
|
||||
builder.defaults()
|
||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||
mutation, ok := m.(*ConfigItemMutation)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
||||
}
|
||||
if err := builder.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.mutation = mutation
|
||||
nodes[i], specs[i] = builder.createSpec()
|
||||
var err error
|
||||
if i < len(mutators)-1 {
|
||||
_, err = mutators[i+1].Mutate(root, cicb.builders[i+1].mutation)
|
||||
} else {
|
||||
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
|
||||
// Invoke the actual operation on the latest mutation in the chain.
|
||||
if err = sqlgraph.BatchCreate(ctx, cicb.driver, spec); err != nil {
|
||||
if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{err.Error(), err}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mutation.id = &nodes[i].ID
|
||||
mutation.done = true
|
||||
if specs[i].ID.Value != nil {
|
||||
id := specs[i].ID.Value.(int64)
|
||||
nodes[i].ID = int(id)
|
||||
}
|
||||
return nodes[i], nil
|
||||
})
|
||||
for i := len(builder.hooks) - 1; i >= 0; i-- {
|
||||
mut = builder.hooks[i](mut)
|
||||
}
|
||||
mutators[i] = mut
|
||||
}(i, ctx)
|
||||
}
|
||||
if len(mutators) > 0 {
|
||||
if _, err := mutators[0].Mutate(ctx, cicb.builders[0].mutation); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (cicb *ConfigItemCreateBulk) SaveX(ctx context.Context) []*ConfigItem {
|
||||
v, err := cicb.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (cicb *ConfigItemCreateBulk) Exec(ctx context.Context) error {
|
||||
_, err := cicb.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (cicb *ConfigItemCreateBulk) ExecX(ctx context.Context) {
|
||||
if err := cicb.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
111
pkg/database/ent/configitem_delete.go
Normal file
111
pkg/database/ent/configitem_delete.go
Normal file
|
@ -0,0 +1,111 @@
|
|||
// Code generated by entc, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/configitem"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/predicate"
|
||||
)
|
||||
|
||||
// ConfigItemDelete is the builder for deleting a ConfigItem entity.
|
||||
type ConfigItemDelete struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *ConfigItemMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the ConfigItemDelete builder.
|
||||
func (cid *ConfigItemDelete) Where(ps ...predicate.ConfigItem) *ConfigItemDelete {
|
||||
cid.mutation.Where(ps...)
|
||||
return cid
|
||||
}
|
||||
|
||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||
func (cid *ConfigItemDelete) Exec(ctx context.Context) (int, error) {
|
||||
var (
|
||||
err error
|
||||
affected int
|
||||
)
|
||||
if len(cid.hooks) == 0 {
|
||||
affected, err = cid.sqlExec(ctx)
|
||||
} else {
|
||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||
mutation, ok := m.(*ConfigItemMutation)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
||||
}
|
||||
cid.mutation = mutation
|
||||
affected, err = cid.sqlExec(ctx)
|
||||
mutation.done = true
|
||||
return affected, err
|
||||
})
|
||||
for i := len(cid.hooks) - 1; i >= 0; i-- {
|
||||
if cid.hooks[i] == nil {
|
||||
return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)")
|
||||
}
|
||||
mut = cid.hooks[i](mut)
|
||||
}
|
||||
if _, err := mut.Mutate(ctx, cid.mutation); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return affected, err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (cid *ConfigItemDelete) ExecX(ctx context.Context) int {
|
||||
n, err := cid.Exec(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (cid *ConfigItemDelete) sqlExec(ctx context.Context) (int, error) {
|
||||
_spec := &sqlgraph.DeleteSpec{
|
||||
Node: &sqlgraph.NodeSpec{
|
||||
Table: configitem.Table,
|
||||
ID: &sqlgraph.FieldSpec{
|
||||
Type: field.TypeInt,
|
||||
Column: configitem.FieldID,
|
||||
},
|
||||
},
|
||||
}
|
||||
if ps := cid.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
return sqlgraph.DeleteNodes(ctx, cid.driver, _spec)
|
||||
}
|
||||
|
||||
// ConfigItemDeleteOne is the builder for deleting a single ConfigItem entity.
|
||||
type ConfigItemDeleteOne struct {
|
||||
cid *ConfigItemDelete
|
||||
}
|
||||
|
||||
// Exec executes the deletion query.
|
||||
func (cido *ConfigItemDeleteOne) Exec(ctx context.Context) error {
|
||||
n, err := cido.cid.Exec(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case n == 0:
|
||||
return &NotFoundError{configitem.Label}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (cido *ConfigItemDeleteOne) ExecX(ctx context.Context) {
|
||||
cido.cid.ExecX(ctx)
|
||||
}
|
921
pkg/database/ent/configitem_query.go
Normal file
921
pkg/database/ent/configitem_query.go
Normal file
|
@ -0,0 +1,921 @@
|
|||
// Code generated by entc, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/configitem"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/predicate"
|
||||
)
|
||||
|
||||
// ConfigItemQuery is the builder for querying ConfigItem entities.
|
||||
type ConfigItemQuery struct {
|
||||
config
|
||||
limit *int
|
||||
offset *int
|
||||
unique *bool
|
||||
order []OrderFunc
|
||||
fields []string
|
||||
predicates []predicate.ConfigItem
|
||||
// intermediate query (i.e. traversal path).
|
||||
sql *sql.Selector
|
||||
path func(context.Context) (*sql.Selector, error)
|
||||
}
|
||||
|
||||
// Where adds a new predicate for the ConfigItemQuery builder.
|
||||
func (ciq *ConfigItemQuery) Where(ps ...predicate.ConfigItem) *ConfigItemQuery {
|
||||
ciq.predicates = append(ciq.predicates, ps...)
|
||||
return ciq
|
||||
}
|
||||
|
||||
// Limit adds a limit step to the query.
|
||||
func (ciq *ConfigItemQuery) Limit(limit int) *ConfigItemQuery {
|
||||
ciq.limit = &limit
|
||||
return ciq
|
||||
}
|
||||
|
||||
// Offset adds an offset step to the query.
|
||||
func (ciq *ConfigItemQuery) Offset(offset int) *ConfigItemQuery {
|
||||
ciq.offset = &offset
|
||||
return ciq
|
||||
}
|
||||
|
||||
// Unique configures the query builder to filter duplicate records on query.
|
||||
// By default, unique is set to true, and can be disabled using this method.
|
||||
func (ciq *ConfigItemQuery) Unique(unique bool) *ConfigItemQuery {
|
||||
ciq.unique = &unique
|
||||
return ciq
|
||||
}
|
||||
|
||||
// Order adds an order step to the query.
|
||||
func (ciq *ConfigItemQuery) Order(o ...OrderFunc) *ConfigItemQuery {
|
||||
ciq.order = append(ciq.order, o...)
|
||||
return ciq
|
||||
}
|
||||
|
||||
// First returns the first ConfigItem entity from the query.
|
||||
// Returns a *NotFoundError when no ConfigItem was found.
|
||||
func (ciq *ConfigItemQuery) First(ctx context.Context) (*ConfigItem, error) {
|
||||
nodes, err := ciq.Limit(1).All(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nil, &NotFoundError{configitem.Label}
|
||||
}
|
||||
return nodes[0], nil
|
||||
}
|
||||
|
||||
// FirstX is like First, but panics if an error occurs.
|
||||
func (ciq *ConfigItemQuery) FirstX(ctx context.Context) *ConfigItem {
|
||||
node, err := ciq.First(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// FirstID returns the first ConfigItem ID from the query.
|
||||
// Returns a *NotFoundError when no ConfigItem ID was found.
|
||||
func (ciq *ConfigItemQuery) FirstID(ctx context.Context) (id int, err error) {
|
||||
var ids []int
|
||||
if ids, err = ciq.Limit(1).IDs(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
err = &NotFoundError{configitem.Label}
|
||||
return
|
||||
}
|
||||
return ids[0], nil
|
||||
}
|
||||
|
||||
// FirstIDX is like FirstID, but panics if an error occurs.
|
||||
func (ciq *ConfigItemQuery) FirstIDX(ctx context.Context) int {
|
||||
id, err := ciq.FirstID(ctx)
|
||||
if err != nil && !IsNotFound(err) {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// Only returns a single ConfigItem entity found by the query, ensuring it only returns one.
|
||||
// Returns a *NotSingularError when more than one ConfigItem entity is found.
|
||||
// Returns a *NotFoundError when no ConfigItem entities are found.
|
||||
func (ciq *ConfigItemQuery) Only(ctx context.Context) (*ConfigItem, error) {
|
||||
nodes, err := ciq.Limit(2).All(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch len(nodes) {
|
||||
case 1:
|
||||
return nodes[0], nil
|
||||
case 0:
|
||||
return nil, &NotFoundError{configitem.Label}
|
||||
default:
|
||||
return nil, &NotSingularError{configitem.Label}
|
||||
}
|
||||
}
|
||||
|
||||
// OnlyX is like Only, but panics if an error occurs.
|
||||
func (ciq *ConfigItemQuery) OnlyX(ctx context.Context) *ConfigItem {
|
||||
node, err := ciq.Only(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// OnlyID is like Only, but returns the only ConfigItem ID in the query.
|
||||
// Returns a *NotSingularError when more than one ConfigItem ID is found.
|
||||
// Returns a *NotFoundError when no entities are found.
|
||||
func (ciq *ConfigItemQuery) OnlyID(ctx context.Context) (id int, err error) {
|
||||
var ids []int
|
||||
if ids, err = ciq.Limit(2).IDs(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(ids) {
|
||||
case 1:
|
||||
id = ids[0]
|
||||
case 0:
|
||||
err = &NotFoundError{configitem.Label}
|
||||
default:
|
||||
err = &NotSingularError{configitem.Label}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// OnlyIDX is like OnlyID, but panics if an error occurs.
|
||||
func (ciq *ConfigItemQuery) OnlyIDX(ctx context.Context) int {
|
||||
id, err := ciq.OnlyID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// All executes the query and returns a list of ConfigItems.
|
||||
func (ciq *ConfigItemQuery) All(ctx context.Context) ([]*ConfigItem, error) {
|
||||
if err := ciq.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ciq.sqlAll(ctx)
|
||||
}
|
||||
|
||||
// AllX is like All, but panics if an error occurs.
|
||||
func (ciq *ConfigItemQuery) AllX(ctx context.Context) []*ConfigItem {
|
||||
nodes, err := ciq.All(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
// IDs executes the query and returns a list of ConfigItem IDs.
|
||||
func (ciq *ConfigItemQuery) IDs(ctx context.Context) ([]int, error) {
|
||||
var ids []int
|
||||
if err := ciq.Select(configitem.FieldID).Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// IDsX is like IDs, but panics if an error occurs.
|
||||
func (ciq *ConfigItemQuery) IDsX(ctx context.Context) []int {
|
||||
ids, err := ciq.IDs(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// Count returns the count of the given query.
|
||||
func (ciq *ConfigItemQuery) Count(ctx context.Context) (int, error) {
|
||||
if err := ciq.prepareQuery(ctx); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return ciq.sqlCount(ctx)
|
||||
}
|
||||
|
||||
// CountX is like Count, but panics if an error occurs.
|
||||
func (ciq *ConfigItemQuery) CountX(ctx context.Context) int {
|
||||
count, err := ciq.Count(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Exist returns true if the query has elements in the graph.
|
||||
func (ciq *ConfigItemQuery) Exist(ctx context.Context) (bool, error) {
|
||||
if err := ciq.prepareQuery(ctx); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return ciq.sqlExist(ctx)
|
||||
}
|
||||
|
||||
// ExistX is like Exist, but panics if an error occurs.
|
||||
func (ciq *ConfigItemQuery) ExistX(ctx context.Context) bool {
|
||||
exist, err := ciq.Exist(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
// Clone returns a duplicate of the ConfigItemQuery builder, including all associated steps. It can be
|
||||
// used to prepare common query builders and use them differently after the clone is made.
|
||||
func (ciq *ConfigItemQuery) Clone() *ConfigItemQuery {
|
||||
if ciq == nil {
|
||||
return nil
|
||||
}
|
||||
return &ConfigItemQuery{
|
||||
config: ciq.config,
|
||||
limit: ciq.limit,
|
||||
offset: ciq.offset,
|
||||
order: append([]OrderFunc{}, ciq.order...),
|
||||
predicates: append([]predicate.ConfigItem{}, ciq.predicates...),
|
||||
// clone intermediate query.
|
||||
sql: ciq.sql.Clone(),
|
||||
path: ciq.path,
|
||||
unique: ciq.unique,
|
||||
}
|
||||
}
|
||||
|
||||
// GroupBy is used to group vertices by one or more fields/columns.
|
||||
// It is often used with aggregate functions, like: count, max, mean, min, sum.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at"`
|
||||
// Count int `json:"count,omitempty"`
|
||||
// }
|
||||
//
|
||||
// client.ConfigItem.Query().
|
||||
// GroupBy(configitem.FieldCreatedAt).
|
||||
// Aggregate(ent.Count()).
|
||||
// Scan(ctx, &v)
|
||||
//
|
||||
func (ciq *ConfigItemQuery) GroupBy(field string, fields ...string) *ConfigItemGroupBy {
|
||||
group := &ConfigItemGroupBy{config: ciq.config}
|
||||
group.fields = append([]string{field}, fields...)
|
||||
group.path = func(ctx context.Context) (prev *sql.Selector, err error) {
|
||||
if err := ciq.prepareQuery(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ciq.sqlQuery(ctx), nil
|
||||
}
|
||||
return group
|
||||
}
|
||||
|
||||
// Select allows the selection one or more fields/columns for the given query,
|
||||
// instead of selecting all fields in the entity.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var v []struct {
|
||||
// CreatedAt time.Time `json:"created_at"`
|
||||
// }
|
||||
//
|
||||
// client.ConfigItem.Query().
|
||||
// Select(configitem.FieldCreatedAt).
|
||||
// Scan(ctx, &v)
|
||||
//
|
||||
func (ciq *ConfigItemQuery) Select(fields ...string) *ConfigItemSelect {
|
||||
ciq.fields = append(ciq.fields, fields...)
|
||||
return &ConfigItemSelect{ConfigItemQuery: ciq}
|
||||
}
|
||||
|
||||
func (ciq *ConfigItemQuery) prepareQuery(ctx context.Context) error {
|
||||
for _, f := range ciq.fields {
|
||||
if !configitem.ValidColumn(f) {
|
||||
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
}
|
||||
if ciq.path != nil {
|
||||
prev, err := ciq.path(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ciq.sql = prev
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ciq *ConfigItemQuery) sqlAll(ctx context.Context) ([]*ConfigItem, error) {
|
||||
var (
|
||||
nodes = []*ConfigItem{}
|
||||
_spec = ciq.querySpec()
|
||||
)
|
||||
_spec.ScanValues = func(columns []string) ([]interface{}, error) {
|
||||
node := &ConfigItem{config: ciq.config}
|
||||
nodes = append(nodes, node)
|
||||
return node.scanValues(columns)
|
||||
}
|
||||
_spec.Assign = func(columns []string, values []interface{}) error {
|
||||
if len(nodes) == 0 {
|
||||
return fmt.Errorf("ent: Assign called without calling ScanValues")
|
||||
}
|
||||
node := nodes[len(nodes)-1]
|
||||
return node.assignValues(columns, values)
|
||||
}
|
||||
if err := sqlgraph.QueryNodes(ctx, ciq.driver, _spec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nodes, nil
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (ciq *ConfigItemQuery) sqlCount(ctx context.Context) (int, error) {
|
||||
_spec := ciq.querySpec()
|
||||
_spec.Node.Columns = ciq.fields
|
||||
if len(ciq.fields) > 0 {
|
||||
_spec.Unique = ciq.unique != nil && *ciq.unique
|
||||
}
|
||||
return sqlgraph.CountNodes(ctx, ciq.driver, _spec)
|
||||
}
|
||||
|
||||
func (ciq *ConfigItemQuery) sqlExist(ctx context.Context) (bool, error) {
|
||||
n, err := ciq.sqlCount(ctx)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("ent: check existence: %w", err)
|
||||
}
|
||||
return n > 0, nil
|
||||
}
|
||||
|
||||
func (ciq *ConfigItemQuery) querySpec() *sqlgraph.QuerySpec {
|
||||
_spec := &sqlgraph.QuerySpec{
|
||||
Node: &sqlgraph.NodeSpec{
|
||||
Table: configitem.Table,
|
||||
Columns: configitem.Columns,
|
||||
ID: &sqlgraph.FieldSpec{
|
||||
Type: field.TypeInt,
|
||||
Column: configitem.FieldID,
|
||||
},
|
||||
},
|
||||
From: ciq.sql,
|
||||
Unique: true,
|
||||
}
|
||||
if unique := ciq.unique; unique != nil {
|
||||
_spec.Unique = *unique
|
||||
}
|
||||
if fields := ciq.fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, configitem.FieldID)
|
||||
for i := range fields {
|
||||
if fields[i] != configitem.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
if ps := ciq.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if limit := ciq.limit; limit != nil {
|
||||
_spec.Limit = *limit
|
||||
}
|
||||
if offset := ciq.offset; offset != nil {
|
||||
_spec.Offset = *offset
|
||||
}
|
||||
if ps := ciq.order; len(ps) > 0 {
|
||||
_spec.Order = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
return _spec
|
||||
}
|
||||
|
||||
func (ciq *ConfigItemQuery) sqlQuery(ctx context.Context) *sql.Selector {
|
||||
builder := sql.Dialect(ciq.driver.Dialect())
|
||||
t1 := builder.Table(configitem.Table)
|
||||
columns := ciq.fields
|
||||
if len(columns) == 0 {
|
||||
columns = configitem.Columns
|
||||
}
|
||||
selector := builder.Select(t1.Columns(columns...)...).From(t1)
|
||||
if ciq.sql != nil {
|
||||
selector = ciq.sql
|
||||
selector.Select(selector.Columns(columns...)...)
|
||||
}
|
||||
if ciq.unique != nil && *ciq.unique {
|
||||
selector.Distinct()
|
||||
}
|
||||
for _, p := range ciq.predicates {
|
||||
p(selector)
|
||||
}
|
||||
for _, p := range ciq.order {
|
||||
p(selector)
|
||||
}
|
||||
if offset := ciq.offset; offset != nil {
|
||||
// limit is mandatory for offset clause. We start
|
||||
// with default value, and override it below if needed.
|
||||
selector.Offset(*offset).Limit(math.MaxInt32)
|
||||
}
|
||||
if limit := ciq.limit; limit != nil {
|
||||
selector.Limit(*limit)
|
||||
}
|
||||
return selector
|
||||
}
|
||||
|
||||
// ConfigItemGroupBy is the group-by builder for ConfigItem entities.
|
||||
type ConfigItemGroupBy struct {
|
||||
config
|
||||
fields []string
|
||||
fns []AggregateFunc
|
||||
// intermediate query (i.e. traversal path).
|
||||
sql *sql.Selector
|
||||
path func(context.Context) (*sql.Selector, error)
|
||||
}
|
||||
|
||||
// Aggregate adds the given aggregation functions to the group-by query.
|
||||
func (cigb *ConfigItemGroupBy) Aggregate(fns ...AggregateFunc) *ConfigItemGroupBy {
|
||||
cigb.fns = append(cigb.fns, fns...)
|
||||
return cigb
|
||||
}
|
||||
|
||||
// Scan applies the group-by query and scans the result into the given value.
|
||||
func (cigb *ConfigItemGroupBy) Scan(ctx context.Context, v interface{}) error {
|
||||
query, err := cigb.path(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cigb.sql = query
|
||||
return cigb.sqlScan(ctx, v)
|
||||
}
|
||||
|
||||
// ScanX is like Scan, but panics if an error occurs.
|
||||
func (cigb *ConfigItemGroupBy) ScanX(ctx context.Context, v interface{}) {
|
||||
if err := cigb.Scan(ctx, v); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Strings returns list of strings from group-by.
|
||||
// It is only allowed when executing a group-by query with one field.
|
||||
func (cigb *ConfigItemGroupBy) Strings(ctx context.Context) ([]string, error) {
|
||||
if len(cigb.fields) > 1 {
|
||||
return nil, errors.New("ent: ConfigItemGroupBy.Strings is not achievable when grouping more than 1 field")
|
||||
}
|
||||
var v []string
|
||||
if err := cigb.Scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// StringsX is like Strings, but panics if an error occurs.
|
||||
func (cigb *ConfigItemGroupBy) StringsX(ctx context.Context) []string {
|
||||
v, err := cigb.Strings(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// String returns a single string from a group-by query.
|
||||
// It is only allowed when executing a group-by query with one field.
|
||||
func (cigb *ConfigItemGroupBy) String(ctx context.Context) (_ string, err error) {
|
||||
var v []string
|
||||
if v, err = cigb.Strings(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{configitem.Label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: ConfigItemGroupBy.Strings returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StringX is like String, but panics if an error occurs.
|
||||
func (cigb *ConfigItemGroupBy) StringX(ctx context.Context) string {
|
||||
v, err := cigb.String(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Ints returns list of ints from group-by.
|
||||
// It is only allowed when executing a group-by query with one field.
|
||||
func (cigb *ConfigItemGroupBy) Ints(ctx context.Context) ([]int, error) {
|
||||
if len(cigb.fields) > 1 {
|
||||
return nil, errors.New("ent: ConfigItemGroupBy.Ints is not achievable when grouping more than 1 field")
|
||||
}
|
||||
var v []int
|
||||
if err := cigb.Scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// IntsX is like Ints, but panics if an error occurs.
|
||||
func (cigb *ConfigItemGroupBy) IntsX(ctx context.Context) []int {
|
||||
v, err := cigb.Ints(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Int returns a single int from a group-by query.
|
||||
// It is only allowed when executing a group-by query with one field.
|
||||
func (cigb *ConfigItemGroupBy) Int(ctx context.Context) (_ int, err error) {
|
||||
var v []int
|
||||
if v, err = cigb.Ints(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{configitem.Label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: ConfigItemGroupBy.Ints returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// IntX is like Int, but panics if an error occurs.
|
||||
func (cigb *ConfigItemGroupBy) IntX(ctx context.Context) int {
|
||||
v, err := cigb.Int(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Float64s returns list of float64s from group-by.
|
||||
// It is only allowed when executing a group-by query with one field.
|
||||
func (cigb *ConfigItemGroupBy) Float64s(ctx context.Context) ([]float64, error) {
|
||||
if len(cigb.fields) > 1 {
|
||||
return nil, errors.New("ent: ConfigItemGroupBy.Float64s is not achievable when grouping more than 1 field")
|
||||
}
|
||||
var v []float64
|
||||
if err := cigb.Scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Float64sX is like Float64s, but panics if an error occurs.
|
||||
func (cigb *ConfigItemGroupBy) Float64sX(ctx context.Context) []float64 {
|
||||
v, err := cigb.Float64s(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Float64 returns a single float64 from a group-by query.
|
||||
// It is only allowed when executing a group-by query with one field.
|
||||
func (cigb *ConfigItemGroupBy) Float64(ctx context.Context) (_ float64, err error) {
|
||||
var v []float64
|
||||
if v, err = cigb.Float64s(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{configitem.Label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: ConfigItemGroupBy.Float64s returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Float64X is like Float64, but panics if an error occurs.
|
||||
func (cigb *ConfigItemGroupBy) Float64X(ctx context.Context) float64 {
|
||||
v, err := cigb.Float64(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Bools returns list of bools from group-by.
|
||||
// It is only allowed when executing a group-by query with one field.
|
||||
func (cigb *ConfigItemGroupBy) Bools(ctx context.Context) ([]bool, error) {
|
||||
if len(cigb.fields) > 1 {
|
||||
return nil, errors.New("ent: ConfigItemGroupBy.Bools is not achievable when grouping more than 1 field")
|
||||
}
|
||||
var v []bool
|
||||
if err := cigb.Scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// BoolsX is like Bools, but panics if an error occurs.
|
||||
func (cigb *ConfigItemGroupBy) BoolsX(ctx context.Context) []bool {
|
||||
v, err := cigb.Bools(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Bool returns a single bool from a group-by query.
|
||||
// It is only allowed when executing a group-by query with one field.
|
||||
func (cigb *ConfigItemGroupBy) Bool(ctx context.Context) (_ bool, err error) {
|
||||
var v []bool
|
||||
if v, err = cigb.Bools(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{configitem.Label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: ConfigItemGroupBy.Bools returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BoolX is like Bool, but panics if an error occurs.
|
||||
func (cigb *ConfigItemGroupBy) BoolX(ctx context.Context) bool {
|
||||
v, err := cigb.Bool(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (cigb *ConfigItemGroupBy) sqlScan(ctx context.Context, v interface{}) error {
|
||||
for _, f := range cigb.fields {
|
||||
if !configitem.ValidColumn(f) {
|
||||
return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)}
|
||||
}
|
||||
}
|
||||
selector := cigb.sqlQuery()
|
||||
if err := selector.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
rows := &sql.Rows{}
|
||||
query, args := selector.Query()
|
||||
if err := cigb.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
||||
|
||||
func (cigb *ConfigItemGroupBy) sqlQuery() *sql.Selector {
|
||||
selector := cigb.sql.Select()
|
||||
aggregation := make([]string, 0, len(cigb.fns))
|
||||
for _, fn := range cigb.fns {
|
||||
aggregation = append(aggregation, fn(selector))
|
||||
}
|
||||
// If no columns were selected in a custom aggregation function, the default
|
||||
// selection is the fields used for "group-by", and the aggregation functions.
|
||||
if len(selector.SelectedColumns()) == 0 {
|
||||
columns := make([]string, 0, len(cigb.fields)+len(cigb.fns))
|
||||
for _, f := range cigb.fields {
|
||||
columns = append(columns, selector.C(f))
|
||||
}
|
||||
columns = append(columns, aggregation...)
|
||||
selector.Select(columns...)
|
||||
}
|
||||
return selector.GroupBy(selector.Columns(cigb.fields...)...)
|
||||
}
|
||||
|
||||
// ConfigItemSelect is the builder for selecting fields of ConfigItem entities.
|
||||
type ConfigItemSelect struct {
|
||||
*ConfigItemQuery
|
||||
// intermediate query (i.e. traversal path).
|
||||
sql *sql.Selector
|
||||
}
|
||||
|
||||
// Scan applies the selector query and scans the result into the given value.
|
||||
func (cis *ConfigItemSelect) Scan(ctx context.Context, v interface{}) error {
|
||||
if err := cis.prepareQuery(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
cis.sql = cis.ConfigItemQuery.sqlQuery(ctx)
|
||||
return cis.sqlScan(ctx, v)
|
||||
}
|
||||
|
||||
// ScanX is like Scan, but panics if an error occurs.
|
||||
func (cis *ConfigItemSelect) ScanX(ctx context.Context, v interface{}) {
|
||||
if err := cis.Scan(ctx, v); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Strings returns list of strings from a selector. It is only allowed when selecting one field.
|
||||
func (cis *ConfigItemSelect) Strings(ctx context.Context) ([]string, error) {
|
||||
if len(cis.fields) > 1 {
|
||||
return nil, errors.New("ent: ConfigItemSelect.Strings is not achievable when selecting more than 1 field")
|
||||
}
|
||||
var v []string
|
||||
if err := cis.Scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// StringsX is like Strings, but panics if an error occurs.
|
||||
func (cis *ConfigItemSelect) StringsX(ctx context.Context) []string {
|
||||
v, err := cis.Strings(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// String returns a single string from a selector. It is only allowed when selecting one field.
|
||||
func (cis *ConfigItemSelect) String(ctx context.Context) (_ string, err error) {
|
||||
var v []string
|
||||
if v, err = cis.Strings(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{configitem.Label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: ConfigItemSelect.Strings returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StringX is like String, but panics if an error occurs.
|
||||
func (cis *ConfigItemSelect) StringX(ctx context.Context) string {
|
||||
v, err := cis.String(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Ints returns list of ints from a selector. It is only allowed when selecting one field.
|
||||
func (cis *ConfigItemSelect) Ints(ctx context.Context) ([]int, error) {
|
||||
if len(cis.fields) > 1 {
|
||||
return nil, errors.New("ent: ConfigItemSelect.Ints is not achievable when selecting more than 1 field")
|
||||
}
|
||||
var v []int
|
||||
if err := cis.Scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// IntsX is like Ints, but panics if an error occurs.
|
||||
func (cis *ConfigItemSelect) IntsX(ctx context.Context) []int {
|
||||
v, err := cis.Ints(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Int returns a single int from a selector. It is only allowed when selecting one field.
|
||||
func (cis *ConfigItemSelect) Int(ctx context.Context) (_ int, err error) {
|
||||
var v []int
|
||||
if v, err = cis.Ints(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{configitem.Label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: ConfigItemSelect.Ints returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// IntX is like Int, but panics if an error occurs.
|
||||
func (cis *ConfigItemSelect) IntX(ctx context.Context) int {
|
||||
v, err := cis.Int(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Float64s returns list of float64s from a selector. It is only allowed when selecting one field.
|
||||
func (cis *ConfigItemSelect) Float64s(ctx context.Context) ([]float64, error) {
|
||||
if len(cis.fields) > 1 {
|
||||
return nil, errors.New("ent: ConfigItemSelect.Float64s is not achievable when selecting more than 1 field")
|
||||
}
|
||||
var v []float64
|
||||
if err := cis.Scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Float64sX is like Float64s, but panics if an error occurs.
|
||||
func (cis *ConfigItemSelect) Float64sX(ctx context.Context) []float64 {
|
||||
v, err := cis.Float64s(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Float64 returns a single float64 from a selector. It is only allowed when selecting one field.
|
||||
func (cis *ConfigItemSelect) Float64(ctx context.Context) (_ float64, err error) {
|
||||
var v []float64
|
||||
if v, err = cis.Float64s(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{configitem.Label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: ConfigItemSelect.Float64s returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Float64X is like Float64, but panics if an error occurs.
|
||||
func (cis *ConfigItemSelect) Float64X(ctx context.Context) float64 {
|
||||
v, err := cis.Float64(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Bools returns list of bools from a selector. It is only allowed when selecting one field.
|
||||
func (cis *ConfigItemSelect) Bools(ctx context.Context) ([]bool, error) {
|
||||
if len(cis.fields) > 1 {
|
||||
return nil, errors.New("ent: ConfigItemSelect.Bools is not achievable when selecting more than 1 field")
|
||||
}
|
||||
var v []bool
|
||||
if err := cis.Scan(ctx, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// BoolsX is like Bools, but panics if an error occurs.
|
||||
func (cis *ConfigItemSelect) BoolsX(ctx context.Context) []bool {
|
||||
v, err := cis.Bools(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Bool returns a single bool from a selector. It is only allowed when selecting one field.
|
||||
func (cis *ConfigItemSelect) Bool(ctx context.Context) (_ bool, err error) {
|
||||
var v []bool
|
||||
if v, err = cis.Bools(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
switch len(v) {
|
||||
case 1:
|
||||
return v[0], nil
|
||||
case 0:
|
||||
err = &NotFoundError{configitem.Label}
|
||||
default:
|
||||
err = fmt.Errorf("ent: ConfigItemSelect.Bools returned %d results when one was expected", len(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BoolX is like Bool, but panics if an error occurs.
|
||||
func (cis *ConfigItemSelect) BoolX(ctx context.Context) bool {
|
||||
v, err := cis.Bool(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (cis *ConfigItemSelect) sqlScan(ctx context.Context, v interface{}) error {
|
||||
rows := &sql.Rows{}
|
||||
query, args := cis.sql.Query()
|
||||
if err := cis.driver.Query(ctx, query, args, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
return sql.ScanSlice(rows, v)
|
||||
}
|
418
pkg/database/ent/configitem_update.go
Normal file
418
pkg/database/ent/configitem_update.go
Normal file
|
@ -0,0 +1,418 @@
|
|||
// Code generated by entc, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/configitem"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/predicate"
|
||||
)
|
||||
|
||||
// ConfigItemUpdate is the builder for updating ConfigItem entities.
|
||||
type ConfigItemUpdate struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *ConfigItemMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the ConfigItemUpdate builder.
|
||||
func (ciu *ConfigItemUpdate) Where(ps ...predicate.ConfigItem) *ConfigItemUpdate {
|
||||
ciu.mutation.Where(ps...)
|
||||
return ciu
|
||||
}
|
||||
|
||||
// SetCreatedAt sets the "created_at" field.
|
||||
func (ciu *ConfigItemUpdate) SetCreatedAt(t time.Time) *ConfigItemUpdate {
|
||||
ciu.mutation.SetCreatedAt(t)
|
||||
return ciu
|
||||
}
|
||||
|
||||
// ClearCreatedAt clears the value of the "created_at" field.
|
||||
func (ciu *ConfigItemUpdate) ClearCreatedAt() *ConfigItemUpdate {
|
||||
ciu.mutation.ClearCreatedAt()
|
||||
return ciu
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (ciu *ConfigItemUpdate) SetUpdatedAt(t time.Time) *ConfigItemUpdate {
|
||||
ciu.mutation.SetUpdatedAt(t)
|
||||
return ciu
|
||||
}
|
||||
|
||||
// ClearUpdatedAt clears the value of the "updated_at" field.
|
||||
func (ciu *ConfigItemUpdate) ClearUpdatedAt() *ConfigItemUpdate {
|
||||
ciu.mutation.ClearUpdatedAt()
|
||||
return ciu
|
||||
}
|
||||
|
||||
// SetName sets the "name" field.
|
||||
func (ciu *ConfigItemUpdate) SetName(s string) *ConfigItemUpdate {
|
||||
ciu.mutation.SetName(s)
|
||||
return ciu
|
||||
}
|
||||
|
||||
// SetValue sets the "value" field.
|
||||
func (ciu *ConfigItemUpdate) SetValue(s string) *ConfigItemUpdate {
|
||||
ciu.mutation.SetValue(s)
|
||||
return ciu
|
||||
}
|
||||
|
||||
// Mutation returns the ConfigItemMutation object of the builder.
|
||||
func (ciu *ConfigItemUpdate) Mutation() *ConfigItemMutation {
|
||||
return ciu.mutation
|
||||
}
|
||||
|
||||
// Save executes the query and returns the number of nodes affected by the update operation.
|
||||
func (ciu *ConfigItemUpdate) Save(ctx context.Context) (int, error) {
|
||||
var (
|
||||
err error
|
||||
affected int
|
||||
)
|
||||
ciu.defaults()
|
||||
if len(ciu.hooks) == 0 {
|
||||
affected, err = ciu.sqlSave(ctx)
|
||||
} else {
|
||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||
mutation, ok := m.(*ConfigItemMutation)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
||||
}
|
||||
ciu.mutation = mutation
|
||||
affected, err = ciu.sqlSave(ctx)
|
||||
mutation.done = true
|
||||
return affected, err
|
||||
})
|
||||
for i := len(ciu.hooks) - 1; i >= 0; i-- {
|
||||
if ciu.hooks[i] == nil {
|
||||
return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)")
|
||||
}
|
||||
mut = ciu.hooks[i](mut)
|
||||
}
|
||||
if _, err := mut.Mutate(ctx, ciu.mutation); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return affected, err
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (ciu *ConfigItemUpdate) SaveX(ctx context.Context) int {
|
||||
affected, err := ciu.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (ciu *ConfigItemUpdate) Exec(ctx context.Context) error {
|
||||
_, err := ciu.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (ciu *ConfigItemUpdate) ExecX(ctx context.Context) {
|
||||
if err := ciu.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (ciu *ConfigItemUpdate) defaults() {
|
||||
if _, ok := ciu.mutation.CreatedAt(); !ok && !ciu.mutation.CreatedAtCleared() {
|
||||
v := configitem.UpdateDefaultCreatedAt()
|
||||
ciu.mutation.SetCreatedAt(v)
|
||||
}
|
||||
if _, ok := ciu.mutation.UpdatedAt(); !ok && !ciu.mutation.UpdatedAtCleared() {
|
||||
v := configitem.UpdateDefaultUpdatedAt()
|
||||
ciu.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
func (ciu *ConfigItemUpdate) sqlSave(ctx context.Context) (n int, err error) {
|
||||
_spec := &sqlgraph.UpdateSpec{
|
||||
Node: &sqlgraph.NodeSpec{
|
||||
Table: configitem.Table,
|
||||
Columns: configitem.Columns,
|
||||
ID: &sqlgraph.FieldSpec{
|
||||
Type: field.TypeInt,
|
||||
Column: configitem.FieldID,
|
||||
},
|
||||
},
|
||||
}
|
||||
if ps := ciu.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := ciu.mutation.CreatedAt(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeTime,
|
||||
Value: value,
|
||||
Column: configitem.FieldCreatedAt,
|
||||
})
|
||||
}
|
||||
if ciu.mutation.CreatedAtCleared() {
|
||||
_spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeTime,
|
||||
Column: configitem.FieldCreatedAt,
|
||||
})
|
||||
}
|
||||
if value, ok := ciu.mutation.UpdatedAt(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeTime,
|
||||
Value: value,
|
||||
Column: configitem.FieldUpdatedAt,
|
||||
})
|
||||
}
|
||||
if ciu.mutation.UpdatedAtCleared() {
|
||||
_spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeTime,
|
||||
Column: configitem.FieldUpdatedAt,
|
||||
})
|
||||
}
|
||||
if value, ok := ciu.mutation.Name(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: configitem.FieldName,
|
||||
})
|
||||
}
|
||||
if value, ok := ciu.mutation.Value(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: configitem.FieldValue,
|
||||
})
|
||||
}
|
||||
if n, err = sqlgraph.UpdateNodes(ctx, ciu.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{configitem.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{err.Error(), err}
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// ConfigItemUpdateOne is the builder for updating a single ConfigItem entity.
|
||||
type ConfigItemUpdateOne struct {
|
||||
config
|
||||
fields []string
|
||||
hooks []Hook
|
||||
mutation *ConfigItemMutation
|
||||
}
|
||||
|
||||
// SetCreatedAt sets the "created_at" field.
|
||||
func (ciuo *ConfigItemUpdateOne) SetCreatedAt(t time.Time) *ConfigItemUpdateOne {
|
||||
ciuo.mutation.SetCreatedAt(t)
|
||||
return ciuo
|
||||
}
|
||||
|
||||
// ClearCreatedAt clears the value of the "created_at" field.
|
||||
func (ciuo *ConfigItemUpdateOne) ClearCreatedAt() *ConfigItemUpdateOne {
|
||||
ciuo.mutation.ClearCreatedAt()
|
||||
return ciuo
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (ciuo *ConfigItemUpdateOne) SetUpdatedAt(t time.Time) *ConfigItemUpdateOne {
|
||||
ciuo.mutation.SetUpdatedAt(t)
|
||||
return ciuo
|
||||
}
|
||||
|
||||
// ClearUpdatedAt clears the value of the "updated_at" field.
|
||||
func (ciuo *ConfigItemUpdateOne) ClearUpdatedAt() *ConfigItemUpdateOne {
|
||||
ciuo.mutation.ClearUpdatedAt()
|
||||
return ciuo
|
||||
}
|
||||
|
||||
// SetName sets the "name" field.
|
||||
func (ciuo *ConfigItemUpdateOne) SetName(s string) *ConfigItemUpdateOne {
|
||||
ciuo.mutation.SetName(s)
|
||||
return ciuo
|
||||
}
|
||||
|
||||
// SetValue sets the "value" field.
|
||||
func (ciuo *ConfigItemUpdateOne) SetValue(s string) *ConfigItemUpdateOne {
|
||||
ciuo.mutation.SetValue(s)
|
||||
return ciuo
|
||||
}
|
||||
|
||||
// Mutation returns the ConfigItemMutation object of the builder.
|
||||
func (ciuo *ConfigItemUpdateOne) Mutation() *ConfigItemMutation {
|
||||
return ciuo.mutation
|
||||
}
|
||||
|
||||
// Select allows selecting one or more fields (columns) of the returned entity.
|
||||
// The default is selecting all fields defined in the entity schema.
|
||||
func (ciuo *ConfigItemUpdateOne) Select(field string, fields ...string) *ConfigItemUpdateOne {
|
||||
ciuo.fields = append([]string{field}, fields...)
|
||||
return ciuo
|
||||
}
|
||||
|
||||
// Save executes the query and returns the updated ConfigItem entity.
|
||||
func (ciuo *ConfigItemUpdateOne) Save(ctx context.Context) (*ConfigItem, error) {
|
||||
var (
|
||||
err error
|
||||
node *ConfigItem
|
||||
)
|
||||
ciuo.defaults()
|
||||
if len(ciuo.hooks) == 0 {
|
||||
node, err = ciuo.sqlSave(ctx)
|
||||
} else {
|
||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||
mutation, ok := m.(*ConfigItemMutation)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
||||
}
|
||||
ciuo.mutation = mutation
|
||||
node, err = ciuo.sqlSave(ctx)
|
||||
mutation.done = true
|
||||
return node, err
|
||||
})
|
||||
for i := len(ciuo.hooks) - 1; i >= 0; i-- {
|
||||
if ciuo.hooks[i] == nil {
|
||||
return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)")
|
||||
}
|
||||
mut = ciuo.hooks[i](mut)
|
||||
}
|
||||
if _, err := mut.Mutate(ctx, ciuo.mutation); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return node, err
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (ciuo *ConfigItemUpdateOne) SaveX(ctx context.Context) *ConfigItem {
|
||||
node, err := ciuo.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// Exec executes the query on the entity.
|
||||
func (ciuo *ConfigItemUpdateOne) Exec(ctx context.Context) error {
|
||||
_, err := ciuo.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (ciuo *ConfigItemUpdateOne) ExecX(ctx context.Context) {
|
||||
if err := ciuo.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (ciuo *ConfigItemUpdateOne) defaults() {
|
||||
if _, ok := ciuo.mutation.CreatedAt(); !ok && !ciuo.mutation.CreatedAtCleared() {
|
||||
v := configitem.UpdateDefaultCreatedAt()
|
||||
ciuo.mutation.SetCreatedAt(v)
|
||||
}
|
||||
if _, ok := ciuo.mutation.UpdatedAt(); !ok && !ciuo.mutation.UpdatedAtCleared() {
|
||||
v := configitem.UpdateDefaultUpdatedAt()
|
||||
ciuo.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
}
|
||||
|
||||
func (ciuo *ConfigItemUpdateOne) sqlSave(ctx context.Context) (_node *ConfigItem, err error) {
|
||||
_spec := &sqlgraph.UpdateSpec{
|
||||
Node: &sqlgraph.NodeSpec{
|
||||
Table: configitem.Table,
|
||||
Columns: configitem.Columns,
|
||||
ID: &sqlgraph.FieldSpec{
|
||||
Type: field.TypeInt,
|
||||
Column: configitem.FieldID,
|
||||
},
|
||||
},
|
||||
}
|
||||
id, ok := ciuo.mutation.ID()
|
||||
if !ok {
|
||||
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ConfigItem.id" for update`)}
|
||||
}
|
||||
_spec.Node.ID.Value = id
|
||||
if fields := ciuo.fields; len(fields) > 0 {
|
||||
_spec.Node.Columns = make([]string, 0, len(fields))
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, configitem.FieldID)
|
||||
for _, f := range fields {
|
||||
if !configitem.ValidColumn(f) {
|
||||
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
|
||||
}
|
||||
if f != configitem.FieldID {
|
||||
_spec.Node.Columns = append(_spec.Node.Columns, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ps := ciuo.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value, ok := ciuo.mutation.CreatedAt(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeTime,
|
||||
Value: value,
|
||||
Column: configitem.FieldCreatedAt,
|
||||
})
|
||||
}
|
||||
if ciuo.mutation.CreatedAtCleared() {
|
||||
_spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeTime,
|
||||
Column: configitem.FieldCreatedAt,
|
||||
})
|
||||
}
|
||||
if value, ok := ciuo.mutation.UpdatedAt(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeTime,
|
||||
Value: value,
|
||||
Column: configitem.FieldUpdatedAt,
|
||||
})
|
||||
}
|
||||
if ciuo.mutation.UpdatedAtCleared() {
|
||||
_spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeTime,
|
||||
Column: configitem.FieldUpdatedAt,
|
||||
})
|
||||
}
|
||||
if value, ok := ciuo.mutation.Name(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: configitem.FieldName,
|
||||
})
|
||||
}
|
||||
if value, ok := ciuo.mutation.Value(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: configitem.FieldValue,
|
||||
})
|
||||
}
|
||||
_node = &ConfigItem{config: ciuo.config}
|
||||
_spec.Assign = _node.assignValues
|
||||
_spec.ScanValues = _node.scanValues
|
||||
if err = sqlgraph.UpdateNode(ctx, ciuo.driver, _spec); err != nil {
|
||||
if _, ok := err.(*sqlgraph.NotFoundError); ok {
|
||||
err = &NotFoundError{configitem.Label}
|
||||
} else if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{err.Error(), err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return _node, nil
|
||||
}
|
|
@ -45,6 +45,8 @@ type Decision struct {
|
|||
Origin string `json:"origin,omitempty"`
|
||||
// Simulated holds the value of the "simulated" field.
|
||||
Simulated bool `json:"simulated,omitempty"`
|
||||
// UUID holds the value of the "uuid" field.
|
||||
UUID string `json:"uuid,omitempty"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the DecisionQuery when eager-loading is set.
|
||||
Edges DecisionEdges `json:"edges"`
|
||||
|
@ -82,7 +84,7 @@ func (*Decision) scanValues(columns []string) ([]any, error) {
|
|||
values[i] = new(sql.NullBool)
|
||||
case decision.FieldID, decision.FieldStartIP, decision.FieldEndIP, decision.FieldStartSuffix, decision.FieldEndSuffix, decision.FieldIPSize:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case decision.FieldScenario, decision.FieldType, decision.FieldScope, decision.FieldValue, decision.FieldOrigin:
|
||||
case decision.FieldScenario, decision.FieldType, decision.FieldScope, decision.FieldValue, decision.FieldOrigin, decision.FieldUUID:
|
||||
values[i] = new(sql.NullString)
|
||||
case decision.FieldCreatedAt, decision.FieldUpdatedAt, decision.FieldUntil:
|
||||
values[i] = new(sql.NullTime)
|
||||
|
@ -196,6 +198,12 @@ func (d *Decision) assignValues(columns []string, values []any) error {
|
|||
} else if value.Valid {
|
||||
d.Simulated = value.Bool
|
||||
}
|
||||
case decision.FieldUUID:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field uuid", values[i])
|
||||
} else if value.Valid {
|
||||
d.UUID = value.String
|
||||
}
|
||||
case decision.ForeignKeys[0]:
|
||||
if value, ok := values[i].(*sql.NullInt64); !ok {
|
||||
return fmt.Errorf("unexpected type %T for edge-field alert_decisions", value)
|
||||
|
@ -283,6 +291,8 @@ func (d *Decision) String() string {
|
|||
builder.WriteString(", ")
|
||||
builder.WriteString("simulated=")
|
||||
builder.WriteString(fmt.Sprintf("%v", d.Simulated))
|
||||
builder.WriteString(", uuid=")
|
||||
builder.WriteString(d.UUID)
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ const (
|
|||
FieldOrigin = "origin"
|
||||
// FieldSimulated holds the string denoting the simulated field in the database.
|
||||
FieldSimulated = "simulated"
|
||||
// FieldUUID holds the string denoting the uuid field in the database.
|
||||
FieldUUID = "uuid"
|
||||
// EdgeOwner holds the string denoting the owner edge name in mutations.
|
||||
EdgeOwner = "owner"
|
||||
// Table holds the table name of the decision in the database.
|
||||
|
@ -69,6 +71,7 @@ var Columns = []string{
|
|||
FieldValue,
|
||||
FieldOrigin,
|
||||
FieldSimulated,
|
||||
FieldUUID,
|
||||
}
|
||||
|
||||
// ForeignKeys holds the SQL foreign-keys that are owned by the "decisions"
|
||||
|
|
|
@ -179,6 +179,13 @@ func Simulated(v bool) predicate.Decision {
|
|||
})
|
||||
}
|
||||
|
||||
// UUID applies equality check predicate on the "uuid" field. It's identical to UUIDEQ.
|
||||
func UUID(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
|
||||
func CreatedAtEQ(v time.Time) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
|
@ -1312,6 +1319,131 @@ func SimulatedNEQ(v bool) predicate.Decision {
|
|||
})
|
||||
}
|
||||
|
||||
// UUIDEQ applies the EQ predicate on the "uuid" field.
|
||||
func UUIDEQ(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDNEQ applies the NEQ predicate on the "uuid" field.
|
||||
func UUIDNEQ(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.NEQ(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDIn applies the In predicate on the "uuid" field.
|
||||
func UUIDIn(vs ...string) predicate.Decision {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.In(s.C(FieldUUID), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDNotIn applies the NotIn predicate on the "uuid" field.
|
||||
func UUIDNotIn(vs ...string) predicate.Decision {
|
||||
v := make([]interface{}, len(vs))
|
||||
for i := range v {
|
||||
v[i] = vs[i]
|
||||
}
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
// if not arguments were provided, append the FALSE constants,
|
||||
// since we can't apply "IN ()". This will make this predicate falsy.
|
||||
if len(v) == 0 {
|
||||
s.Where(sql.False())
|
||||
return
|
||||
}
|
||||
s.Where(sql.NotIn(s.C(FieldUUID), v...))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDGT applies the GT predicate on the "uuid" field.
|
||||
func UUIDGT(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.GT(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDGTE applies the GTE predicate on the "uuid" field.
|
||||
func UUIDGTE(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.GTE(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDLT applies the LT predicate on the "uuid" field.
|
||||
func UUIDLT(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.LT(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDLTE applies the LTE predicate on the "uuid" field.
|
||||
func UUIDLTE(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.LTE(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDContains applies the Contains predicate on the "uuid" field.
|
||||
func UUIDContains(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.Contains(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDHasPrefix applies the HasPrefix predicate on the "uuid" field.
|
||||
func UUIDHasPrefix(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.HasPrefix(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDHasSuffix applies the HasSuffix predicate on the "uuid" field.
|
||||
func UUIDHasSuffix(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.HasSuffix(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDIsNil applies the IsNil predicate on the "uuid" field.
|
||||
func UUIDIsNil() predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.IsNull(s.C(FieldUUID)))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDNotNil applies the NotNil predicate on the "uuid" field.
|
||||
func UUIDNotNil() predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.NotNull(s.C(FieldUUID)))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDEqualFold applies the EqualFold predicate on the "uuid" field.
|
||||
func UUIDEqualFold(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.EqualFold(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// UUIDContainsFold applies the ContainsFold predicate on the "uuid" field.
|
||||
func UUIDContainsFold(v string) predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
s.Where(sql.ContainsFold(s.C(FieldUUID), v))
|
||||
})
|
||||
}
|
||||
|
||||
// HasOwner applies the HasEdge predicate on the "owner" edge.
|
||||
func HasOwner() predicate.Decision {
|
||||
return predicate.Decision(func(s *sql.Selector) {
|
||||
|
|
|
@ -177,6 +177,20 @@ func (dc *DecisionCreate) SetNillableSimulated(b *bool) *DecisionCreate {
|
|||
return dc
|
||||
}
|
||||
|
||||
// SetUUID sets the "uuid" field.
|
||||
func (dc *DecisionCreate) SetUUID(s string) *DecisionCreate {
|
||||
dc.mutation.SetUUID(s)
|
||||
return dc
|
||||
}
|
||||
|
||||
// SetNillableUUID sets the "uuid" field if the given value is not nil.
|
||||
func (dc *DecisionCreate) SetNillableUUID(s *string) *DecisionCreate {
|
||||
if s != nil {
|
||||
dc.SetUUID(*s)
|
||||
}
|
||||
return dc
|
||||
}
|
||||
|
||||
// SetOwnerID sets the "owner" edge to the Alert entity by ID.
|
||||
func (dc *DecisionCreate) SetOwnerID(id int) *DecisionCreate {
|
||||
dc.mutation.SetOwnerID(id)
|
||||
|
@ -446,6 +460,14 @@ func (dc *DecisionCreate) createSpec() (*Decision, *sqlgraph.CreateSpec) {
|
|||
})
|
||||
_node.Simulated = value
|
||||
}
|
||||
if value, ok := dc.mutation.UUID(); ok {
|
||||
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: decision.FieldUUID,
|
||||
})
|
||||
_node.UUID = value
|
||||
}
|
||||
if nodes := dc.mutation.OwnerIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
|
|
|
@ -252,6 +252,26 @@ func (du *DecisionUpdate) SetNillableSimulated(b *bool) *DecisionUpdate {
|
|||
return du
|
||||
}
|
||||
|
||||
// SetUUID sets the "uuid" field.
|
||||
func (du *DecisionUpdate) SetUUID(s string) *DecisionUpdate {
|
||||
du.mutation.SetUUID(s)
|
||||
return du
|
||||
}
|
||||
|
||||
// SetNillableUUID sets the "uuid" field if the given value is not nil.
|
||||
func (du *DecisionUpdate) SetNillableUUID(s *string) *DecisionUpdate {
|
||||
if s != nil {
|
||||
du.SetUUID(*s)
|
||||
}
|
||||
return du
|
||||
}
|
||||
|
||||
// ClearUUID clears the value of the "uuid" field.
|
||||
func (du *DecisionUpdate) ClearUUID() *DecisionUpdate {
|
||||
du.mutation.ClearUUID()
|
||||
return du
|
||||
}
|
||||
|
||||
// SetOwnerID sets the "owner" edge to the Alert entity by ID.
|
||||
func (du *DecisionUpdate) SetOwnerID(id int) *DecisionUpdate {
|
||||
du.mutation.SetOwnerID(id)
|
||||
|
@ -548,6 +568,19 @@ func (du *DecisionUpdate) sqlSave(ctx context.Context) (n int, err error) {
|
|||
Column: decision.FieldSimulated,
|
||||
})
|
||||
}
|
||||
if value, ok := du.mutation.UUID(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: decision.FieldUUID,
|
||||
})
|
||||
}
|
||||
if du.mutation.UUIDCleared() {
|
||||
_spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Column: decision.FieldUUID,
|
||||
})
|
||||
}
|
||||
if du.mutation.OwnerCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
|
@ -825,6 +858,26 @@ func (duo *DecisionUpdateOne) SetNillableSimulated(b *bool) *DecisionUpdateOne {
|
|||
return duo
|
||||
}
|
||||
|
||||
// SetUUID sets the "uuid" field.
|
||||
func (duo *DecisionUpdateOne) SetUUID(s string) *DecisionUpdateOne {
|
||||
duo.mutation.SetUUID(s)
|
||||
return duo
|
||||
}
|
||||
|
||||
// SetNillableUUID sets the "uuid" field if the given value is not nil.
|
||||
func (duo *DecisionUpdateOne) SetNillableUUID(s *string) *DecisionUpdateOne {
|
||||
if s != nil {
|
||||
duo.SetUUID(*s)
|
||||
}
|
||||
return duo
|
||||
}
|
||||
|
||||
// ClearUUID clears the value of the "uuid" field.
|
||||
func (duo *DecisionUpdateOne) ClearUUID() *DecisionUpdateOne {
|
||||
duo.mutation.ClearUUID()
|
||||
return duo
|
||||
}
|
||||
|
||||
// SetOwnerID sets the "owner" edge to the Alert entity by ID.
|
||||
func (duo *DecisionUpdateOne) SetOwnerID(id int) *DecisionUpdateOne {
|
||||
duo.mutation.SetOwnerID(id)
|
||||
|
@ -1151,6 +1204,19 @@ func (duo *DecisionUpdateOne) sqlSave(ctx context.Context) (_node *Decision, err
|
|||
Column: decision.FieldSimulated,
|
||||
})
|
||||
}
|
||||
if value, ok := duo.mutation.UUID(); ok {
|
||||
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Value: value,
|
||||
Column: decision.FieldUUID,
|
||||
})
|
||||
}
|
||||
if duo.mutation.UUIDCleared() {
|
||||
_spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{
|
||||
Type: field.TypeString,
|
||||
Column: decision.FieldUUID,
|
||||
})
|
||||
}
|
||||
if duo.mutation.OwnerCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/alert"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/bouncer"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/configitem"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/decision"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/event"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/machine"
|
||||
|
@ -36,12 +37,13 @@ type OrderFunc func(*sql.Selector)
|
|||
// columnChecker returns a function indicates if the column exists in the given column.
|
||||
func columnChecker(table string) func(string) error {
|
||||
checks := map[string]func(string) bool{
|
||||
alert.Table: alert.ValidColumn,
|
||||
bouncer.Table: bouncer.ValidColumn,
|
||||
decision.Table: decision.ValidColumn,
|
||||
event.Table: event.ValidColumn,
|
||||
machine.Table: machine.ValidColumn,
|
||||
meta.Table: meta.ValidColumn,
|
||||
alert.Table: alert.ValidColumn,
|
||||
bouncer.Table: bouncer.ValidColumn,
|
||||
configitem.Table: configitem.ValidColumn,
|
||||
decision.Table: decision.ValidColumn,
|
||||
event.Table: event.ValidColumn,
|
||||
machine.Table: machine.ValidColumn,
|
||||
meta.Table: meta.ValidColumn,
|
||||
}
|
||||
check, ok := checks[table]
|
||||
if !ok {
|
||||
|
|
|
@ -35,6 +35,19 @@ func (f BouncerFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, err
|
|||
return f(ctx, mv)
|
||||
}
|
||||
|
||||
// The ConfigItemFunc type is an adapter to allow the use of ordinary
|
||||
// function as ConfigItem mutator.
|
||||
type ConfigItemFunc func(context.Context, *ent.ConfigItemMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f ConfigItemFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
mv, ok := m.(*ent.ConfigItemMutation)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ConfigItemMutation", m)
|
||||
}
|
||||
return f(ctx, mv)
|
||||
}
|
||||
|
||||
// The DecisionFunc type is an adapter to allow the use of ordinary
|
||||
// function as Decision mutator.
|
||||
type DecisionFunc func(context.Context, *ent.DecisionMutation) (ent.Value, error)
|
||||
|
|
|
@ -33,6 +33,7 @@ var (
|
|||
{Name: "scenario_version", Type: field.TypeString, Nullable: true},
|
||||
{Name: "scenario_hash", Type: field.TypeString, Nullable: true},
|
||||
{Name: "simulated", Type: field.TypeBool, Default: false},
|
||||
{Name: "uuid", Type: field.TypeString, Nullable: true},
|
||||
{Name: "machine_alerts", Type: field.TypeInt, Nullable: true},
|
||||
}
|
||||
// AlertsTable holds the schema information for the "alerts" table.
|
||||
|
@ -43,7 +44,7 @@ var (
|
|||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "alerts_machines_alerts",
|
||||
Columns: []*schema.Column{AlertsColumns[23]},
|
||||
Columns: []*schema.Column{AlertsColumns[24]},
|
||||
RefColumns: []*schema.Column{MachinesColumns[0]},
|
||||
OnDelete: schema.SetNull,
|
||||
},
|
||||
|
@ -77,6 +78,20 @@ var (
|
|||
Columns: BouncersColumns,
|
||||
PrimaryKey: []*schema.Column{BouncersColumns[0]},
|
||||
}
|
||||
// ConfigItemsColumns holds the columns for the "config_items" table.
|
||||
ConfigItemsColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeInt, Increment: true},
|
||||
{Name: "created_at", Type: field.TypeTime, Nullable: true},
|
||||
{Name: "updated_at", Type: field.TypeTime, Nullable: true},
|
||||
{Name: "name", Type: field.TypeString, Unique: true},
|
||||
{Name: "value", Type: field.TypeString},
|
||||
}
|
||||
// ConfigItemsTable holds the schema information for the "config_items" table.
|
||||
ConfigItemsTable = &schema.Table{
|
||||
Name: "config_items",
|
||||
Columns: ConfigItemsColumns,
|
||||
PrimaryKey: []*schema.Column{ConfigItemsColumns[0]},
|
||||
}
|
||||
// DecisionsColumns holds the columns for the "decisions" table.
|
||||
DecisionsColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeInt, Increment: true},
|
||||
|
@ -94,6 +109,7 @@ var (
|
|||
{Name: "value", Type: field.TypeString},
|
||||
{Name: "origin", Type: field.TypeString},
|
||||
{Name: "simulated", Type: field.TypeBool, Default: false},
|
||||
{Name: "uuid", Type: field.TypeString, Nullable: true},
|
||||
{Name: "alert_decisions", Type: field.TypeInt, Nullable: true},
|
||||
}
|
||||
// DecisionsTable holds the schema information for the "decisions" table.
|
||||
|
@ -104,7 +120,7 @@ var (
|
|||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "decisions_alerts_decisions",
|
||||
Columns: []*schema.Column{DecisionsColumns[15]},
|
||||
Columns: []*schema.Column{DecisionsColumns[16]},
|
||||
RefColumns: []*schema.Column{AlertsColumns[0]},
|
||||
OnDelete: schema.Cascade,
|
||||
},
|
||||
|
@ -199,6 +215,7 @@ var (
|
|||
Tables = []*schema.Table{
|
||||
AlertsTable,
|
||||
BouncersTable,
|
||||
ConfigItemsTable,
|
||||
DecisionsTable,
|
||||
EventsTable,
|
||||
MachinesTable,
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/alert"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/bouncer"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/configitem"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/decision"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/event"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/machine"
|
||||
|
@ -29,12 +30,13 @@ const (
|
|||
OpUpdateOne = ent.OpUpdateOne
|
||||
|
||||
// Node types.
|
||||
TypeAlert = "Alert"
|
||||
TypeBouncer = "Bouncer"
|
||||
TypeDecision = "Decision"
|
||||
TypeEvent = "Event"
|
||||
TypeMachine = "Machine"
|
||||
TypeMeta = "Meta"
|
||||
TypeAlert = "Alert"
|
||||
TypeBouncer = "Bouncer"
|
||||
TypeConfigItem = "ConfigItem"
|
||||
TypeDecision = "Decision"
|
||||
TypeEvent = "Event"
|
||||
TypeMachine = "Machine"
|
||||
TypeMeta = "Meta"
|
||||
)
|
||||
|
||||
// AlertMutation represents an operation that mutates the Alert nodes in the graph.
|
||||
|
@ -69,6 +71,7 @@ type AlertMutation struct {
|
|||
scenarioVersion *string
|
||||
scenarioHash *string
|
||||
simulated *bool
|
||||
uuid *string
|
||||
clearedFields map[string]struct{}
|
||||
owner *int
|
||||
clearedowner bool
|
||||
|
@ -1320,6 +1323,55 @@ func (m *AlertMutation) ResetSimulated() {
|
|||
m.simulated = nil
|
||||
}
|
||||
|
||||
// SetUUID sets the "uuid" field.
|
||||
func (m *AlertMutation) SetUUID(s string) {
|
||||
m.uuid = &s
|
||||
}
|
||||
|
||||
// UUID returns the value of the "uuid" field in the mutation.
|
||||
func (m *AlertMutation) UUID() (r string, exists bool) {
|
||||
v := m.uuid
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
return *v, true
|
||||
}
|
||||
|
||||
// OldUUID returns the old "uuid" field's value of the Alert entity.
|
||||
// If the Alert object wasn't provided to the builder, the object is fetched from the database.
|
||||
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
||||
func (m *AlertMutation) OldUUID(ctx context.Context) (v string, err error) {
|
||||
if !m.op.Is(OpUpdateOne) {
|
||||
return v, errors.New("OldUUID is only allowed on UpdateOne operations")
|
||||
}
|
||||
if m.id == nil || m.oldValue == nil {
|
||||
return v, errors.New("OldUUID requires an ID field in the mutation")
|
||||
}
|
||||
oldValue, err := m.oldValue(ctx)
|
||||
if err != nil {
|
||||
return v, fmt.Errorf("querying old value for OldUUID: %w", err)
|
||||
}
|
||||
return oldValue.UUID, nil
|
||||
}
|
||||
|
||||
// ClearUUID clears the value of the "uuid" field.
|
||||
func (m *AlertMutation) ClearUUID() {
|
||||
m.uuid = nil
|
||||
m.clearedFields[alert.FieldUUID] = struct{}{}
|
||||
}
|
||||
|
||||
// UUIDCleared returns if the "uuid" field was cleared in this mutation.
|
||||
func (m *AlertMutation) UUIDCleared() bool {
|
||||
_, ok := m.clearedFields[alert.FieldUUID]
|
||||
return ok
|
||||
}
|
||||
|
||||
// ResetUUID resets all changes to the "uuid" field.
|
||||
func (m *AlertMutation) ResetUUID() {
|
||||
m.uuid = nil
|
||||
delete(m.clearedFields, alert.FieldUUID)
|
||||
}
|
||||
|
||||
// SetOwnerID sets the "owner" edge to the Machine entity by id.
|
||||
func (m *AlertMutation) SetOwnerID(id int) {
|
||||
m.owner = &id
|
||||
|
@ -1540,7 +1592,7 @@ func (m *AlertMutation) Type() string {
|
|||
// order to get all numeric fields that were incremented/decremented, call
|
||||
// AddedFields().
|
||||
func (m *AlertMutation) Fields() []string {
|
||||
fields := make([]string, 0, 22)
|
||||
fields := make([]string, 0, 23)
|
||||
if m.created_at != nil {
|
||||
fields = append(fields, alert.FieldCreatedAt)
|
||||
}
|
||||
|
@ -1607,6 +1659,9 @@ func (m *AlertMutation) Fields() []string {
|
|||
if m.simulated != nil {
|
||||
fields = append(fields, alert.FieldSimulated)
|
||||
}
|
||||
if m.uuid != nil {
|
||||
fields = append(fields, alert.FieldUUID)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
|
@ -1659,6 +1714,8 @@ func (m *AlertMutation) Field(name string) (ent.Value, bool) {
|
|||
return m.ScenarioHash()
|
||||
case alert.FieldSimulated:
|
||||
return m.Simulated()
|
||||
case alert.FieldUUID:
|
||||
return m.UUID()
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
@ -1712,6 +1769,8 @@ func (m *AlertMutation) OldField(ctx context.Context, name string) (ent.Value, e
|
|||
return m.OldScenarioHash(ctx)
|
||||
case alert.FieldSimulated:
|
||||
return m.OldSimulated(ctx)
|
||||
case alert.FieldUUID:
|
||||
return m.OldUUID(ctx)
|
||||
}
|
||||
return nil, fmt.Errorf("unknown Alert field %s", name)
|
||||
}
|
||||
|
@ -1875,6 +1934,13 @@ func (m *AlertMutation) SetField(name string, value ent.Value) error {
|
|||
}
|
||||
m.SetSimulated(v)
|
||||
return nil
|
||||
case alert.FieldUUID:
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||
}
|
||||
m.SetUUID(v)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown Alert field %s", name)
|
||||
}
|
||||
|
@ -2016,6 +2082,9 @@ func (m *AlertMutation) ClearedFields() []string {
|
|||
if m.FieldCleared(alert.FieldScenarioHash) {
|
||||
fields = append(fields, alert.FieldScenarioHash)
|
||||
}
|
||||
if m.FieldCleared(alert.FieldUUID) {
|
||||
fields = append(fields, alert.FieldUUID)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
|
@ -2090,6 +2159,9 @@ func (m *AlertMutation) ClearField(name string) error {
|
|||
case alert.FieldScenarioHash:
|
||||
m.ClearScenarioHash()
|
||||
return nil
|
||||
case alert.FieldUUID:
|
||||
m.ClearUUID()
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown Alert nullable field %s", name)
|
||||
}
|
||||
|
@ -2164,6 +2236,9 @@ func (m *AlertMutation) ResetField(name string) error {
|
|||
case alert.FieldSimulated:
|
||||
m.ResetSimulated()
|
||||
return nil
|
||||
case alert.FieldUUID:
|
||||
m.ResetUUID()
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown Alert field %s", name)
|
||||
}
|
||||
|
@ -3290,6 +3365,520 @@ func (m *BouncerMutation) ResetEdge(name string) error {
|
|||
return fmt.Errorf("unknown Bouncer edge %s", name)
|
||||
}
|
||||
|
||||
// ConfigItemMutation represents an operation that mutates the ConfigItem nodes in the graph.
|
||||
type ConfigItemMutation struct {
|
||||
config
|
||||
op Op
|
||||
typ string
|
||||
id *int
|
||||
created_at *time.Time
|
||||
updated_at *time.Time
|
||||
name *string
|
||||
value *string
|
||||
clearedFields map[string]struct{}
|
||||
done bool
|
||||
oldValue func(context.Context) (*ConfigItem, error)
|
||||
predicates []predicate.ConfigItem
|
||||
}
|
||||
|
||||
var _ ent.Mutation = (*ConfigItemMutation)(nil)
|
||||
|
||||
// configitemOption allows management of the mutation configuration using functional options.
|
||||
type configitemOption func(*ConfigItemMutation)
|
||||
|
||||
// newConfigItemMutation creates new mutation for the ConfigItem entity.
|
||||
func newConfigItemMutation(c config, op Op, opts ...configitemOption) *ConfigItemMutation {
|
||||
m := &ConfigItemMutation{
|
||||
config: c,
|
||||
op: op,
|
||||
typ: TypeConfigItem,
|
||||
clearedFields: make(map[string]struct{}),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(m)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// withConfigItemID sets the ID field of the mutation.
|
||||
func withConfigItemID(id int) configitemOption {
|
||||
return func(m *ConfigItemMutation) {
|
||||
var (
|
||||
err error
|
||||
once sync.Once
|
||||
value *ConfigItem
|
||||
)
|
||||
m.oldValue = func(ctx context.Context) (*ConfigItem, error) {
|
||||
once.Do(func() {
|
||||
if m.done {
|
||||
err = errors.New("querying old values post mutation is not allowed")
|
||||
} else {
|
||||
value, err = m.Client().ConfigItem.Get(ctx, id)
|
||||
}
|
||||
})
|
||||
return value, err
|
||||
}
|
||||
m.id = &id
|
||||
}
|
||||
}
|
||||
|
||||
// withConfigItem sets the old ConfigItem of the mutation.
|
||||
func withConfigItem(node *ConfigItem) configitemOption {
|
||||
return func(m *ConfigItemMutation) {
|
||||
m.oldValue = func(context.Context) (*ConfigItem, error) {
|
||||
return node, nil
|
||||
}
|
||||
m.id = &node.ID
|
||||
}
|
||||
}
|
||||
|
||||
// Client returns a new `ent.Client` from the mutation. If the mutation was
|
||||
// executed in a transaction (ent.Tx), a transactional client is returned.
|
||||
func (m ConfigItemMutation) Client() *Client {
|
||||
client := &Client{config: m.config}
|
||||
client.init()
|
||||
return client
|
||||
}
|
||||
|
||||
// Tx returns an `ent.Tx` for mutations that were executed in transactions;
|
||||
// it returns an error otherwise.
|
||||
func (m ConfigItemMutation) Tx() (*Tx, error) {
|
||||
if _, ok := m.driver.(*txDriver); !ok {
|
||||
return nil, errors.New("ent: mutation is not running in a transaction")
|
||||
}
|
||||
tx := &Tx{config: m.config}
|
||||
tx.init()
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// ID returns the ID value in the mutation. Note that the ID is only available
|
||||
// if it was provided to the builder or after it was returned from the database.
|
||||
func (m *ConfigItemMutation) ID() (id int, exists bool) {
|
||||
if m.id == nil {
|
||||
return
|
||||
}
|
||||
return *m.id, true
|
||||
}
|
||||
|
||||
// IDs queries the database and returns the entity ids that match the mutation's predicate.
|
||||
// That means, if the mutation is applied within a transaction with an isolation level such
|
||||
// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
|
||||
// or updated by the mutation.
|
||||
func (m *ConfigItemMutation) IDs(ctx context.Context) ([]int, error) {
|
||||
switch {
|
||||
case m.op.Is(OpUpdateOne | OpDeleteOne):
|
||||
id, exists := m.ID()
|
||||
if exists {
|
||||
return []int{id}, nil
|
||||
}
|
||||
fallthrough
|
||||
case m.op.Is(OpUpdate | OpDelete):
|
||||
return m.Client().ConfigItem.Query().Where(m.predicates...).IDs(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
|
||||
}
|
||||
}
|
||||
|
||||
// SetCreatedAt sets the "created_at" field.
|
||||
func (m *ConfigItemMutation) SetCreatedAt(t time.Time) {
|
||||
m.created_at = &t
|
||||
}
|
||||
|
||||
// CreatedAt returns the value of the "created_at" field in the mutation.
|
||||
func (m *ConfigItemMutation) CreatedAt() (r time.Time, exists bool) {
|
||||
v := m.created_at
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
return *v, true
|
||||
}
|
||||
|
||||
// OldCreatedAt returns the old "created_at" field's value of the ConfigItem entity.
|
||||
// If the ConfigItem object wasn't provided to the builder, the object is fetched from the database.
|
||||
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
||||
func (m *ConfigItemMutation) OldCreatedAt(ctx context.Context) (v *time.Time, err error) {
|
||||
if !m.op.Is(OpUpdateOne) {
|
||||
return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations")
|
||||
}
|
||||
if m.id == nil || m.oldValue == nil {
|
||||
return v, errors.New("OldCreatedAt requires an ID field in the mutation")
|
||||
}
|
||||
oldValue, err := m.oldValue(ctx)
|
||||
if err != nil {
|
||||
return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err)
|
||||
}
|
||||
return oldValue.CreatedAt, nil
|
||||
}
|
||||
|
||||
// ClearCreatedAt clears the value of the "created_at" field.
|
||||
func (m *ConfigItemMutation) ClearCreatedAt() {
|
||||
m.created_at = nil
|
||||
m.clearedFields[configitem.FieldCreatedAt] = struct{}{}
|
||||
}
|
||||
|
||||
// CreatedAtCleared returns if the "created_at" field was cleared in this mutation.
|
||||
func (m *ConfigItemMutation) CreatedAtCleared() bool {
|
||||
_, ok := m.clearedFields[configitem.FieldCreatedAt]
|
||||
return ok
|
||||
}
|
||||
|
||||
// ResetCreatedAt resets all changes to the "created_at" field.
|
||||
func (m *ConfigItemMutation) ResetCreatedAt() {
|
||||
m.created_at = nil
|
||||
delete(m.clearedFields, configitem.FieldCreatedAt)
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (m *ConfigItemMutation) SetUpdatedAt(t time.Time) {
|
||||
m.updated_at = &t
|
||||
}
|
||||
|
||||
// UpdatedAt returns the value of the "updated_at" field in the mutation.
|
||||
func (m *ConfigItemMutation) UpdatedAt() (r time.Time, exists bool) {
|
||||
v := m.updated_at
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
return *v, true
|
||||
}
|
||||
|
||||
// OldUpdatedAt returns the old "updated_at" field's value of the ConfigItem entity.
|
||||
// If the ConfigItem object wasn't provided to the builder, the object is fetched from the database.
|
||||
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
||||
func (m *ConfigItemMutation) OldUpdatedAt(ctx context.Context) (v *time.Time, err error) {
|
||||
if !m.op.Is(OpUpdateOne) {
|
||||
return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations")
|
||||
}
|
||||
if m.id == nil || m.oldValue == nil {
|
||||
return v, errors.New("OldUpdatedAt requires an ID field in the mutation")
|
||||
}
|
||||
oldValue, err := m.oldValue(ctx)
|
||||
if err != nil {
|
||||
return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err)
|
||||
}
|
||||
return oldValue.UpdatedAt, nil
|
||||
}
|
||||
|
||||
// ClearUpdatedAt clears the value of the "updated_at" field.
|
||||
func (m *ConfigItemMutation) ClearUpdatedAt() {
|
||||
m.updated_at = nil
|
||||
m.clearedFields[configitem.FieldUpdatedAt] = struct{}{}
|
||||
}
|
||||
|
||||
// UpdatedAtCleared returns if the "updated_at" field was cleared in this mutation.
|
||||
func (m *ConfigItemMutation) UpdatedAtCleared() bool {
|
||||
_, ok := m.clearedFields[configitem.FieldUpdatedAt]
|
||||
return ok
|
||||
}
|
||||
|
||||
// ResetUpdatedAt resets all changes to the "updated_at" field.
|
||||
func (m *ConfigItemMutation) ResetUpdatedAt() {
|
||||
m.updated_at = nil
|
||||
delete(m.clearedFields, configitem.FieldUpdatedAt)
|
||||
}
|
||||
|
||||
// SetName sets the "name" field.
|
||||
func (m *ConfigItemMutation) SetName(s string) {
|
||||
m.name = &s
|
||||
}
|
||||
|
||||
// Name returns the value of the "name" field in the mutation.
|
||||
func (m *ConfigItemMutation) Name() (r string, exists bool) {
|
||||
v := m.name
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
return *v, true
|
||||
}
|
||||
|
||||
// OldName returns the old "name" field's value of the ConfigItem entity.
|
||||
// If the ConfigItem object wasn't provided to the builder, the object is fetched from the database.
|
||||
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
||||
func (m *ConfigItemMutation) OldName(ctx context.Context) (v string, err error) {
|
||||
if !m.op.Is(OpUpdateOne) {
|
||||
return v, errors.New("OldName is only allowed on UpdateOne operations")
|
||||
}
|
||||
if m.id == nil || m.oldValue == nil {
|
||||
return v, errors.New("OldName requires an ID field in the mutation")
|
||||
}
|
||||
oldValue, err := m.oldValue(ctx)
|
||||
if err != nil {
|
||||
return v, fmt.Errorf("querying old value for OldName: %w", err)
|
||||
}
|
||||
return oldValue.Name, nil
|
||||
}
|
||||
|
||||
// ResetName resets all changes to the "name" field.
|
||||
func (m *ConfigItemMutation) ResetName() {
|
||||
m.name = nil
|
||||
}
|
||||
|
||||
// SetValue sets the "value" field.
|
||||
func (m *ConfigItemMutation) SetValue(s string) {
|
||||
m.value = &s
|
||||
}
|
||||
|
||||
// Value returns the value of the "value" field in the mutation.
|
||||
func (m *ConfigItemMutation) Value() (r string, exists bool) {
|
||||
v := m.value
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
return *v, true
|
||||
}
|
||||
|
||||
// OldValue returns the old "value" field's value of the ConfigItem entity.
|
||||
// If the ConfigItem object wasn't provided to the builder, the object is fetched from the database.
|
||||
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
||||
func (m *ConfigItemMutation) OldValue(ctx context.Context) (v string, err error) {
|
||||
if !m.op.Is(OpUpdateOne) {
|
||||
return v, errors.New("OldValue is only allowed on UpdateOne operations")
|
||||
}
|
||||
if m.id == nil || m.oldValue == nil {
|
||||
return v, errors.New("OldValue requires an ID field in the mutation")
|
||||
}
|
||||
oldValue, err := m.oldValue(ctx)
|
||||
if err != nil {
|
||||
return v, fmt.Errorf("querying old value for OldValue: %w", err)
|
||||
}
|
||||
return oldValue.Value, nil
|
||||
}
|
||||
|
||||
// ResetValue resets all changes to the "value" field.
|
||||
func (m *ConfigItemMutation) ResetValue() {
|
||||
m.value = nil
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the ConfigItemMutation builder.
|
||||
func (m *ConfigItemMutation) Where(ps ...predicate.ConfigItem) {
|
||||
m.predicates = append(m.predicates, ps...)
|
||||
}
|
||||
|
||||
// Op returns the operation name.
|
||||
func (m *ConfigItemMutation) Op() Op {
|
||||
return m.op
|
||||
}
|
||||
|
||||
// Type returns the node type of this mutation (ConfigItem).
|
||||
func (m *ConfigItemMutation) Type() string {
|
||||
return m.typ
|
||||
}
|
||||
|
||||
// Fields returns all fields that were changed during this mutation. Note that in
|
||||
// order to get all numeric fields that were incremented/decremented, call
|
||||
// AddedFields().
|
||||
func (m *ConfigItemMutation) Fields() []string {
|
||||
fields := make([]string, 0, 4)
|
||||
if m.created_at != nil {
|
||||
fields = append(fields, configitem.FieldCreatedAt)
|
||||
}
|
||||
if m.updated_at != nil {
|
||||
fields = append(fields, configitem.FieldUpdatedAt)
|
||||
}
|
||||
if m.name != nil {
|
||||
fields = append(fields, configitem.FieldName)
|
||||
}
|
||||
if m.value != nil {
|
||||
fields = append(fields, configitem.FieldValue)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
// Field returns the value of a field with the given name. The second boolean
|
||||
// return value indicates that this field was not set, or was not defined in the
|
||||
// schema.
|
||||
func (m *ConfigItemMutation) Field(name string) (ent.Value, bool) {
|
||||
switch name {
|
||||
case configitem.FieldCreatedAt:
|
||||
return m.CreatedAt()
|
||||
case configitem.FieldUpdatedAt:
|
||||
return m.UpdatedAt()
|
||||
case configitem.FieldName:
|
||||
return m.Name()
|
||||
case configitem.FieldValue:
|
||||
return m.Value()
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// OldField returns the old value of the field from the database. An error is
|
||||
// returned if the mutation operation is not UpdateOne, or the query to the
|
||||
// database failed.
|
||||
func (m *ConfigItemMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
|
||||
switch name {
|
||||
case configitem.FieldCreatedAt:
|
||||
return m.OldCreatedAt(ctx)
|
||||
case configitem.FieldUpdatedAt:
|
||||
return m.OldUpdatedAt(ctx)
|
||||
case configitem.FieldName:
|
||||
return m.OldName(ctx)
|
||||
case configitem.FieldValue:
|
||||
return m.OldValue(ctx)
|
||||
}
|
||||
return nil, fmt.Errorf("unknown ConfigItem field %s", name)
|
||||
}
|
||||
|
||||
// SetField sets the value of a field with the given name. It returns an error if
|
||||
// the field is not defined in the schema, or if the type mismatched the field
|
||||
// type.
|
||||
func (m *ConfigItemMutation) SetField(name string, value ent.Value) error {
|
||||
switch name {
|
||||
case configitem.FieldCreatedAt:
|
||||
v, ok := value.(time.Time)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||
}
|
||||
m.SetCreatedAt(v)
|
||||
return nil
|
||||
case configitem.FieldUpdatedAt:
|
||||
v, ok := value.(time.Time)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||
}
|
||||
m.SetUpdatedAt(v)
|
||||
return nil
|
||||
case configitem.FieldName:
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||
}
|
||||
m.SetName(v)
|
||||
return nil
|
||||
case configitem.FieldValue:
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||
}
|
||||
m.SetValue(v)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown ConfigItem field %s", name)
|
||||
}
|
||||
|
||||
// AddedFields returns all numeric fields that were incremented/decremented during
|
||||
// this mutation.
|
||||
func (m *ConfigItemMutation) AddedFields() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddedField returns the numeric value that was incremented/decremented on a field
|
||||
// with the given name. The second boolean return value indicates that this field
|
||||
// was not set, or was not defined in the schema.
|
||||
func (m *ConfigItemMutation) AddedField(name string) (ent.Value, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// AddField adds the value to the field with the given name. It returns an error if
|
||||
// the field is not defined in the schema, or if the type mismatched the field
|
||||
// type.
|
||||
func (m *ConfigItemMutation) AddField(name string, value ent.Value) error {
|
||||
switch name {
|
||||
}
|
||||
return fmt.Errorf("unknown ConfigItem numeric field %s", name)
|
||||
}
|
||||
|
||||
// ClearedFields returns all nullable fields that were cleared during this
|
||||
// mutation.
|
||||
func (m *ConfigItemMutation) ClearedFields() []string {
|
||||
var fields []string
|
||||
if m.FieldCleared(configitem.FieldCreatedAt) {
|
||||
fields = append(fields, configitem.FieldCreatedAt)
|
||||
}
|
||||
if m.FieldCleared(configitem.FieldUpdatedAt) {
|
||||
fields = append(fields, configitem.FieldUpdatedAt)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
// FieldCleared returns a boolean indicating if a field with the given name was
|
||||
// cleared in this mutation.
|
||||
func (m *ConfigItemMutation) FieldCleared(name string) bool {
|
||||
_, ok := m.clearedFields[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
// ClearField clears the value of the field with the given name. It returns an
|
||||
// error if the field is not defined in the schema.
|
||||
func (m *ConfigItemMutation) ClearField(name string) error {
|
||||
switch name {
|
||||
case configitem.FieldCreatedAt:
|
||||
m.ClearCreatedAt()
|
||||
return nil
|
||||
case configitem.FieldUpdatedAt:
|
||||
m.ClearUpdatedAt()
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown ConfigItem nullable field %s", name)
|
||||
}
|
||||
|
||||
// ResetField resets all changes in the mutation for the field with the given name.
|
||||
// It returns an error if the field is not defined in the schema.
|
||||
func (m *ConfigItemMutation) ResetField(name string) error {
|
||||
switch name {
|
||||
case configitem.FieldCreatedAt:
|
||||
m.ResetCreatedAt()
|
||||
return nil
|
||||
case configitem.FieldUpdatedAt:
|
||||
m.ResetUpdatedAt()
|
||||
return nil
|
||||
case configitem.FieldName:
|
||||
m.ResetName()
|
||||
return nil
|
||||
case configitem.FieldValue:
|
||||
m.ResetValue()
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown ConfigItem field %s", name)
|
||||
}
|
||||
|
||||
// AddedEdges returns all edge names that were set/added in this mutation.
|
||||
func (m *ConfigItemMutation) AddedEdges() []string {
|
||||
edges := make([]string, 0, 0)
|
||||
return edges
|
||||
}
|
||||
|
||||
// AddedIDs returns all IDs (to other nodes) that were added for the given edge
|
||||
// name in this mutation.
|
||||
func (m *ConfigItemMutation) AddedIDs(name string) []ent.Value {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemovedEdges returns all edge names that were removed in this mutation.
|
||||
func (m *ConfigItemMutation) RemovedEdges() []string {
|
||||
edges := make([]string, 0, 0)
|
||||
return edges
|
||||
}
|
||||
|
||||
// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
|
||||
// the given name in this mutation.
|
||||
func (m *ConfigItemMutation) RemovedIDs(name string) []ent.Value {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClearedEdges returns all edge names that were cleared in this mutation.
|
||||
func (m *ConfigItemMutation) ClearedEdges() []string {
|
||||
edges := make([]string, 0, 0)
|
||||
return edges
|
||||
}
|
||||
|
||||
// EdgeCleared returns a boolean which indicates if the edge with the given name
|
||||
// was cleared in this mutation.
|
||||
func (m *ConfigItemMutation) EdgeCleared(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ClearEdge clears the value of the edge with the given name. It returns an error
|
||||
// if that edge is not defined in the schema.
|
||||
func (m *ConfigItemMutation) ClearEdge(name string) error {
|
||||
return fmt.Errorf("unknown ConfigItem unique edge %s", name)
|
||||
}
|
||||
|
||||
// ResetEdge resets all changes to the edge with the given name in this mutation.
|
||||
// It returns an error if the edge is not defined in the schema.
|
||||
func (m *ConfigItemMutation) ResetEdge(name string) error {
|
||||
return fmt.Errorf("unknown ConfigItem edge %s", name)
|
||||
}
|
||||
|
||||
// DecisionMutation represents an operation that mutates the Decision nodes in the graph.
|
||||
type DecisionMutation struct {
|
||||
config
|
||||
|
@ -3315,6 +3904,7 @@ type DecisionMutation struct {
|
|||
value *string
|
||||
origin *string
|
||||
simulated *bool
|
||||
uuid *string
|
||||
clearedFields map[string]struct{}
|
||||
owner *int
|
||||
clearedowner bool
|
||||
|
@ -4134,6 +4724,55 @@ func (m *DecisionMutation) ResetSimulated() {
|
|||
m.simulated = nil
|
||||
}
|
||||
|
||||
// SetUUID sets the "uuid" field.
|
||||
func (m *DecisionMutation) SetUUID(s string) {
|
||||
m.uuid = &s
|
||||
}
|
||||
|
||||
// UUID returns the value of the "uuid" field in the mutation.
|
||||
func (m *DecisionMutation) UUID() (r string, exists bool) {
|
||||
v := m.uuid
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
return *v, true
|
||||
}
|
||||
|
||||
// OldUUID returns the old "uuid" field's value of the Decision entity.
|
||||
// If the Decision object wasn't provided to the builder, the object is fetched from the database.
|
||||
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
||||
func (m *DecisionMutation) OldUUID(ctx context.Context) (v string, err error) {
|
||||
if !m.op.Is(OpUpdateOne) {
|
||||
return v, errors.New("OldUUID is only allowed on UpdateOne operations")
|
||||
}
|
||||
if m.id == nil || m.oldValue == nil {
|
||||
return v, errors.New("OldUUID requires an ID field in the mutation")
|
||||
}
|
||||
oldValue, err := m.oldValue(ctx)
|
||||
if err != nil {
|
||||
return v, fmt.Errorf("querying old value for OldUUID: %w", err)
|
||||
}
|
||||
return oldValue.UUID, nil
|
||||
}
|
||||
|
||||
// ClearUUID clears the value of the "uuid" field.
|
||||
func (m *DecisionMutation) ClearUUID() {
|
||||
m.uuid = nil
|
||||
m.clearedFields[decision.FieldUUID] = struct{}{}
|
||||
}
|
||||
|
||||
// UUIDCleared returns if the "uuid" field was cleared in this mutation.
|
||||
func (m *DecisionMutation) UUIDCleared() bool {
|
||||
_, ok := m.clearedFields[decision.FieldUUID]
|
||||
return ok
|
||||
}
|
||||
|
||||
// ResetUUID resets all changes to the "uuid" field.
|
||||
func (m *DecisionMutation) ResetUUID() {
|
||||
m.uuid = nil
|
||||
delete(m.clearedFields, decision.FieldUUID)
|
||||
}
|
||||
|
||||
// SetOwnerID sets the "owner" edge to the Alert entity by id.
|
||||
func (m *DecisionMutation) SetOwnerID(id int) {
|
||||
m.owner = &id
|
||||
|
@ -4192,7 +4831,7 @@ func (m *DecisionMutation) Type() string {
|
|||
// order to get all numeric fields that were incremented/decremented, call
|
||||
// AddedFields().
|
||||
func (m *DecisionMutation) Fields() []string {
|
||||
fields := make([]string, 0, 14)
|
||||
fields := make([]string, 0, 15)
|
||||
if m.created_at != nil {
|
||||
fields = append(fields, decision.FieldCreatedAt)
|
||||
}
|
||||
|
@ -4235,6 +4874,9 @@ func (m *DecisionMutation) Fields() []string {
|
|||
if m.simulated != nil {
|
||||
fields = append(fields, decision.FieldSimulated)
|
||||
}
|
||||
if m.uuid != nil {
|
||||
fields = append(fields, decision.FieldUUID)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
|
@ -4271,6 +4913,8 @@ func (m *DecisionMutation) Field(name string) (ent.Value, bool) {
|
|||
return m.Origin()
|
||||
case decision.FieldSimulated:
|
||||
return m.Simulated()
|
||||
case decision.FieldUUID:
|
||||
return m.UUID()
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
@ -4308,6 +4952,8 @@ func (m *DecisionMutation) OldField(ctx context.Context, name string) (ent.Value
|
|||
return m.OldOrigin(ctx)
|
||||
case decision.FieldSimulated:
|
||||
return m.OldSimulated(ctx)
|
||||
case decision.FieldUUID:
|
||||
return m.OldUUID(ctx)
|
||||
}
|
||||
return nil, fmt.Errorf("unknown Decision field %s", name)
|
||||
}
|
||||
|
@ -4415,6 +5061,13 @@ func (m *DecisionMutation) SetField(name string, value ent.Value) error {
|
|||
}
|
||||
m.SetSimulated(v)
|
||||
return nil
|
||||
case decision.FieldUUID:
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||
}
|
||||
m.SetUUID(v)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown Decision field %s", name)
|
||||
}
|
||||
|
@ -4532,6 +5185,9 @@ func (m *DecisionMutation) ClearedFields() []string {
|
|||
if m.FieldCleared(decision.FieldIPSize) {
|
||||
fields = append(fields, decision.FieldIPSize)
|
||||
}
|
||||
if m.FieldCleared(decision.FieldUUID) {
|
||||
fields = append(fields, decision.FieldUUID)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
|
@ -4570,6 +5226,9 @@ func (m *DecisionMutation) ClearField(name string) error {
|
|||
case decision.FieldIPSize:
|
||||
m.ClearIPSize()
|
||||
return nil
|
||||
case decision.FieldUUID:
|
||||
m.ClearUUID()
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown Decision nullable field %s", name)
|
||||
}
|
||||
|
@ -4620,6 +5279,9 @@ func (m *DecisionMutation) ResetField(name string) error {
|
|||
case decision.FieldSimulated:
|
||||
m.ResetSimulated()
|
||||
return nil
|
||||
case decision.FieldUUID:
|
||||
m.ResetUUID()
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown Decision field %s", name)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,9 @@ type Alert func(*sql.Selector)
|
|||
// Bouncer is the predicate function for bouncer builders.
|
||||
type Bouncer func(*sql.Selector)
|
||||
|
||||
// ConfigItem is the predicate function for configitem builders.
|
||||
type ConfigItem func(*sql.Selector)
|
||||
|
||||
// Decision is the predicate function for decision builders.
|
||||
type Decision func(*sql.Selector)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/alert"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/bouncer"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/configitem"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/decision"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/event"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/machine"
|
||||
|
@ -86,6 +87,20 @@ func init() {
|
|||
bouncerDescAuthType := bouncerFields[10].Descriptor()
|
||||
// bouncer.DefaultAuthType holds the default value on creation for the auth_type field.
|
||||
bouncer.DefaultAuthType = bouncerDescAuthType.Default.(string)
|
||||
configitemFields := schema.ConfigItem{}.Fields()
|
||||
_ = configitemFields
|
||||
// configitemDescCreatedAt is the schema descriptor for created_at field.
|
||||
configitemDescCreatedAt := configitemFields[0].Descriptor()
|
||||
// configitem.DefaultCreatedAt holds the default value on creation for the created_at field.
|
||||
configitem.DefaultCreatedAt = configitemDescCreatedAt.Default.(func() time.Time)
|
||||
// configitem.UpdateDefaultCreatedAt holds the default value on update for the created_at field.
|
||||
configitem.UpdateDefaultCreatedAt = configitemDescCreatedAt.UpdateDefault.(func() time.Time)
|
||||
// configitemDescUpdatedAt is the schema descriptor for updated_at field.
|
||||
configitemDescUpdatedAt := configitemFields[1].Descriptor()
|
||||
// configitem.DefaultUpdatedAt holds the default value on creation for the updated_at field.
|
||||
configitem.DefaultUpdatedAt = configitemDescUpdatedAt.Default.(func() time.Time)
|
||||
// configitem.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
|
||||
configitem.UpdateDefaultUpdatedAt = configitemDescUpdatedAt.UpdateDefault.(func() time.Time)
|
||||
decisionFields := schema.Decision{}.Fields()
|
||||
_ = decisionFields
|
||||
// decisionDescCreatedAt is the schema descriptor for created_at field.
|
||||
|
|
|
@ -50,6 +50,7 @@ func (Alert) Fields() []ent.Field {
|
|||
field.String("scenarioVersion").Optional(),
|
||||
field.String("scenarioHash").Optional(),
|
||||
field.Bool("simulated").Default(false),
|
||||
field.String("uuid").Optional(), //this uuid is mostly here to ensure that CAPI/PAPI has a unique id for each alert
|
||||
}
|
||||
}
|
||||
|
||||
|
|
31
pkg/database/ent/schema/config.go
Normal file
31
pkg/database/ent/schema/config.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package schema
|
||||
|
||||
import (
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/schema/field"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
)
|
||||
|
||||
// ConfigItem holds the schema definition for the ConfigItem entity.
|
||||
type ConfigItem struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
// Fields of the Bouncer.
|
||||
func (ConfigItem) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.Time("created_at").
|
||||
Default(types.UtcNow).
|
||||
UpdateDefault(types.UtcNow).Nillable().Optional().StructTag(`json:"created_at"`),
|
||||
field.Time("updated_at").
|
||||
Default(types.UtcNow).
|
||||
UpdateDefault(types.UtcNow).Nillable().Optional().StructTag(`json:"updated_at"`),
|
||||
field.String("name").Unique().StructTag(`json:"name"`),
|
||||
field.String("value").StructTag(`json:"value"`), // a json object
|
||||
}
|
||||
}
|
||||
|
||||
// Edges of the Bouncer.
|
||||
func (ConfigItem) Edges() []ent.Edge {
|
||||
return nil
|
||||
}
|
|
@ -37,6 +37,7 @@ func (Decision) Fields() []ent.Field {
|
|||
field.String("value"),
|
||||
field.String("origin"),
|
||||
field.Bool("simulated").Default(false),
|
||||
field.String("uuid").Optional(), //this uuid is mostly here to ensure that CAPI/PAPI has a unique id for each decision
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ type Tx struct {
|
|||
Alert *AlertClient
|
||||
// Bouncer is the client for interacting with the Bouncer builders.
|
||||
Bouncer *BouncerClient
|
||||
// ConfigItem is the client for interacting with the ConfigItem builders.
|
||||
ConfigItem *ConfigItemClient
|
||||
// Decision is the client for interacting with the Decision builders.
|
||||
Decision *DecisionClient
|
||||
// Event is the client for interacting with the Event builders.
|
||||
|
@ -161,6 +163,7 @@ func (tx *Tx) Client() *Client {
|
|||
func (tx *Tx) init() {
|
||||
tx.Alert = NewAlertClient(tx.config)
|
||||
tx.Bouncer = NewBouncerClient(tx.config)
|
||||
tx.ConfigItem = NewConfigItemClient(tx.config)
|
||||
tx.Decision = NewDecisionClient(tx.config)
|
||||
tx.Event = NewEventClient(tx.config)
|
||||
tx.Machine = NewMachineClient(tx.config)
|
||||
|
|
|
@ -8,12 +8,13 @@ import (
|
|||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/machine"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
const CapiMachineID = "CAPI"
|
||||
const CapiListsMachineID = "lists"
|
||||
const CapiMachineID = types.CAPIOrigin
|
||||
const CapiListsMachineID = types.ListOrigin
|
||||
|
||||
func (c *Client) CreateMachine(machineID *string, password *strfmt.Password, ipAddress string, isValidated bool, force bool, authType string) (*ent.Machine, error) {
|
||||
hashPassword, err := bcrypt.GenerateFromPassword([]byte(*password), bcrypt.DefaultCost)
|
||||
|
|
|
@ -4,6 +4,7 @@ var Crowdsec = FeatureRegister{EnvPrefix: "CROWDSEC_FEATURE_"}
|
|||
|
||||
var CscliSetup = &Feature{Name: "cscli_setup", Description: "Enable cscli setup command (service detection)"}
|
||||
var DisableHttpRetryBackoff = &Feature{Name: "disable_http_retry_backoff", Description: "Disable http retry backoff"}
|
||||
var PapiClient = &Feature{Name: "papi_client", Description: "Enable Polling API client"}
|
||||
|
||||
func RegisterAllFeatures() error {
|
||||
err := Crowdsec.RegisterFeature(CscliSetup)
|
||||
|
@ -14,6 +15,9 @@ func RegisterAllFeatures() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = Crowdsec.RegisterFeature(PapiClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
191
pkg/longpollclient/client.go
Normal file
191
pkg/longpollclient/client.go
Normal file
|
@ -0,0 +1,191 @@
|
|||
package longpollclient
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gopkg.in/tomb.v2"
|
||||
)
|
||||
|
||||
type LongPollClient struct {
|
||||
t tomb.Tomb
|
||||
c chan Event
|
||||
url url.URL
|
||||
logger *log.Entry
|
||||
since int64
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
type LongPollClientConfig struct {
|
||||
Url url.URL
|
||||
Logger *log.Logger
|
||||
HttpClient *http.Client
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Category string `json:"category"`
|
||||
Data string `json:"data"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
RequestId string
|
||||
}
|
||||
|
||||
type pollResponse struct {
|
||||
Events []Event `json:"events"`
|
||||
// Set for timeout responses
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
// API error responses could have an informative error here. Empty on success.
|
||||
ErrorMessage string `json:"error"`
|
||||
}
|
||||
|
||||
var errUnauthorized = fmt.Errorf("user is not authorized to use PAPI")
|
||||
|
||||
const timeoutMessage = "no events before timeout"
|
||||
|
||||
func (c *LongPollClient) doQuery() error {
|
||||
|
||||
logger := c.logger.WithField("method", "doQuery")
|
||||
|
||||
query := c.url.Query()
|
||||
query.Set("since_time", fmt.Sprintf("%d", c.since))
|
||||
query.Set("timeout", "45")
|
||||
c.url.RawQuery = query.Encode()
|
||||
|
||||
logger.Debugf("Query parameters: %s", c.url.RawQuery)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, c.url.String(), nil)
|
||||
if err != nil {
|
||||
logger.Errorf("failed to create request: %s", err)
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Accept", "application/json")
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
logger.Errorf("failed to execute request: %s", err)
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
requestId := resp.Header.Get("X-Amzn-Trace-Id")
|
||||
logger = logger.WithField("request-id", requestId)
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
c.logger.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
if resp.StatusCode == http.StatusPaymentRequired {
|
||||
bodyContent, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logger.Errorf("failed to read response body: %s", err)
|
||||
return err
|
||||
}
|
||||
logger.Errorf(string(bodyContent))
|
||||
return errUnauthorized
|
||||
}
|
||||
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-c.t.Dying():
|
||||
logger.Debugf("dying")
|
||||
close(c.c)
|
||||
return nil
|
||||
default:
|
||||
var pollResp pollResponse
|
||||
err = decoder.Decode(&pollResp)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
logger.Debugf("server closed connection")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("error decoding poll response: %v", err)
|
||||
}
|
||||
|
||||
logger.Tracef("got response: %+v", pollResp)
|
||||
|
||||
if len(pollResp.ErrorMessage) > 0 {
|
||||
if pollResp.ErrorMessage == timeoutMessage {
|
||||
logger.Debugf("got timeout message")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("longpoll API error message: %s", pollResp.ErrorMessage)
|
||||
}
|
||||
|
||||
if len(pollResp.Events) > 0 {
|
||||
logger.Debugf("got %d events", len(pollResp.Events))
|
||||
for _, event := range pollResp.Events {
|
||||
event.RequestId = requestId
|
||||
c.c <- event
|
||||
if event.Timestamp > c.since {
|
||||
c.since = event.Timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
if pollResp.Timestamp > 0 {
|
||||
c.since = pollResp.Timestamp
|
||||
}
|
||||
logger.Debugf("Since is now %d", c.since)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *LongPollClient) pollEvents() error {
|
||||
for {
|
||||
select {
|
||||
case <-c.t.Dying():
|
||||
c.logger.Debug("dying")
|
||||
return nil
|
||||
default:
|
||||
c.logger.Debug("Polling PAPI")
|
||||
err := c.doQuery()
|
||||
if err != nil {
|
||||
c.logger.Errorf("failed to poll: %s", err)
|
||||
if err == errUnauthorized {
|
||||
c.t.Kill(err)
|
||||
close(c.c)
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *LongPollClient) Start(since time.Time) chan Event {
|
||||
c.logger.Infof("starting polling client")
|
||||
c.c = make(chan Event)
|
||||
c.since = since.Unix() * 1000
|
||||
c.t.Go(c.pollEvents)
|
||||
return c.c
|
||||
}
|
||||
|
||||
func (c *LongPollClient) Stop() error {
|
||||
c.t.Kill(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewLongPollClient(config LongPollClientConfig) (*LongPollClient, error) {
|
||||
var logger *log.Entry
|
||||
if config.Url == (url.URL{}) {
|
||||
return nil, fmt.Errorf("url is required")
|
||||
}
|
||||
if config.Logger == nil {
|
||||
logger = log.WithField("component", "longpollclient")
|
||||
} else {
|
||||
logger = config.Logger.WithFields(log.Fields{
|
||||
"component": "longpollclient",
|
||||
"url": config.Url.String(),
|
||||
})
|
||||
}
|
||||
|
||||
return &LongPollClient{
|
||||
url: config.Url,
|
||||
logger: logger,
|
||||
httpClient: config.HttpClient,
|
||||
}, nil
|
||||
}
|
|
@ -23,12 +23,16 @@ type AddSignalsRequestItem struct {
|
|||
// alert id
|
||||
AlertID int64 `json:"alert_id,omitempty"`
|
||||
|
||||
|
||||
// context
|
||||
Context []*AddSignalsRequestItemContextItems0 `json:"context"`
|
||||
|
||||
// created at
|
||||
// created at
|
||||
CreatedAt string `json:"created_at,omitempty"`
|
||||
|
||||
// decisions
|
||||
Decisions AddSignalsRequestItemDecisions `json:"decisions,omitempty"`
|
||||
|
||||
// machine id
|
||||
MachineID string `json:"machine_id,omitempty"`
|
||||
|
||||
|
@ -53,7 +57,7 @@ type AddSignalsRequestItem struct {
|
|||
|
||||
// source
|
||||
// Required: true
|
||||
Source *Source `json:"source"`
|
||||
Source *AddSignalsRequestItemSource `json:"source"`
|
||||
|
||||
// start at
|
||||
// Required: true
|
||||
|
@ -62,6 +66,10 @@ type AddSignalsRequestItem struct {
|
|||
// stop at
|
||||
// Required: true
|
||||
StopAt *string `json:"stop_at"`
|
||||
|
||||
// uuid
|
||||
// Read Only: true
|
||||
UUID string `json:"uuid,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this add signals request item
|
||||
|
@ -106,6 +114,7 @@ func (m *AddSignalsRequestItem) Validate(formats strfmt.Registry) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
|
||||
func (m *AddSignalsRequestItem) validateContext(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.Context) { // not required
|
||||
return nil
|
||||
|
@ -210,6 +219,7 @@ func (m *AddSignalsRequestItem) validateStopAt(formats strfmt.Registry) error {
|
|||
func (m *AddSignalsRequestItem) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
|
||||
if err := m.contextValidateContext(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
@ -218,12 +228,17 @@ func (m *AddSignalsRequestItem) ContextValidate(ctx context.Context, formats str
|
|||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.contextValidateUUID(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func (m *AddSignalsRequestItem) contextValidateContext(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
for i := 0; i < len(m.Context); i++ {
|
||||
|
@ -260,6 +275,15 @@ func (m *AddSignalsRequestItem) contextValidateSource(ctx context.Context, forma
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *AddSignalsRequestItem) contextValidateUUID(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.ReadOnly(ctx, "uuid", "body", string(m.UUID)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *AddSignalsRequestItem) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
|
|
73
pkg/models/add_signals_request_item_decisions.go
Normal file
73
pkg/models/add_signals_request_item_decisions.go
Normal file
|
@ -0,0 +1,73 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// AddSignalsRequestItemDecisions Decisions list
|
||||
//
|
||||
// swagger:model AddSignalsRequestItemDecisions
|
||||
type AddSignalsRequestItemDecisions []*AddSignalsRequestItemDecisionsItem
|
||||
|
||||
// Validate validates this add signals request item decisions
|
||||
func (m AddSignalsRequestItemDecisions) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
for i := 0; i < len(m); i++ {
|
||||
if swag.IsZero(m[i]) { // not required
|
||||
continue
|
||||
}
|
||||
|
||||
if m[i] != nil {
|
||||
if err := m[i].Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName(strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName(strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this add signals request item decisions based on the context it is used
|
||||
func (m AddSignalsRequestItemDecisions) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
for i := 0; i < len(m); i++ {
|
||||
|
||||
if m[i] != nil {
|
||||
if err := m[i].ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName(strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName(strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
201
pkg/models/add_signals_request_item_decisions_item.go
Normal file
201
pkg/models/add_signals_request_item_decisions_item.go
Normal file
|
@ -0,0 +1,201 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// AddSignalsRequestItemDecisionsItem Decision
|
||||
//
|
||||
// swagger:model AddSignalsRequestItemDecisionsItem
|
||||
type AddSignalsRequestItemDecisionsItem struct {
|
||||
|
||||
// duration
|
||||
// Required: true
|
||||
Duration *string `json:"duration"`
|
||||
|
||||
// (only relevant for GET ops) the unique id
|
||||
// Required: true
|
||||
ID *int64 `json:"id"`
|
||||
|
||||
// the origin of the decision : cscli, crowdsec
|
||||
// Required: true
|
||||
Origin *string `json:"origin"`
|
||||
|
||||
// scenario
|
||||
// Required: true
|
||||
Scenario *string `json:"scenario"`
|
||||
|
||||
// the scope of decision : does it apply to an IP, a range, a username, etc
|
||||
// Required: true
|
||||
Scope *string `json:"scope"`
|
||||
|
||||
// simulated
|
||||
Simulated bool `json:"simulated,omitempty"`
|
||||
|
||||
// the type of decision, might be 'ban', 'captcha' or something custom. Ignored when watcher (cscli/crowdsec) is pushing to APIL.
|
||||
// Required: true
|
||||
Type *string `json:"type"`
|
||||
|
||||
// until
|
||||
Until string `json:"until,omitempty"`
|
||||
|
||||
// only relevant for LAPI->CAPI, ignored for cscli->LAPI and crowdsec->LAPI
|
||||
// Read Only: true
|
||||
UUID string `json:"uuid,omitempty"`
|
||||
|
||||
// the value of the decision scope : an IP, a range, a username, etc
|
||||
// Required: true
|
||||
Value *string `json:"value"`
|
||||
}
|
||||
|
||||
// Validate validates this add signals request item decisions item
|
||||
func (m *AddSignalsRequestItemDecisionsItem) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateDuration(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateID(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateOrigin(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateScenario(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateScope(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateType(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateValue(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddSignalsRequestItemDecisionsItem) validateDuration(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("duration", "body", m.Duration); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddSignalsRequestItemDecisionsItem) validateID(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("id", "body", m.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddSignalsRequestItemDecisionsItem) validateOrigin(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("origin", "body", m.Origin); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddSignalsRequestItemDecisionsItem) validateScenario(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("scenario", "body", m.Scenario); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddSignalsRequestItemDecisionsItem) validateScope(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("scope", "body", m.Scope); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddSignalsRequestItemDecisionsItem) validateType(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("type", "body", m.Type); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddSignalsRequestItemDecisionsItem) validateValue(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("value", "body", m.Value); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this add signals request item decisions item based on the context it is used
|
||||
func (m *AddSignalsRequestItemDecisionsItem) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.contextValidateUUID(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddSignalsRequestItemDecisionsItem) contextValidateUUID(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.ReadOnly(ctx, "uuid", "body", string(m.UUID)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *AddSignalsRequestItemDecisionsItem) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *AddSignalsRequestItemDecisionsItem) UnmarshalBinary(b []byte) error {
|
||||
var res AddSignalsRequestItemDecisionsItem
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
109
pkg/models/add_signals_request_item_source.go
Normal file
109
pkg/models/add_signals_request_item_source.go
Normal file
|
@ -0,0 +1,109 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// AddSignalsRequestItemSource Source
|
||||
//
|
||||
// swagger:model AddSignalsRequestItemSource
|
||||
type AddSignalsRequestItemSource struct {
|
||||
|
||||
// provided as a convenience when the source is an IP
|
||||
AsName string `json:"as_name,omitempty"`
|
||||
|
||||
// provided as a convenience when the source is an IP
|
||||
AsNumber string `json:"as_number,omitempty"`
|
||||
|
||||
// cn
|
||||
Cn string `json:"cn,omitempty"`
|
||||
|
||||
// provided as a convenience when the source is an IP
|
||||
IP string `json:"ip,omitempty"`
|
||||
|
||||
// latitude
|
||||
Latitude float32 `json:"latitude,omitempty"`
|
||||
|
||||
// longitude
|
||||
Longitude float32 `json:"longitude,omitempty"`
|
||||
|
||||
// provided as a convenience when the source is an IP
|
||||
Range string `json:"range,omitempty"`
|
||||
|
||||
// the scope of a source : ip,range,username,etc
|
||||
// Required: true
|
||||
Scope *string `json:"scope"`
|
||||
|
||||
// the value of a source : the ip, the range, the username,etc
|
||||
// Required: true
|
||||
Value *string `json:"value"`
|
||||
}
|
||||
|
||||
// Validate validates this add signals request item source
|
||||
func (m *AddSignalsRequestItemSource) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateScope(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateValue(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddSignalsRequestItemSource) validateScope(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("scope", "body", m.Scope); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AddSignalsRequestItemSource) validateValue(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("value", "body", m.Value); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validates this add signals request item source based on context it is used
|
||||
func (m *AddSignalsRequestItemSource) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *AddSignalsRequestItemSource) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *AddSignalsRequestItemSource) UnmarshalBinary(b []byte) error {
|
||||
var res AddSignalsRequestItemSource
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
|
@ -50,7 +50,7 @@ type Alert struct {
|
|||
// Required: true
|
||||
Leakspeed *string `json:"leakspeed"`
|
||||
|
||||
// only relevant for APIL->APIC, ignored for cscli->APIL and crowdsec->APIL
|
||||
// only relevant for LAPI->CAPI, ignored for cscli->LAPI and crowdsec->LAPI
|
||||
// Read Only: true
|
||||
MachineID string `json:"machine_id,omitempty"`
|
||||
|
||||
|
@ -91,6 +91,10 @@ type Alert struct {
|
|||
// stop at
|
||||
// Required: true
|
||||
StopAt *string `json:"stop_at"`
|
||||
|
||||
// only relevant for LAPI->CAPI, ignored for cscli->LAPI and crowdsec->LAPI
|
||||
// Read Only: true
|
||||
UUID string `json:"uuid,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this alert
|
||||
|
@ -371,6 +375,10 @@ func (m *Alert) ContextValidate(ctx context.Context, formats strfmt.Registry) er
|
|||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.contextValidateUUID(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
|
@ -474,6 +482,15 @@ func (m *Alert) contextValidateSource(ctx context.Context, formats strfmt.Regist
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *Alert) contextValidateUUID(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.ReadOnly(ctx, "uuid", "body", string(m.UUID)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *Alert) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
|
|
|
@ -50,6 +50,10 @@ type Decision struct {
|
|||
// the date until the decisions must be active
|
||||
Until string `json:"until,omitempty"`
|
||||
|
||||
// only relevant for LAPI->CAPI, ignored for cscli->LAPI and crowdsec->LAPI
|
||||
// Read Only: true
|
||||
UUID string `json:"uuid,omitempty"`
|
||||
|
||||
// the value of the decision scope : an IP, a range, a username, etc
|
||||
// Required: true
|
||||
Value *string `json:"value"`
|
||||
|
@ -155,6 +159,10 @@ func (m *Decision) ContextValidate(ctx context.Context, formats strfmt.Registry)
|
|||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.contextValidateUUID(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
|
@ -179,6 +187,15 @@ func (m *Decision) contextValidateSimulated(ctx context.Context, formats strfmt.
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *Decision) contextValidateUUID(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.ReadOnly(ctx, "uuid", "body", string(m.UUID)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *Decision) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
|
|
67
pkg/models/decisions_delete_request.go
Normal file
67
pkg/models/decisions_delete_request.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// DecisionsDeleteRequest delete decisions
|
||||
//
|
||||
// delete decision model
|
||||
//
|
||||
// swagger:model DecisionsDeleteRequest
|
||||
type DecisionsDeleteRequest []DecisionsDeleteRequestItem
|
||||
|
||||
// Validate validates this decisions delete request
|
||||
func (m DecisionsDeleteRequest) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
for i := 0; i < len(m); i++ {
|
||||
|
||||
if err := m[i].Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName(strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName(strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this decisions delete request based on the context it is used
|
||||
func (m DecisionsDeleteRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
for i := 0; i < len(m); i++ {
|
||||
|
||||
if err := m[i].ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName(strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName(strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
27
pkg/models/decisions_delete_request_item.go
Normal file
27
pkg/models/decisions_delete_request_item.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// DecisionsDeleteRequestItem decisionsIDs
|
||||
//
|
||||
// swagger:model DecisionsDeleteRequestItem
|
||||
type DecisionsDeleteRequestItem string
|
||||
|
||||
// Validate validates this decisions delete request item
|
||||
func (m DecisionsDeleteRequestItem) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validates this decisions delete request item based on context it is used
|
||||
func (m DecisionsDeleteRequestItem) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
|
@ -733,8 +733,12 @@ definitions:
|
|||
description: 'only relevant for GET, ignored in POST requests'
|
||||
type: integer
|
||||
readOnly: true
|
||||
uuid:
|
||||
description: 'only relevant for LAPI->CAPI, ignored for cscli->LAPI and crowdsec->LAPI'
|
||||
type: string
|
||||
readOnly: true
|
||||
machine_id:
|
||||
description: 'only relevant for APIL->APIC, ignored for cscli->APIL and crowdsec->APIL'
|
||||
description: 'only relevant for LAPI->CAPI, ignored for cscli->LAPI and crowdsec->LAPI'
|
||||
type: string
|
||||
readOnly: true
|
||||
created_at:
|
||||
|
@ -890,6 +894,10 @@ definitions:
|
|||
description: (only relevant for GET ops) the unique id
|
||||
type: integer
|
||||
readOnly: true
|
||||
uuid:
|
||||
description: 'only relevant for LAPI->CAPI, ignored for cscli->LAPI and crowdsec->LAPI'
|
||||
type: string
|
||||
readOnly: true
|
||||
origin:
|
||||
description: 'the origin of the decision : cscli, crowdsec'
|
||||
type: string
|
||||
|
@ -999,46 +1007,6 @@ definitions:
|
|||
description: "more detail on individual errors"
|
||||
title: "error response"
|
||||
description: "error response return by the API"
|
||||
AddSignalsRequest:
|
||||
title: "add signals request"
|
||||
type: "array"
|
||||
description: "All signals request model"
|
||||
items:
|
||||
$ref: "#/definitions/AddSignalsRequestItem"
|
||||
AddSignalsRequestItem:
|
||||
type: "object"
|
||||
required:
|
||||
- "message"
|
||||
- "scenario"
|
||||
- "scenario_hash"
|
||||
- "scenario_version"
|
||||
- "source"
|
||||
- "start_at"
|
||||
- "stop_at"
|
||||
- "scenario_trust"
|
||||
properties:
|
||||
scenario_hash:
|
||||
type: "string"
|
||||
scenario:
|
||||
type: "string"
|
||||
created_at:
|
||||
type: "string"
|
||||
machine_id:
|
||||
type: "string"
|
||||
source:
|
||||
$ref: "#/definitions/Source"
|
||||
scenario_version:
|
||||
type: "string"
|
||||
scenario_trust:
|
||||
type: "string"
|
||||
message:
|
||||
type: "string"
|
||||
description: "a human readable message"
|
||||
start_at:
|
||||
type: "string"
|
||||
stop_at:
|
||||
type: "string"
|
||||
title: "Signal"
|
||||
tags:
|
||||
- name: bouncers
|
||||
description: 'Operations about decisions : bans, captcha, rate-limit etc.'
|
||||
|
|
|
@ -3,3 +3,24 @@ package types
|
|||
const ApiKeyAuthType = "api-key"
|
||||
const TlsAuthType = "tls"
|
||||
const PasswordAuthType = "password"
|
||||
|
||||
const PAPIBaseURL = "https://papi.crowdsec.net/v1/decisions/stream/poll"
|
||||
const CAPIBaseURL = "https://api.crowdsec.net/"
|
||||
|
||||
const CscliOrigin = "cscli"
|
||||
const CrowdSecOrigin = "crowdsec"
|
||||
const ConsoleOrigin = "console"
|
||||
const CscliImportOrigin = "cscli-import"
|
||||
const ListOrigin = "lists"
|
||||
const CAPIOrigin = "CAPI"
|
||||
|
||||
func GetOrigins() []string {
|
||||
return []string{
|
||||
CscliOrigin,
|
||||
CrowdSecOrigin,
|
||||
ConsoleOrigin,
|
||||
CscliImportOrigin,
|
||||
ListOrigin,
|
||||
CAPIOrigin,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue