mirror of
https://github.com/SecurityBrewery/catalyst.git
synced 2025-12-06 15:22:47 +01:00
@@ -23,7 +23,7 @@ func (db *Database) ArtifactGet(ctx context.Context, id int64, name string) (*mo
|
||||
FOR a in NOT_NULL(d.artifacts, [])
|
||||
FILTER a.name == @name
|
||||
RETURN a`
|
||||
cursor, _, err := db.Query(ctx, query, mergeMaps(ticketFilterVars, map[string]interface{}{
|
||||
cursor, _, err := db.Query(ctx, query, mergeMaps(ticketFilterVars, map[string]any{
|
||||
"@collection": TicketCollectionName,
|
||||
"ID": fmt.Sprint(id),
|
||||
"name": name,
|
||||
@@ -55,7 +55,8 @@ func (db *Database) ArtifactUpdate(ctx context.Context, id int64, name string, a
|
||||
LET newartifacts = APPEND(REMOVE_VALUE(d.artifacts, a), @artifact)
|
||||
UPDATE d WITH { "artifacts": newartifacts } IN @@collection
|
||||
RETURN NEW`
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{
|
||||
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{
|
||||
"@collection": TicketCollectionName,
|
||||
"ID": id,
|
||||
"name": name,
|
||||
@@ -69,7 +70,7 @@ func (db *Database) ArtifactUpdate(ctx context.Context, id int64, name string, a
|
||||
}
|
||||
|
||||
func (db *Database) EnrichArtifact(ctx context.Context, id int64, name string, enrichmentForm *model.EnrichmentForm) (*model.TicketWithTickets, error) {
|
||||
enrichment := model.Enrichment{time.Now().UTC(), enrichmentForm.Data, enrichmentForm.Name}
|
||||
enrichment := model.Enrichment{Created: time.Now().UTC(), Data: enrichmentForm.Data, Name: enrichmentForm.Name}
|
||||
|
||||
ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx)
|
||||
if err != nil {
|
||||
@@ -85,7 +86,8 @@ func (db *Database) EnrichArtifact(ctx context.Context, id int64, name string, e
|
||||
LET newartifacts = APPEND(REMOVE_VALUE(d.artifacts, a), MERGE(a, { "enrichments": newenrichments }))
|
||||
UPDATE d WITH { "artifacts": newartifacts } IN @@collection
|
||||
RETURN NEW`
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{
|
||||
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{
|
||||
"@collection": TicketCollectionName,
|
||||
"ID": id,
|
||||
"name": name,
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/SecurityBrewery/catalyst/generated/model"
|
||||
)
|
||||
|
||||
func toAutomation(doc *model.AutomationForm) interface{} {
|
||||
func toAutomation(doc *model.AutomationForm) *model.Automation {
|
||||
return &model.Automation{
|
||||
Image: doc.Image,
|
||||
Script: doc.Script,
|
||||
@@ -72,12 +72,13 @@ func (db *Database) AutomationUpdate(ctx context.Context, id string, automation
|
||||
|
||||
func (db *Database) AutomationDelete(ctx context.Context, id string) error {
|
||||
_, err := db.automationCollection.RemoveDocument(ctx, id)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *Database) AutomationList(ctx context.Context) ([]*model.AutomationResponse, error) {
|
||||
query := "FOR d IN @@collection SORT d._key ASC RETURN UNSET(d, 'script')"
|
||||
cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": AutomationCollectionName}, busdb.ReadOperation)
|
||||
cursor, _, err := db.Query(ctx, query, map[string]any{"@collection": AutomationCollectionName}, busdb.ReadOperation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -40,10 +40,12 @@ type Operation struct {
|
||||
Ids []driver.DocumentID
|
||||
}
|
||||
|
||||
var CreateOperation = &Operation{Type: bus.DatabaseEntryCreated}
|
||||
var ReadOperation = &Operation{Type: bus.DatabaseEntryRead}
|
||||
var (
|
||||
CreateOperation = &Operation{Type: bus.DatabaseEntryCreated}
|
||||
ReadOperation = &Operation{Type: bus.DatabaseEntryRead}
|
||||
)
|
||||
|
||||
func (db BusDatabase) Query(ctx context.Context, query string, vars map[string]interface{}, operation *Operation) (cur driver.Cursor, logs *model.LogEntry, err error) {
|
||||
func (db *BusDatabase) Query(ctx context.Context, query string, vars map[string]any, operation *Operation) (cur driver.Cursor, logs *model.LogEntry, err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
cur, err = db.internal.Query(ctx, query, vars)
|
||||
@@ -61,31 +63,31 @@ func (db BusDatabase) Query(ctx context.Context, query string, vars map[string]i
|
||||
return cur, logs, err
|
||||
}
|
||||
|
||||
func (db BusDatabase) Remove(ctx context.Context) (err error) {
|
||||
func (db *BusDatabase) Remove(ctx context.Context) (err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
return db.internal.Remove(ctx)
|
||||
}
|
||||
|
||||
func (db BusDatabase) Collection(ctx context.Context, name string) (col driver.Collection, err error) {
|
||||
func (db *BusDatabase) Collection(ctx context.Context, name string) (col driver.Collection, err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
return db.internal.Collection(ctx, name)
|
||||
}
|
||||
|
||||
type Collection struct {
|
||||
type Collection[T any] struct {
|
||||
internal driver.Collection
|
||||
db *BusDatabase
|
||||
}
|
||||
|
||||
func NewCollection(internal driver.Collection, db *BusDatabase) *Collection {
|
||||
return &Collection{internal: internal, db: db}
|
||||
func NewCollection[T any](internal driver.Collection, db *BusDatabase) *Collection[T] {
|
||||
return &Collection[T]{internal: internal, db: db}
|
||||
}
|
||||
|
||||
func (c Collection) CreateDocument(ctx, newctx context.Context, key string, document interface{}) (meta driver.DocumentMeta, err error) {
|
||||
func (c *Collection[T]) CreateDocument(ctx, newctx context.Context, key string, document *T) (meta driver.DocumentMeta, err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
meta, err = c.internal.CreateDocument(newctx, &Keyed{Key: key, Doc: document})
|
||||
meta, err = c.internal.CreateDocument(newctx, &Keyed[T]{Key: key, Doc: document})
|
||||
if err != nil {
|
||||
return meta, err
|
||||
}
|
||||
@@ -94,10 +96,11 @@ func (c Collection) CreateDocument(ctx, newctx context.Context, key string, docu
|
||||
if err != nil {
|
||||
return meta, err
|
||||
}
|
||||
|
||||
return meta, nil
|
||||
}
|
||||
|
||||
func (c Collection) CreateEdge(ctx, newctx context.Context, edge *driver.EdgeDocument) (meta driver.DocumentMeta, err error) {
|
||||
func (c *Collection[T]) CreateEdge(ctx, newctx context.Context, edge *driver.EdgeDocument) (meta driver.DocumentMeta, err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
meta, err = c.internal.CreateDocument(newctx, edge)
|
||||
@@ -109,10 +112,11 @@ func (c Collection) CreateEdge(ctx, newctx context.Context, edge *driver.EdgeDoc
|
||||
if err != nil {
|
||||
return meta, err
|
||||
}
|
||||
|
||||
return meta, nil
|
||||
}
|
||||
|
||||
func (c Collection) CreateEdges(ctx context.Context, edges []*driver.EdgeDocument) (meta driver.DocumentMetaSlice, err error) {
|
||||
func (c *Collection[T]) CreateEdges(ctx context.Context, edges []*driver.EdgeDocument) (meta driver.DocumentMetaSlice, err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
metas, errs, err := c.internal.CreateDocuments(ctx, edges)
|
||||
@@ -136,13 +140,13 @@ func (c Collection) CreateEdges(ctx context.Context, edges []*driver.EdgeDocumen
|
||||
return metas, nil
|
||||
}
|
||||
|
||||
func (c Collection) DocumentExists(ctx context.Context, id string) (exists bool, err error) {
|
||||
func (c *Collection[T]) DocumentExists(ctx context.Context, id string) (exists bool, err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
return c.internal.DocumentExists(ctx, id)
|
||||
}
|
||||
|
||||
func (c Collection) ReadDocument(ctx context.Context, key string, result interface{}) (meta driver.DocumentMeta, err error) {
|
||||
func (c *Collection[T]) ReadDocument(ctx context.Context, key string, result *T) (meta driver.DocumentMeta, err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
meta, err = c.internal.ReadDocument(ctx, key, result)
|
||||
@@ -150,7 +154,7 @@ func (c Collection) ReadDocument(ctx context.Context, key string, result interfa
|
||||
return
|
||||
}
|
||||
|
||||
func (c Collection) UpdateDocument(ctx context.Context, key string, update interface{}) (meta driver.DocumentMeta, err error) {
|
||||
func (c *Collection[T]) UpdateDocument(ctx context.Context, key string, update any) (meta driver.DocumentMeta, err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
meta, err = c.internal.UpdateDocument(ctx, key, update)
|
||||
@@ -161,7 +165,7 @@ func (c Collection) UpdateDocument(ctx context.Context, key string, update inter
|
||||
return meta, c.db.bus.PublishDatabaseUpdate([]driver.DocumentID{meta.ID}, bus.DatabaseEntryUpdated)
|
||||
}
|
||||
|
||||
func (c Collection) ReplaceDocument(ctx context.Context, key string, document interface{}) (meta driver.DocumentMeta, err error) {
|
||||
func (c *Collection[T]) ReplaceDocument(ctx context.Context, key string, document *T) (meta driver.DocumentMeta, err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
meta, err = c.internal.ReplaceDocument(ctx, key, document)
|
||||
@@ -172,13 +176,13 @@ func (c Collection) ReplaceDocument(ctx context.Context, key string, document in
|
||||
return meta, c.db.bus.PublishDatabaseUpdate([]driver.DocumentID{meta.ID}, bus.DatabaseEntryUpdated)
|
||||
}
|
||||
|
||||
func (c Collection) RemoveDocument(ctx context.Context, formatInt string) (meta driver.DocumentMeta, err error) {
|
||||
func (c *Collection[T]) RemoveDocument(ctx context.Context, formatInt string) (meta driver.DocumentMeta, err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
return c.internal.RemoveDocument(ctx, formatInt)
|
||||
}
|
||||
|
||||
func (c Collection) Truncate(ctx context.Context) (err error) {
|
||||
func (c *Collection[T]) Truncate(ctx context.Context) (err error) {
|
||||
defer func() { err = toHTTPErr(err) }()
|
||||
|
||||
return c.internal.Truncate(ctx)
|
||||
@@ -190,7 +194,9 @@ func toHTTPErr(err error) error {
|
||||
if errors.As(err, &ae) {
|
||||
return &api.HTTPError{Status: ae.Code, Internal: err}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -8,9 +8,11 @@ import (
|
||||
"github.com/SecurityBrewery/catalyst/role"
|
||||
)
|
||||
|
||||
type contextKey string
|
||||
|
||||
const (
|
||||
userContextKey = "user"
|
||||
groupContextKey = "groups"
|
||||
userContextKey contextKey = "user"
|
||||
groupContextKey contextKey = "groups"
|
||||
)
|
||||
|
||||
func SetContext(r *http.Request, user *model.UserResponse) *http.Request {
|
||||
@@ -25,10 +27,12 @@ func SetGroupContext(r *http.Request, groups []string) *http.Request {
|
||||
|
||||
func UserContext(ctx context.Context, user *model.UserResponse) context.Context {
|
||||
user.Roles = role.Strings(role.Explodes(user.Roles))
|
||||
|
||||
return context.WithValue(ctx, userContextKey, user)
|
||||
}
|
||||
|
||||
func UserFromContext(ctx context.Context) (*model.UserResponse, bool) {
|
||||
u, ok := ctx.Value(userContextKey).(*model.UserResponse)
|
||||
|
||||
return u, ok
|
||||
}
|
||||
|
||||
@@ -2,18 +2,18 @@ package busdb
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type Keyed struct {
|
||||
type Keyed[T any] struct {
|
||||
Key string
|
||||
Doc interface{}
|
||||
Doc *T
|
||||
}
|
||||
|
||||
func (p Keyed) MarshalJSON() ([]byte, error) {
|
||||
func (p *Keyed[T]) MarshalJSON() ([]byte, error) {
|
||||
b, err := json.Marshal(p.Doc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var m map[string]interface{}
|
||||
var m map[string]any
|
||||
err = json.Unmarshal(b, &m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
@@ -3,6 +3,7 @@ package busdb
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/arangodb/go-driver"
|
||||
@@ -45,7 +46,12 @@ func (db *BusDatabase) LogBatchCreate(ctx context.Context, logentries []*model.L
|
||||
}
|
||||
}
|
||||
if ids != nil {
|
||||
go db.bus.PublishDatabaseUpdate(ids, bus.DatabaseEntryCreated)
|
||||
go func() {
|
||||
err := db.bus.PublishDatabaseUpdate(ids, bus.DatabaseEntryCreated)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
_, errs, err := db.logCollection.CreateDocuments(ctx, logentries)
|
||||
@@ -62,7 +68,7 @@ func (db *BusDatabase) LogBatchCreate(ctx context.Context, logentries []*model.L
|
||||
|
||||
func (db *BusDatabase) LogList(ctx context.Context, reference string) ([]*model.LogEntry, error) {
|
||||
query := "FOR d IN @@collection FILTER d.reference == @reference SORT d.created DESC RETURN d"
|
||||
cursor, err := db.internal.Query(ctx, query, map[string]interface{}{
|
||||
cursor, err := db.internal.Query(ctx, query, map[string]any{
|
||||
"@collection": LogCollectionName,
|
||||
"reference": reference,
|
||||
})
|
||||
|
||||
@@ -72,12 +72,13 @@ func (db *Database) DashboardUpdate(ctx context.Context, id string, dashboard *m
|
||||
|
||||
func (db *Database) DashboardDelete(ctx context.Context, id string) error {
|
||||
_, err := db.dashboardCollection.RemoveDocument(ctx, id)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *Database) DashboardList(ctx context.Context) ([]*model.DashboardResponse, error) {
|
||||
query := "FOR d IN @@collection RETURN d"
|
||||
cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": DashboardCollectionName}, busdb.ReadOperation)
|
||||
cursor, _, err := db.Query(ctx, query, map[string]any{"@collection": DashboardCollectionName}, busdb.ReadOperation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -103,15 +104,16 @@ func (db *Database) parseWidgets(dashboard *model.Dashboard) error {
|
||||
|
||||
_, err := parser.Parse(widget.Aggregation)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid aggregation query (%s): syntax error\n", widget.Aggregation)
|
||||
return fmt.Errorf("invalid aggregation query (%s): syntax error", widget.Aggregation)
|
||||
}
|
||||
|
||||
if widget.Filter != nil {
|
||||
_, err := parser.Parse(*widget.Filter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid filter query (%s): syntax error\n", *widget.Filter)
|
||||
return fmt.Errorf("invalid filter query (%s): syntax error", *widget.Filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/SecurityBrewery/catalyst/bus"
|
||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||
"github.com/SecurityBrewery/catalyst/database/migrations"
|
||||
"github.com/SecurityBrewery/catalyst/generated/model"
|
||||
"github.com/SecurityBrewery/catalyst/hooks"
|
||||
"github.com/SecurityBrewery/catalyst/index"
|
||||
)
|
||||
@@ -38,18 +39,18 @@ type Database struct {
|
||||
bus *bus.Bus
|
||||
Hooks *hooks.Hooks
|
||||
|
||||
templateCollection *busdb.Collection
|
||||
ticketCollection *busdb.Collection
|
||||
playbookCollection *busdb.Collection
|
||||
automationCollection *busdb.Collection
|
||||
userdataCollection *busdb.Collection
|
||||
userCollection *busdb.Collection
|
||||
tickettypeCollection *busdb.Collection
|
||||
jobCollection *busdb.Collection
|
||||
settingsCollection *busdb.Collection
|
||||
dashboardCollection *busdb.Collection
|
||||
templateCollection *busdb.Collection[model.TicketTemplate]
|
||||
ticketCollection *busdb.Collection[model.Ticket]
|
||||
playbookCollection *busdb.Collection[model.PlaybookTemplate]
|
||||
automationCollection *busdb.Collection[model.Automation]
|
||||
userdataCollection *busdb.Collection[model.UserData]
|
||||
userCollection *busdb.Collection[model.User]
|
||||
tickettypeCollection *busdb.Collection[model.TicketType]
|
||||
jobCollection *busdb.Collection[model.Job]
|
||||
settingsCollection *busdb.Collection[model.Settings]
|
||||
dashboardCollection *busdb.Collection[model.Dashboard]
|
||||
|
||||
relatedCollection *busdb.Collection
|
||||
relatedCollection *busdb.Collection[driver.EdgeDocument]
|
||||
// containsCollection *busdb.Collection
|
||||
}
|
||||
|
||||
@@ -145,17 +146,17 @@ func New(ctx context.Context, index *index.Index, bus *bus.Bus, hooks *hooks.Hoo
|
||||
bus: bus,
|
||||
Index: index,
|
||||
Hooks: hooks,
|
||||
templateCollection: busdb.NewCollection(templateCollection, hookedDB),
|
||||
ticketCollection: busdb.NewCollection(ticketCollection, hookedDB),
|
||||
playbookCollection: busdb.NewCollection(playbookCollection, hookedDB),
|
||||
automationCollection: busdb.NewCollection(automationCollection, hookedDB),
|
||||
relatedCollection: busdb.NewCollection(relatedCollection, hookedDB),
|
||||
userdataCollection: busdb.NewCollection(userdataCollection, hookedDB),
|
||||
userCollection: busdb.NewCollection(userCollection, hookedDB),
|
||||
tickettypeCollection: busdb.NewCollection(tickettypeCollection, hookedDB),
|
||||
jobCollection: busdb.NewCollection(jobCollection, hookedDB),
|
||||
settingsCollection: busdb.NewCollection(settingsCollection, hookedDB),
|
||||
dashboardCollection: busdb.NewCollection(dashboardCollection, hookedDB),
|
||||
templateCollection: busdb.NewCollection[model.TicketTemplate](templateCollection, hookedDB),
|
||||
ticketCollection: busdb.NewCollection[model.Ticket](ticketCollection, hookedDB),
|
||||
playbookCollection: busdb.NewCollection[model.PlaybookTemplate](playbookCollection, hookedDB),
|
||||
automationCollection: busdb.NewCollection[model.Automation](automationCollection, hookedDB),
|
||||
userdataCollection: busdb.NewCollection[model.UserData](userdataCollection, hookedDB),
|
||||
userCollection: busdb.NewCollection[model.User](userCollection, hookedDB),
|
||||
tickettypeCollection: busdb.NewCollection[model.TicketType](tickettypeCollection, hookedDB),
|
||||
jobCollection: busdb.NewCollection[model.Job](jobCollection, hookedDB),
|
||||
settingsCollection: busdb.NewCollection[model.Settings](settingsCollection, hookedDB),
|
||||
dashboardCollection: busdb.NewCollection[model.Dashboard](dashboardCollection, hookedDB),
|
||||
relatedCollection: busdb.NewCollection[driver.EdgeDocument](relatedCollection, hookedDB),
|
||||
}
|
||||
|
||||
return db, nil
|
||||
@@ -194,16 +195,16 @@ func SetupDB(ctx context.Context, client driver.Client, dbName string) (driver.D
|
||||
}
|
||||
|
||||
func (db *Database) Truncate(ctx context.Context) {
|
||||
db.templateCollection.Truncate(ctx)
|
||||
db.ticketCollection.Truncate(ctx)
|
||||
db.playbookCollection.Truncate(ctx)
|
||||
db.automationCollection.Truncate(ctx)
|
||||
db.userdataCollection.Truncate(ctx)
|
||||
db.userCollection.Truncate(ctx)
|
||||
db.tickettypeCollection.Truncate(ctx)
|
||||
db.jobCollection.Truncate(ctx)
|
||||
db.relatedCollection.Truncate(ctx)
|
||||
db.settingsCollection.Truncate(ctx)
|
||||
db.dashboardCollection.Truncate(ctx)
|
||||
_ = db.templateCollection.Truncate(ctx)
|
||||
_ = db.ticketCollection.Truncate(ctx)
|
||||
_ = db.playbookCollection.Truncate(ctx)
|
||||
_ = db.automationCollection.Truncate(ctx)
|
||||
_ = db.userdataCollection.Truncate(ctx)
|
||||
_ = db.userCollection.Truncate(ctx)
|
||||
_ = db.tickettypeCollection.Truncate(ctx)
|
||||
_ = db.jobCollection.Truncate(ctx)
|
||||
_ = db.relatedCollection.Truncate(ctx)
|
||||
_ = db.settingsCollection.Truncate(ctx)
|
||||
_ = db.dashboardCollection.Truncate(ctx)
|
||||
// db.containsCollection.Truncate(ctx)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func (db *Database) toJobResponse(ctx context.Context, key string, doc *model.Jo
|
||||
inspect, err := cli.ContainerInspect(ctx, key)
|
||||
if err != nil || inspect.State == nil {
|
||||
if update {
|
||||
db.JobUpdate(ctx, key, &model.JobUpdate{
|
||||
_, _ = db.JobUpdate(ctx, key, &model.JobUpdate{
|
||||
Status: doc.Status,
|
||||
Running: false,
|
||||
})
|
||||
@@ -46,7 +46,7 @@ func (db *Database) toJobResponse(ctx context.Context, key string, doc *model.Jo
|
||||
} else if doc.Status != inspect.State.Status {
|
||||
status = inspect.State.Status
|
||||
if update {
|
||||
db.JobUpdate(ctx, key, &model.JobUpdate{
|
||||
_, _ = db.JobUpdate(ctx, key, &model.JobUpdate{
|
||||
Status: status,
|
||||
Running: doc.Running,
|
||||
})
|
||||
@@ -107,7 +107,7 @@ func (db *Database) JobUpdate(ctx context.Context, id string, job *model.JobUpda
|
||||
func (db *Database) JobLogAppend(ctx context.Context, id string, logLine string) error {
|
||||
query := `LET d = DOCUMENT(@@collection, @ID)
|
||||
UPDATE d WITH { "log": CONCAT(NOT_NULL(d.log, ""), @logline) } IN @@collection`
|
||||
cur, _, err := db.Query(ctx, query, map[string]interface{}{
|
||||
cur, _, err := db.Query(ctx, query, map[string]any{
|
||||
"@collection": JobCollectionName,
|
||||
"ID": id,
|
||||
"logline": logLine,
|
||||
@@ -125,10 +125,10 @@ func (db *Database) JobLogAppend(ctx context.Context, id string, logLine string)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *Database) JobComplete(ctx context.Context, id string, out interface{}) error {
|
||||
func (db *Database) JobComplete(ctx context.Context, id string, out any) error {
|
||||
query := `LET d = DOCUMENT(@@collection, @ID)
|
||||
UPDATE d WITH { "output": @out, "status": "completed", "running": false } IN @@collection`
|
||||
cur, _, err := db.Query(ctx, query, map[string]interface{}{
|
||||
cur, _, err := db.Query(ctx, query, map[string]any{
|
||||
"@collection": JobCollectionName,
|
||||
"ID": id,
|
||||
"out": out,
|
||||
@@ -148,12 +148,13 @@ func (db *Database) JobComplete(ctx context.Context, id string, out interface{})
|
||||
|
||||
func (db *Database) JobDelete(ctx context.Context, id string) error {
|
||||
_, err := db.jobCollection.RemoveDocument(ctx, id)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *Database) JobList(ctx context.Context) ([]*model.JobResponse, error) {
|
||||
query := "FOR d IN @@collection RETURN d"
|
||||
cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": JobCollectionName}, busdb.ReadOperation)
|
||||
cursor, _, err := db.Query(ctx, query, map[string]any{"@collection": JobCollectionName}, busdb.ReadOperation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -188,24 +189,24 @@ func publishJobMapping(id, automation string, contextStructs *model.Context, ori
|
||||
return publishJob(id, automation, contextStructs, origin, msg, db)
|
||||
}
|
||||
|
||||
func publishJob(id, automation string, contextStructs *model.Context, origin *model.Origin, payload map[string]interface{}, db *Database) error {
|
||||
func publishJob(id, automation string, contextStructs *model.Context, origin *model.Origin, payload map[string]any, db *Database) error {
|
||||
return db.bus.PublishJob(id, automation, payload, contextStructs, origin)
|
||||
}
|
||||
|
||||
func generatePayload(msgMapping map[string]string, contextStructs *model.Context) (map[string]interface{}, error) {
|
||||
contextJson, err := json.Marshal(contextStructs)
|
||||
func generatePayload(msgMapping map[string]string, contextStructs *model.Context) (map[string]any, error) {
|
||||
contextJSON, err := json.Marshal(contextStructs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
automationContext := map[string]interface{}{}
|
||||
err = json.Unmarshal(contextJson, &automationContext)
|
||||
automationContext := map[string]any{}
|
||||
err = json.Unmarshal(contextJSON, &automationContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parser := caql.Parser{}
|
||||
msg := map[string]interface{}{}
|
||||
msg := map[string]any{}
|
||||
for arg, expr := range msgMapping {
|
||||
tree, err := parser.Parse(expr)
|
||||
if err != nil {
|
||||
@@ -218,5 +219,6 @@ func generatePayload(msgMapping map[string]string, contextStructs *model.Context
|
||||
}
|
||||
msg[arg] = v
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
@@ -32,34 +32,34 @@ func generateMigrations() ([]Migration, error) {
|
||||
|
||||
&createGraph{ID: "create-ticket-graph", Name: "Graph", EdgeDefinitions: []driver.EdgeDefinition{{Collection: "related", From: []string{"tickets"}, To: []string{"tickets"}}}},
|
||||
|
||||
&createDocument{ID: "create-template-default", Collection: "templates", Document: &busdb.Keyed{Key: "default", Doc: model.TicketTemplate{Schema: DefaultTemplateSchema, Name: "Default"}}},
|
||||
&createDocument{ID: "create-automation-vt.hash", Collection: "automations", Document: &busdb.Keyed{Key: "vt.hash", Doc: model.Automation{Image: "docker.io/python:3", Script: VTHashAutomation}}},
|
||||
&createDocument{ID: "create-automation-comment", Collection: "automations", Document: &busdb.Keyed{Key: "comment", Doc: model.Automation{Image: "docker.io/python:3", Script: CommentAutomation}}},
|
||||
&createDocument{ID: "create-automation-hash.sha1", Collection: "automations", Document: &busdb.Keyed{Key: "hash.sha1", Doc: model.Automation{Image: "docker.io/python:3", Script: SHA1HashAutomation}}},
|
||||
&createDocument{ID: "create-playbook-malware", Collection: "playbooks", Document: &busdb.Keyed{Key: "malware", Doc: model.PlaybookTemplate{Name: "Malware", Yaml: MalwarePlaybook}}},
|
||||
&createDocument{ID: "create-playbook-phishing", Collection: "playbooks", Document: &busdb.Keyed{Key: "phishing", Doc: model.PlaybookTemplate{Name: "Phishing", Yaml: PhishingPlaybook}}},
|
||||
&createDocument{ID: "create-tickettype-alert", Collection: "tickettypes", Document: &busdb.Keyed{Key: "alert", Doc: model.TicketType{Name: "Alerts", Icon: "mdi-alert", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
&createDocument{ID: "create-tickettype-incident", Collection: "tickettypes", Document: &busdb.Keyed{Key: "incident", Doc: model.TicketType{Name: "Incidents", Icon: "mdi-radioactive", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
&createDocument{ID: "create-tickettype-investigation", Collection: "tickettypes", Document: &busdb.Keyed{Key: "investigation", Doc: model.TicketType{Name: "Forensic Investigations", Icon: "mdi-fingerprint", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
&createDocument{ID: "create-tickettype-hunt", Collection: "tickettypes", Document: &busdb.Keyed{Key: "hunt", Doc: model.TicketType{Name: "Threat Hunting", Icon: "mdi-target", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
&createDocument[busdb.Keyed[model.TicketTemplate]]{ID: "create-template-default", Collection: "templates", Document: &busdb.Keyed[model.TicketTemplate]{Key: "default", Doc: &model.TicketTemplate{Schema: DefaultTemplateSchema, Name: "Default"}}},
|
||||
&createDocument[busdb.Keyed[model.Automation]]{ID: "create-automation-vt.hash", Collection: "automations", Document: &busdb.Keyed[model.Automation]{Key: "vt.hash", Doc: &model.Automation{Image: "docker.io/python:3", Script: VTHashAutomation}}},
|
||||
&createDocument[busdb.Keyed[model.Automation]]{ID: "create-automation-comment", Collection: "automations", Document: &busdb.Keyed[model.Automation]{Key: "comment", Doc: &model.Automation{Image: "docker.io/python:3", Script: CommentAutomation}}},
|
||||
&createDocument[busdb.Keyed[model.Automation]]{ID: "create-automation-hash.sha1", Collection: "automations", Document: &busdb.Keyed[model.Automation]{Key: "hash.sha1", Doc: &model.Automation{Image: "docker.io/python:3", Script: SHA1HashAutomation}}},
|
||||
&createDocument[busdb.Keyed[model.PlaybookTemplate]]{ID: "create-playbook-malware", Collection: "playbooks", Document: &busdb.Keyed[model.PlaybookTemplate]{Key: "malware", Doc: &model.PlaybookTemplate{Name: "Malware", Yaml: MalwarePlaybook}}},
|
||||
&createDocument[busdb.Keyed[model.PlaybookTemplate]]{ID: "create-playbook-phishing", Collection: "playbooks", Document: &busdb.Keyed[model.PlaybookTemplate]{Key: "phishing", Doc: &model.PlaybookTemplate{Name: "Phishing", Yaml: PhishingPlaybook}}},
|
||||
&createDocument[busdb.Keyed[model.TicketType]]{ID: "create-tickettype-alert", Collection: "tickettypes", Document: &busdb.Keyed[model.TicketType]{Key: "alert", Doc: &model.TicketType{Name: "Alerts", Icon: "mdi-alert", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
&createDocument[busdb.Keyed[model.TicketType]]{ID: "create-tickettype-incident", Collection: "tickettypes", Document: &busdb.Keyed[model.TicketType]{Key: "incident", Doc: &model.TicketType{Name: "Incidents", Icon: "mdi-radioactive", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
&createDocument[busdb.Keyed[model.TicketType]]{ID: "create-tickettype-investigation", Collection: "tickettypes", Document: &busdb.Keyed[model.TicketType]{Key: "investigation", Doc: &model.TicketType{Name: "Forensic Investigations", Icon: "mdi-fingerprint", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
&createDocument[busdb.Keyed[model.TicketType]]{ID: "create-tickettype-hunt", Collection: "tickettypes", Document: &busdb.Keyed[model.TicketType]{Key: "hunt", Doc: &model.TicketType{Name: "Threat Hunting", Icon: "mdi-target", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}},
|
||||
|
||||
&updateSchema{ID: "update-automation-collection-1", Name: "automations", DataType: "automation", Schema: `{"properties":{"image":{"type":"string"},"script":{"type":"string"}},"required":["image","script"],"type":"object"}`},
|
||||
&updateDocument{ID: "update-automation-vt.hash-1", Collection: "automations", Key: "vt.hash", Document: model.Automation{Image: "docker.io/python:3", Script: VTHashAutomation, Schema: pointer.String(`{"title":"Input","type":"object","properties":{"default":{"type":"string","title":"Value"}},"required":["default"]}`), Type: []string{"global", "artifact", "playbook"}}},
|
||||
&updateDocument{ID: "update-automation-comment-1", Collection: "automations", Key: "comment", Document: model.Automation{Image: "docker.io/python:3", Script: CommentAutomation, Type: []string{"playbook"}}},
|
||||
&updateDocument{ID: "update-automation-hash.sha1-1", Collection: "automations", Key: "hash.sha1", Document: model.Automation{Image: "docker.io/python:3", Script: SHA1HashAutomation, Schema: pointer.String(`{"title":"Input","type":"object","properties":{"default":{"type":"string","title":"Value"}},"required":["default"]}`), Type: []string{"global", "artifact", "playbook"}}},
|
||||
&updateDocument[model.Automation]{ID: "update-automation-vt.hash-1", Collection: "automations", Key: "vt.hash", Document: &model.Automation{Image: "docker.io/python:3", Script: VTHashAutomation, Schema: pointer.String(`{"title":"Input","type":"object","properties":{"default":{"type":"string","title":"Value"}},"required":["default"]}`), Type: []string{"global", "artifact", "playbook"}}},
|
||||
&updateDocument[model.Automation]{ID: "update-automation-comment-1", Collection: "automations", Key: "comment", Document: &model.Automation{Image: "docker.io/python:3", Script: CommentAutomation, Type: []string{"playbook"}}},
|
||||
&updateDocument[model.Automation]{ID: "update-automation-hash.sha1-1", Collection: "automations", Key: "hash.sha1", Document: &model.Automation{Image: "docker.io/python:3", Script: SHA1HashAutomation, Schema: pointer.String(`{"title":"Input","type":"object","properties":{"default":{"type":"string","title":"Value"}},"required":["default"]}`), Type: []string{"global", "artifact", "playbook"}}},
|
||||
|
||||
&createCollection{ID: "create-job-collection", Name: "jobs", DataType: "job", Schema: `{"properties":{"automation":{"type":"string"},"log":{"type":"string"},"payload":{},"origin":{"properties":{"artifact_origin":{"properties":{"artifact":{"type":"string"},"ticket_id":{"format":"int64","type":"integer"}},"required":["artifact","ticket_id"],"type":"object"},"task_origin":{"properties":{"playbook_id":{"type":"string"},"task_id":{"type":"string"},"ticket_id":{"format":"int64","type":"integer"}},"required":["playbook_id","task_id","ticket_id"],"type":"object"}},"type":"object"},"output":{"properties":{},"type":"object"},"running":{"type":"boolean"},"status":{"type":"string"}},"required":["automation","running","status"],"type":"object"}`},
|
||||
|
||||
&createDocument{ID: "create-playbook-simple", Collection: "playbooks", Document: &busdb.Keyed{Key: "simple", Doc: model.PlaybookTemplate{Name: "Simple", Yaml: SimplePlaybook}}},
|
||||
&createDocument[busdb.Keyed[model.PlaybookTemplate]]{ID: "create-playbook-simple", Collection: "playbooks", Document: &busdb.Keyed[model.PlaybookTemplate]{Key: "simple", Doc: &model.PlaybookTemplate{Name: "Simple", Yaml: SimplePlaybook}}},
|
||||
|
||||
&createCollection{ID: "create-settings-collection", Name: "settings", DataType: "settings", Schema: `{"type":"object","properties":{"artifactStates":{"title":"Artifact States","items":{"type":"object","properties":{"color":{"title":"Color","type":"string","enum":["error","info","success","warning"]},"icon":{"title":"Icon (https://materialdesignicons.com)","type":"string"},"id":{"title":"ID","type":"string"},"name":{"title":"Name","type":"string"}},"required":["id","name","icon"]},"type":"array"},"artifactKinds":{"title":"Artifact Kinds","items":{"type":"object","properties":{"color":{"title":"Color","type":"string","enum":["error","info","success","warning"]},"icon":{"title":"Icon (https://materialdesignicons.com)","type":"string"},"id":{"title":"ID","type":"string"},"name":{"title":"Name","type":"string"}},"required":["id","name","icon"]},"type":"array"},"timeformat":{"title":"Time Format","type":"string"}},"required":["timeformat","artifactKinds","artifactStates"]}`},
|
||||
&createDocument{ID: "create-settings-global", Collection: "settings", Document: &busdb.Keyed{Key: "global", Doc: model.Settings{ArtifactStates: []*model.Type{{Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(model.TypeColorInfo)}, {Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(model.TypeColorError)}, {Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(model.TypeColorSuccess)}}, ArtifactKinds: []*model.Type{{Icon: "mdi-server", ID: "asset", Name: "Asset"}, {Icon: "mdi-bullseye", ID: "ioc", Name: "IOC"}}, Timeformat: "YYYY-MM-DDThh:mm:ss"}}},
|
||||
&createDocument[busdb.Keyed[model.Settings]]{ID: "create-settings-global", Collection: "settings", Document: &busdb.Keyed[model.Settings]{Key: "global", Doc: &model.Settings{ArtifactStates: []*model.Type{{Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(model.TypeColorInfo)}, {Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(model.TypeColorError)}, {Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(model.TypeColorSuccess)}}, ArtifactKinds: []*model.Type{{Icon: "mdi-server", ID: "asset", Name: "Asset"}, {Icon: "mdi-bullseye", ID: "ioc", Name: "IOC"}}, Timeformat: "YYYY-MM-DDThh:mm:ss"}}},
|
||||
|
||||
&updateSchema{ID: "update-ticket-collection", Name: "tickets", DataType: "ticket", Schema: `{"properties":{"artifacts":{"items":{"properties":{"enrichments":{"additionalProperties":{"properties":{"created":{"format":"date-time","type":"string"},"data":{"example":{"hash":"b7a067a742c20d07a7456646de89bc2d408a1153"},"properties":{},"type":"object"},"name":{"example":"hash.sha1","type":"string"}},"required":["created","data","name"],"type":"object"},"type":"object"},"name":{"example":"2.2.2.2","type":"string"},"status":{"example":"Unknown","type":"string"},"type":{"type":"string"},"kind":{"type":"string"}},"required":["name"],"type":"object"},"type":"array"},"comments":{"items":{"properties":{"created":{"format":"date-time","type":"string"},"creator":{"type":"string"},"message":{"type":"string"}},"required":["created","creator","message"],"type":"object"},"type":"array"},"created":{"format":"date-time","type":"string"},"details":{"example":{"description":"my little incident"},"properties":{},"type":"object"},"files":{"items":{"properties":{"key":{"example":"myfile","type":"string"},"name":{"example":"notes.docx","type":"string"}},"required":["key","name"],"type":"object"},"type":"array"},"modified":{"format":"date-time","type":"string"},"name":{"example":"WannyCry","type":"string"},"owner":{"example":"bob","type":"string"},"playbooks":{"additionalProperties":{"properties":{"name":{"example":"Phishing","type":"string"},"tasks":{"additionalProperties":{"properties":{"automation":{"type":"string"},"closed":{"format":"date-time","type":"string"},"created":{"format":"date-time","type":"string"},"data":{"properties":{},"type":"object"},"done":{"type":"boolean"},"join":{"example":false,"type":"boolean"},"payload":{"additionalProperties":{"type":"string"},"type":"object"},"name":{"example":"Inform user","type":"string"},"next":{"additionalProperties":{"type":"string"},"type":"object"},"owner":{"type":"string"},"schema":{"properties":{},"type":"object"},"type":{"enum":["task","input","automation"],"example":"task","type":"string"}},"required":["created","done","name","type"],"type":"object"},"type":"object"}},"required":["name","tasks"],"type":"object"},"type":"object"},"read":{"example":["bob"],"items":{"type":"string"},"type":"array"},"references":{"items":{"properties":{"href":{"example":"https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2017-0144","type":"string"},"name":{"example":"CVE-2017-0144","type":"string"}},"required":["href","name"],"type":"object"},"type":"array"},"schema":{"example":"{}","type":"string"},"status":{"example":"open","type":"string"},"type":{"example":"incident","type":"string"},"write":{"example":["alice"],"items":{"type":"string"},"type":"array"}},"required":["created","modified","name","schema","status","type"],"type":"object"}`},
|
||||
|
||||
&createCollection{ID: "create-dashboard-collection", Name: "dashboards", DataType: "dashboards", Schema: `{"type":"object","properties":{"name":{"type":"string"},"widgets":{"items":{"type":"object","properties":{"aggregation":{"type":"string"},"filter":{"type":"string"},"name":{"type":"string"},"type":{"enum":[ "bar", "line", "pie" ]},"width": { "type": "integer", "minimum": 1, "maximum": 12 }},"required":["name","aggregation", "type", "width"]},"type":"array"}},"required":["name","widgets"]}`},
|
||||
|
||||
&updateDocument{ID: "update-settings-global-1", Collection: "settings", Key: "global", Document: &model.Settings{ArtifactStates: []*model.Type{{Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(model.TypeColorInfo)}, {Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(model.TypeColorError)}, {Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(model.TypeColorSuccess)}}, ArtifactKinds: []*model.Type{{Icon: "mdi-server", ID: "asset", Name: "Asset"}, {Icon: "mdi-bullseye", ID: "ioc", Name: "IOC"}}, Timeformat: "yyyy-MM-dd hh:mm:ss"}},
|
||||
&updateDocument[model.Settings]{ID: "update-settings-global-1", Collection: "settings", Key: "global", Document: &model.Settings{ArtifactStates: []*model.Type{{Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(model.TypeColorInfo)}, {Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(model.TypeColorError)}, {Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(model.TypeColorSuccess)}}, ArtifactKinds: []*model.Type{{Icon: "mdi-server", ID: "asset", Name: "Asset"}, {Icon: "mdi-bullseye", ID: "ioc", Name: "IOC"}}, Timeformat: "yyyy-MM-dd hh:mm:ss"}},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ func loadSchema(dataType, jsonschema string) (*driver.CollectionSchemaOptions, e
|
||||
ticketCollectionSchema := &driver.CollectionSchemaOptions{Level: driver.CollectionSchemaLevelStrict, Message: fmt.Sprintf("Validation of %s failed", dataType)}
|
||||
|
||||
err := ticketCollectionSchema.LoadRule([]byte(jsonschema))
|
||||
|
||||
return ticketCollectionSchema, err
|
||||
}
|
||||
|
||||
@@ -101,6 +102,7 @@ func PerformMigrations(ctx context.Context, db driver.Database) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -171,41 +173,43 @@ func (m *createGraph) Migrate(ctx context.Context, db driver.Database) error {
|
||||
_, err := db.CreateGraph(ctx, m.Name, &driver.CreateGraphOptions{
|
||||
EdgeDefinitions: m.EdgeDefinitions,
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type createDocument struct {
|
||||
type createDocument[T any] struct {
|
||||
ID string
|
||||
Collection string
|
||||
Document interface{}
|
||||
Document *T
|
||||
}
|
||||
|
||||
func (m *createDocument) MID() string {
|
||||
func (m *createDocument[T]) MID() string {
|
||||
return m.ID
|
||||
}
|
||||
|
||||
func (m *createDocument) Migrate(ctx context.Context, driver driver.Database) error {
|
||||
func (m *createDocument[T]) Migrate(ctx context.Context, driver driver.Database) error {
|
||||
collection, err := driver.Collection(ctx, m.Collection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = collection.CreateDocument(ctx, m.Document)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type updateDocument struct {
|
||||
type updateDocument[T any] struct {
|
||||
ID string
|
||||
Collection string
|
||||
Key string
|
||||
Document interface{}
|
||||
Document *T
|
||||
}
|
||||
|
||||
func (m *updateDocument) MID() string {
|
||||
func (m *updateDocument[T]) MID() string {
|
||||
return m.ID
|
||||
}
|
||||
|
||||
func (m *updateDocument) Migrate(ctx context.Context, driver driver.Database) error {
|
||||
func (m *updateDocument[T]) Migrate(ctx context.Context, driver driver.Database) error {
|
||||
collection, err := driver.Collection(ctx, m.Collection)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -218,9 +222,11 @@ func (m *updateDocument) Migrate(ctx context.Context, driver driver.Database) er
|
||||
|
||||
if !exists {
|
||||
_, err = collection.CreateDocument(ctx, m.Document)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = collection.ReplaceDocument(ctx, m.Key, m.Document)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ type PlaybookYAML struct {
|
||||
type TaskYAML struct {
|
||||
Name string `yaml:"name"`
|
||||
Type string `yaml:"type"`
|
||||
Schema interface{} `yaml:"schema"`
|
||||
Schema any `yaml:"schema"`
|
||||
Automation string `yaml:"automation"`
|
||||
Payload map[string]string `yaml:"payload"`
|
||||
Next map[string]string `yaml:"next"`
|
||||
@@ -42,6 +42,7 @@ func toPlaybooks(docs []*model.PlaybookTemplateForm) (map[string]*model.Playbook
|
||||
playbooks[strcase.ToKebab(playbook.Name)] = playbook
|
||||
}
|
||||
}
|
||||
|
||||
return playbooks, nil
|
||||
}
|
||||
|
||||
@@ -53,11 +54,17 @@ func toPlaybook(doc *model.PlaybookTemplateForm) (*model.Playbook, error) {
|
||||
}
|
||||
for idx, task := range ticketPlaybook.Tasks {
|
||||
if task.Schema != nil {
|
||||
task.Schema = dyno.ConvertMapI2MapS(task.Schema).(map[string]interface{})
|
||||
schema, ok := dyno.ConvertMapI2MapS(task.Schema).(map[string]any)
|
||||
if ok {
|
||||
task.Schema = schema
|
||||
} else {
|
||||
return nil, errors.New("could not convert schema")
|
||||
}
|
||||
}
|
||||
task.Created = time.Now().UTC()
|
||||
ticketPlaybook.Tasks[idx] = task
|
||||
}
|
||||
|
||||
return ticketPlaybook, nil
|
||||
}
|
||||
|
||||
@@ -84,7 +91,7 @@ func (db *Database) PlaybookCreate(ctx context.Context, playbook *model.Playbook
|
||||
var doc model.PlaybookTemplate
|
||||
newctx := driver.WithReturnNew(ctx, &doc)
|
||||
|
||||
meta, err := db.playbookCollection.CreateDocument(ctx, newctx, strcase.ToKebab(playbookYAML.Name), p)
|
||||
meta, err := db.playbookCollection.CreateDocument(ctx, newctx, strcase.ToKebab(playbookYAML.Name), &p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -104,6 +111,7 @@ func (db *Database) PlaybookGet(ctx context.Context, id string) (*model.Playbook
|
||||
|
||||
func (db *Database) PlaybookDelete(ctx context.Context, id string) error {
|
||||
_, err := db.playbookCollection.RemoveDocument(ctx, id)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -121,7 +129,7 @@ func (db *Database) PlaybookUpdate(ctx context.Context, id string, playbook *mod
|
||||
var doc model.PlaybookTemplate
|
||||
ctx = driver.WithReturnNew(ctx, &doc)
|
||||
|
||||
meta, err := db.playbookCollection.ReplaceDocument(ctx, id, model.PlaybookTemplate{Name: pb.Name, Yaml: playbook.Yaml})
|
||||
meta, err := db.playbookCollection.ReplaceDocument(ctx, id, &model.PlaybookTemplate{Name: pb.Name, Yaml: playbook.Yaml})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -131,7 +139,7 @@ func (db *Database) PlaybookUpdate(ctx context.Context, id string, playbook *mod
|
||||
|
||||
func (db *Database) PlaybookList(ctx context.Context) ([]*model.PlaybookTemplateResponse, error) {
|
||||
query := "FOR d IN @@collection RETURN d"
|
||||
cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": PlaybookCollectionName}, busdb.ReadOperation)
|
||||
cursor, _, err := db.Query(ctx, query, map[string]any{"@collection": PlaybookCollectionName}, busdb.ReadOperation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ func playbookGraph(playbook *model.Playbook) (*dag.Graph, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
@@ -109,6 +110,7 @@ func active(playbook *model.Playbook, taskID string, d *dag.Graph, task *model.T
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -129,10 +131,11 @@ func active(playbook *model.Playbook, taskID string, d *dag.Graph, task *model.T
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func evalRequirement(aql string, data interface{}) (bool, error) {
|
||||
func evalRequirement(aql string, data any) (bool, error) {
|
||||
if aql == "" {
|
||||
return true, nil
|
||||
}
|
||||
@@ -143,9 +146,9 @@ func evalRequirement(aql string, data interface{}) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var dataMap map[string]interface{}
|
||||
var dataMap map[string]any
|
||||
if data != nil {
|
||||
if dataMapX, ok := data.(map[string]interface{}); ok {
|
||||
if dataMapX, ok := data.(map[string]any); ok {
|
||||
dataMap = dataMapX
|
||||
} else {
|
||||
log.Println("wrong data type for task data")
|
||||
@@ -160,6 +163,7 @@ func evalRequirement(aql string, data interface{}) (bool, error) {
|
||||
if b, ok := v.(bool); ok {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@ var playbook2 = &model.Playbook{
|
||||
Name: "Phishing",
|
||||
Tasks: map[string]*model.Task{
|
||||
"board": {Next: map[string]string{
|
||||
"escalate": "boardInvolved == true",
|
||||
"aquire-mail": "boardInvolved == false",
|
||||
"escalate": "boardInvolved == true",
|
||||
"acquire-mail": "boardInvolved == false",
|
||||
}},
|
||||
"escalate": {},
|
||||
"aquire-mail": {Next: map[string]string{
|
||||
"acquire-mail": {Next: map[string]string{
|
||||
"extract-iocs": "schemaKey == 'yes'",
|
||||
"block-sender": "schemaKey == 'yes'",
|
||||
"search-email-gateway": "schemaKey == 'no'",
|
||||
@@ -34,11 +34,11 @@ var playbook3 = &model.Playbook{
|
||||
Name: "Phishing",
|
||||
Tasks: map[string]*model.Task{
|
||||
"board": {Next: map[string]string{
|
||||
"escalate": "boardInvolved == true",
|
||||
"aquire-mail": "boardInvolved == false",
|
||||
}, Data: map[string]interface{}{"boardInvolved": true}, Done: true},
|
||||
"escalate": "boardInvolved == true",
|
||||
"acquire-mail": "boardInvolved == false",
|
||||
}, Data: map[string]any{"boardInvolved": true}, Done: true},
|
||||
"escalate": {},
|
||||
"aquire-mail": {Next: map[string]string{
|
||||
"acquire-mail": {Next: map[string]string{
|
||||
"extract-iocs": "schemaKey == 'yes'",
|
||||
"block-sender": "schemaKey == 'yes'",
|
||||
"search-email-gateway": "schemaKey == 'no'",
|
||||
@@ -71,6 +71,8 @@ var playbook4 = &model.Playbook{
|
||||
}
|
||||
|
||||
func Test_canBeCompleted(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type args struct {
|
||||
playbook *model.Playbook
|
||||
taskID string
|
||||
@@ -83,18 +85,22 @@ func Test_canBeCompleted(t *testing.T) {
|
||||
}{
|
||||
{"playbook2 board", args{playbook: playbook2, taskID: "board"}, true, false},
|
||||
{"playbook2 escalate", args{playbook: playbook2, taskID: "escalate"}, false, false},
|
||||
{"playbook2 aquire-mail", args{playbook: playbook2, taskID: "aquire-mail"}, false, false},
|
||||
{"playbook2 acquire-mail", args{playbook: playbook2, taskID: "acquire-mail"}, false, false},
|
||||
{"playbook2 block-ioc", args{playbook: playbook2, taskID: "block-ioc"}, false, false},
|
||||
{"playbook3 board", args{playbook: playbook3, taskID: "board"}, false, false},
|
||||
{"playbook3 escalate", args{playbook: playbook3, taskID: "escalate"}, true, false},
|
||||
{"playbook3 aquire-mail", args{playbook: playbook3, taskID: "aquire-mail"}, false, false},
|
||||
{"playbook3 acquire-mail", args{playbook: playbook3, taskID: "acquire-mail"}, false, false},
|
||||
{"playbook3 block-ioc", args{playbook: playbook3, taskID: "block-ioc"}, false, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
got, err := activePlaybook(tt.args.playbook, tt.args.taskID)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("activePlaybook() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
@@ -105,6 +111,8 @@ func Test_canBeCompleted(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_playbookOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type args struct {
|
||||
playbook *model.Playbook
|
||||
}
|
||||
@@ -117,10 +125,14 @@ func Test_playbookOrder(t *testing.T) {
|
||||
{"playbook4", args{playbook: playbook4}, []string{"file-or-hash", "enter-hash", "upload", "hash", "virustotal"}, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
got, err := toPlaybookResponse(tt.args.playbook)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("activePlaybook() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,13 @@ func (db *Database) RelatedCreate(ctx context.Context, id, id2 int64) error {
|
||||
From: driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id))),
|
||||
To: driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id2))),
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *Database) RelatedBatchCreate(ctx context.Context, edges []*driver.EdgeDocument) error {
|
||||
_, err := db.relatedCollection.CreateEdges(ctx, edges)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -33,7 +35,7 @@ func (db *Database) RelatedRemove(ctx context.Context, id, id2 int64) error {
|
||||
FOR d in @@collection
|
||||
FILTER (d._from == @id && d._to == @id2) || (d._to == @id && d._from == @id2)
|
||||
REMOVE d in @@collection`
|
||||
_, _, err := db.Query(ctx, q, map[string]interface{}{
|
||||
_, _, err := db.Query(ctx, q, map[string]any{
|
||||
"@collection": RelatedTicketsCollectionName,
|
||||
"id": driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id))),
|
||||
"id2": driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id2))),
|
||||
@@ -44,5 +46,6 @@ func (db *Database) RelatedRemove(ctx context.Context, id, id2 int64) error {
|
||||
driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id2))),
|
||||
},
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -44,12 +44,12 @@ func (db *Database) Statistics(ctx context.Context) (*model.Statistics, error) {
|
||||
return &statistics, nil
|
||||
}
|
||||
|
||||
func (db *Database) WidgetData(ctx context.Context, aggregation string, filter *string) (map[string]interface{}, error) {
|
||||
func (db *Database) WidgetData(ctx context.Context, aggregation string, filter *string) (map[string]any, error) {
|
||||
parser := &caql.Parser{Searcher: db.Index, Prefix: "d."}
|
||||
|
||||
queryTree, err := parser.Parse(aggregation)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid aggregation query (%s): syntax error\n", aggregation)
|
||||
return nil, fmt.Errorf("invalid aggregation query (%s): syntax error", aggregation)
|
||||
}
|
||||
aggregationString, err := queryTree.String()
|
||||
if err != nil {
|
||||
@@ -61,7 +61,7 @@ func (db *Database) WidgetData(ctx context.Context, aggregation string, filter *
|
||||
if filter != nil && *filter != "" {
|
||||
queryTree, err := parser.Parse(*filter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid filter query (%s): syntax error\n", *filter)
|
||||
return nil, fmt.Errorf("invalid filter query (%s): syntax error", *filter)
|
||||
}
|
||||
filterString, err := queryTree.String()
|
||||
if err != nil {
|
||||
@@ -82,7 +82,7 @@ func (db *Database) WidgetData(ctx context.Context, aggregation string, filter *
|
||||
}
|
||||
defer cur.Close()
|
||||
|
||||
statistics := map[string]interface{}{}
|
||||
statistics := map[string]any{}
|
||||
if _, err := cur.ReadDocument(ctx, &statistics); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
)
|
||||
|
||||
type playbookResponse struct {
|
||||
PlaybookId string `json:"playbook_id"`
|
||||
PlaybookID string `json:"playbook_id"`
|
||||
PlaybookName string `json:"playbook_name"`
|
||||
Playbook model.Playbook `json:"playbook"`
|
||||
TicketId int64 `json:"ticket_id"`
|
||||
TicketID int64 `json:"ticket_id"`
|
||||
TicketName string `json:"ticket_name"`
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func (db *Database) TaskList(ctx context.Context) ([]*model.TaskWithContext, err
|
||||
FILTER d.status == 'open'
|
||||
FOR playbook IN NOT_NULL(VALUES(d.playbooks), [])
|
||||
RETURN { ticket_id: TO_NUMBER(d._key), ticket_name: d.name, playbook_id: POSITION(d.playbooks, playbook, true), playbook_name: playbook.name, playbook: playbook }`
|
||||
cursor, _, err := db.Query(ctx, query, mergeMaps(ticketFilterVars, map[string]interface{}{
|
||||
cursor, _, err := db.Query(ctx, query, mergeMaps(ticketFilterVars, map[string]any{
|
||||
"@collection": TicketCollectionName,
|
||||
}), busdb.ReadOperation)
|
||||
if err != nil {
|
||||
@@ -53,10 +53,10 @@ func (db *Database) TaskList(ctx context.Context) ([]*model.TaskWithContext, err
|
||||
for _, task := range playbook.Tasks {
|
||||
if task.Active {
|
||||
docs = append(docs, &model.TaskWithContext{
|
||||
PlaybookId: doc.PlaybookId,
|
||||
PlaybookId: doc.PlaybookID,
|
||||
PlaybookName: doc.PlaybookName,
|
||||
Task: task,
|
||||
TicketId: doc.TicketId,
|
||||
TicketId: doc.TicketID,
|
||||
TicketName: doc.TicketName,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -62,12 +62,13 @@ func (db *Database) TemplateUpdate(ctx context.Context, id string, template *mod
|
||||
|
||||
func (db *Database) TemplateDelete(ctx context.Context, id string) error {
|
||||
_, err := db.templateCollection.RemoveDocument(ctx, id)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *Database) TemplateList(ctx context.Context) ([]*model.TicketTemplateResponse, error) {
|
||||
query := "FOR d IN @@collection RETURN d"
|
||||
cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": TemplateCollectionName}, busdb.ReadOperation)
|
||||
cursor, _, err := db.Query(ctx, query, map[string]any{"@collection": TemplateCollectionName}, busdb.ReadOperation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -10,16 +10,20 @@ import (
|
||||
"github.com/SecurityBrewery/catalyst/test"
|
||||
)
|
||||
|
||||
var template1 = &model.TicketTemplateForm{
|
||||
Schema: migrations.DefaultTemplateSchema,
|
||||
Name: "Template 1",
|
||||
}
|
||||
var default1 = &model.TicketTemplateForm{
|
||||
Schema: migrations.DefaultTemplateSchema,
|
||||
Name: "Default",
|
||||
}
|
||||
var (
|
||||
template1 = &model.TicketTemplateForm{
|
||||
Schema: migrations.DefaultTemplateSchema,
|
||||
Name: "Template 1",
|
||||
}
|
||||
default1 = &model.TicketTemplateForm{
|
||||
Schema: migrations.DefaultTemplateSchema,
|
||||
Name: "Default",
|
||||
}
|
||||
)
|
||||
|
||||
func TestDatabase_TemplateCreate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type args struct {
|
||||
template *model.TicketTemplateForm
|
||||
}
|
||||
@@ -35,7 +39,10 @@ func TestDatabase_TemplateCreate(t *testing.T) {
|
||||
{name: "Only name", args: args{template: &model.TicketTemplateForm{Name: "name"}}, wantErr: false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, _, _, _, db, cleanup, err := test.DB(t)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -50,6 +57,8 @@ func TestDatabase_TemplateCreate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDatabase_TemplateDelete(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type args struct {
|
||||
id string
|
||||
}
|
||||
@@ -62,7 +71,10 @@ func TestDatabase_TemplateDelete(t *testing.T) {
|
||||
{name: "Not existing", args: args{"foobar"}, wantErr: true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, _, _, _, db, cleanup, err := test.DB(t)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -81,6 +93,8 @@ func TestDatabase_TemplateDelete(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDatabase_TemplateGet(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type args struct {
|
||||
id string
|
||||
}
|
||||
@@ -94,7 +108,10 @@ func TestDatabase_TemplateGet(t *testing.T) {
|
||||
{name: "Not existing", args: args{id: "foobar"}, wantErr: true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, _, _, _, db, cleanup, err := test.DB(t)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -108,6 +125,7 @@ func TestDatabase_TemplateGet(t *testing.T) {
|
||||
got, err := db.TemplateGet(test.Context(), tt.args.id)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("TemplateGet() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
@@ -120,6 +138,8 @@ func TestDatabase_TemplateGet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDatabase_TemplateList(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
want []*model.TicketTemplateResponse
|
||||
@@ -128,7 +148,10 @@ func TestDatabase_TemplateList(t *testing.T) {
|
||||
{name: "Normal", want: []*model.TicketTemplateResponse{{ID: "default", Name: "Default", Schema: migrations.DefaultTemplateSchema}, {ID: "template-1", Name: template1.Name, Schema: template1.Schema}}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, _, _, _, db, cleanup, err := test.DB(t)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -142,6 +165,7 @@ func TestDatabase_TemplateList(t *testing.T) {
|
||||
got, err := db.TemplateList(test.Context())
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("TemplateList() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
assert.Equal(t, got, tt.want)
|
||||
@@ -150,6 +174,8 @@ func TestDatabase_TemplateList(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDatabase_TemplateUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type args struct {
|
||||
id string
|
||||
template *model.TicketTemplateForm
|
||||
@@ -163,7 +189,10 @@ func TestDatabase_TemplateUpdate(t *testing.T) {
|
||||
{name: "Not existing", args: args{"foobar", template1}, wantErr: true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, _, _, _, db, cleanup, err := test.DB(t)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -21,7 +22,7 @@ import (
|
||||
"github.com/SecurityBrewery/catalyst/index"
|
||||
)
|
||||
|
||||
func toTicket(ticketForm *model.TicketForm) (interface{}, error) {
|
||||
func toTicket(ticketForm *model.TicketForm) (any, error) {
|
||||
playbooks, err := toPlaybooks(ticketForm.Playbooks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -65,8 +66,9 @@ func toTicket(ticketForm *model.TicketForm) (interface{}, error) {
|
||||
ticket.Status = "open"
|
||||
}
|
||||
if ticketForm.ID != nil {
|
||||
return &busdb.Keyed{Key: strconv.FormatInt(*ticketForm.ID, 10), Doc: ticket}, nil
|
||||
return &busdb.Keyed[model.Ticket]{Key: strconv.FormatInt(*ticketForm.ID, 10), Doc: ticket}, nil
|
||||
}
|
||||
|
||||
return ticket, nil
|
||||
}
|
||||
|
||||
@@ -79,6 +81,7 @@ func toTicketResponses(tickets []*model.TicketSimpleResponse) ([]*model.TicketRe
|
||||
}
|
||||
extendedTickets = append(extendedTickets, tr)
|
||||
}
|
||||
|
||||
return extendedTickets, nil
|
||||
}
|
||||
|
||||
@@ -167,6 +170,7 @@ func toPlaybookResponses(playbooks map[string]*model.Playbook) (map[string]*mode
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return pr, nil
|
||||
}
|
||||
|
||||
@@ -195,6 +199,7 @@ func toPlaybookResponse(playbook *model.Playbook) (*model.PlaybookResponse, erro
|
||||
re.Tasks[taskID] = rootTask
|
||||
i++
|
||||
}
|
||||
|
||||
return re, nil
|
||||
}
|
||||
|
||||
@@ -204,7 +209,7 @@ func (db *Database) TicketBatchCreate(ctx context.Context, ticketForms []*model.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dbTickets []interface{}
|
||||
var dbTickets []any
|
||||
for _, ticketForm := range ticketForms {
|
||||
ticket, err := toTicket(ticketForm)
|
||||
if err != nil {
|
||||
@@ -231,7 +236,7 @@ func (db *Database) TicketBatchCreate(ctx context.Context, ticketForms []*model.
|
||||
LET noiddoc = UNSET(keyeddoc, "id")
|
||||
INSERT noiddoc INTO @@collection
|
||||
RETURN NEW`
|
||||
apiTickets, _, err := db.ticketListQuery(ctx, query, mergeMaps(map[string]interface{}{
|
||||
apiTickets, _, err := db.ticketListQuery(ctx, query, mergeMaps(map[string]any{
|
||||
"tickets": dbTickets,
|
||||
}, ticketFilterVars), busdb.CreateOperation)
|
||||
if err != nil {
|
||||
@@ -247,7 +252,11 @@ func (db *Database) TicketBatchCreate(ctx context.Context, ticketForms []*model.
|
||||
ids = append(ids, driver.NewDocumentID(TicketCollectionName, fmt.Sprint(apiTicket.ID)))
|
||||
}
|
||||
|
||||
go db.bus.PublishDatabaseUpdate(ids, bus.DatabaseEntryUpdated)
|
||||
go func() {
|
||||
if err := db.bus.PublishDatabaseUpdate(ids, bus.DatabaseEntryUpdated); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}()
|
||||
|
||||
ticketResponses, err := toTicketResponses(apiTickets)
|
||||
if err != nil {
|
||||
@@ -294,6 +303,7 @@ func batchIndex(index *index.Index, tickets []*model.TicketSimpleResponse) error
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -306,9 +316,9 @@ func (db *Database) TicketGet(ctx context.Context, ticketID int64) (*model.Ticke
|
||||
return db.ticketGetQuery(ctx, ticketID, `LET d = DOCUMENT(@@collection, @ID) `+ticketFilterQuery+` RETURN d`, ticketFilterVars, busdb.ReadOperation)
|
||||
}
|
||||
|
||||
func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query string, bindVars map[string]interface{}, operation *busdb.Operation) (*model.TicketWithTickets, error) {
|
||||
func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query string, bindVars map[string]any, operation *busdb.Operation) (*model.TicketWithTickets, error) {
|
||||
if bindVars == nil {
|
||||
bindVars = map[string]interface{}{}
|
||||
bindVars = map[string]any{}
|
||||
}
|
||||
bindVars["@collection"] = TicketCollectionName
|
||||
if ticketID != 0 {
|
||||
@@ -350,7 +360,7 @@ func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query st
|
||||
` + ticketFilterQuery + `
|
||||
RETURN d`
|
||||
|
||||
outTickets, _, err := db.ticketListQuery(ctx, ticketsQuery, mergeMaps(map[string]interface{}{
|
||||
outTickets, _, err := db.ticketListQuery(ctx, ticketsQuery, mergeMaps(map[string]any{
|
||||
"ID": fmt.Sprint(ticketID),
|
||||
"graph": TicketArtifactsGraphName,
|
||||
"@tickets": TicketCollectionName,
|
||||
@@ -368,7 +378,7 @@ func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query st
|
||||
` + ticketFilterQuery + `
|
||||
RETURN d`
|
||||
|
||||
inTickets, _, err := db.ticketListQuery(ctx, ticketsQuery, mergeMaps(map[string]interface{}{
|
||||
inTickets, _, err := db.ticketListQuery(ctx, ticketsQuery, mergeMaps(map[string]any{
|
||||
"ID": fmt.Sprint(ticketID),
|
||||
"graph": TicketArtifactsGraphName,
|
||||
"@tickets": TicketCollectionName,
|
||||
@@ -387,7 +397,7 @@ func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query st
|
||||
FOR a IN NOT_NULL(d.artifacts, [])
|
||||
FILTER POSITION(@artifacts, a.name)
|
||||
RETURN d`
|
||||
sameArtifactTickets, _, err := db.ticketListQuery(ctx, ticketsQuery, mergeMaps(map[string]interface{}{
|
||||
sameArtifactTickets, _, err := db.ticketListQuery(ctx, ticketsQuery, mergeMaps(map[string]any{
|
||||
"ID": fmt.Sprint(ticketID),
|
||||
"artifacts": artifactNames,
|
||||
}, ticketFilterVars), busdb.ReadOperation)
|
||||
@@ -395,7 +405,8 @@ func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query st
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tickets := append(outTickets, inTickets...)
|
||||
tickets := outTickets
|
||||
tickets = append(tickets, inTickets...)
|
||||
tickets = append(tickets, sameArtifactTickets...)
|
||||
sort.Slice(tickets, func(i, j int) bool {
|
||||
return tickets[i].ID < tickets[j].ID
|
||||
@@ -425,7 +436,8 @@ func (db *Database) TicketUpdate(ctx context.Context, ticketID int64, ticket *mo
|
||||
REPLACE d WITH @ticket IN @@collection
|
||||
RETURN NEW`
|
||||
ticket.Modified = time.Now().UTC() // TODO make setable?
|
||||
return db.ticketGetQuery(ctx, ticketID, query, mergeMaps(map[string]interface{}{"ticket": ticket}, ticketFilterVars), &busdb.Operation{
|
||||
|
||||
return db.ticketGetQuery(ctx, ticketID, query, mergeMaps(map[string]any{"ticket": ticket}, ticketFilterVars), &busdb.Operation{
|
||||
Type: bus.DatabaseEntryUpdated, Ids: []driver.DocumentID{
|
||||
driver.NewDocumentID(TicketCollectionName, strconv.FormatInt(ticketID, 10)),
|
||||
},
|
||||
@@ -447,15 +459,15 @@ func (db *Database) TicketDelete(ctx context.Context, ticketID int64) error {
|
||||
}
|
||||
|
||||
func (db *Database) TicketList(ctx context.Context, ticketType string, query string, sorts []string, desc []bool, offset, count int64) (*model.TicketList, error) {
|
||||
binVars := map[string]interface{}{}
|
||||
binVars := map[string]any{}
|
||||
|
||||
var typeString = ""
|
||||
typeString := ""
|
||||
if ticketType != "" {
|
||||
typeString = "FILTER d.type == @type "
|
||||
binVars["type"] = ticketType
|
||||
}
|
||||
|
||||
var filterString = ""
|
||||
filterString := ""
|
||||
if query != "" {
|
||||
parser := &caql.Parser{Searcher: db.Index, Prefix: "d."}
|
||||
queryTree, err := parser.Parse(query)
|
||||
@@ -493,6 +505,7 @@ func (db *Database) TicketList(ctx context.Context, ticketType string, query str
|
||||
RETURN d`
|
||||
// RETURN KEEP(d, "_key", "id", "name", "type", "created")`
|
||||
ticketList, _, err := db.ticketListQuery(ctx, q, mergeMaps(binVars, ticketFilterVars), busdb.ReadOperation)
|
||||
|
||||
return &model.TicketList{
|
||||
Count: documentCount,
|
||||
Tickets: ticketList,
|
||||
@@ -500,9 +513,9 @@ func (db *Database) TicketList(ctx context.Context, ticketType string, query str
|
||||
// return map[string]interface{}{"tickets": ticketList, "count": documentCount}, err
|
||||
}
|
||||
|
||||
func (db *Database) ticketListQuery(ctx context.Context, query string, bindVars map[string]interface{}, operation *busdb.Operation) ([]*model.TicketSimpleResponse, *model.LogEntry, error) {
|
||||
func (db *Database) ticketListQuery(ctx context.Context, query string, bindVars map[string]any, operation *busdb.Operation) ([]*model.TicketSimpleResponse, *model.LogEntry, error) {
|
||||
if bindVars == nil {
|
||||
bindVars = map[string]interface{}{}
|
||||
bindVars = map[string]any{}
|
||||
}
|
||||
bindVars["@collection"] = TicketCollectionName
|
||||
|
||||
@@ -533,9 +546,9 @@ func (db *Database) ticketListQuery(ctx context.Context, query string, bindVars
|
||||
return docs, logEntry, nil
|
||||
}
|
||||
|
||||
func (db *Database) TicketCount(ctx context.Context, typequery, filterquery string, bindVars map[string]interface{}) (int, error) {
|
||||
func (db *Database) TicketCount(ctx context.Context, typequery, filterquery string, bindVars map[string]any) (int, error) {
|
||||
if bindVars == nil {
|
||||
bindVars = map[string]interface{}{}
|
||||
bindVars = map[string]any{}
|
||||
}
|
||||
bindVars["@collection"] = TicketCollectionName
|
||||
|
||||
@@ -555,10 +568,11 @@ func (db *Database) TicketCount(ctx context.Context, typequery, filterquery stri
|
||||
return 0, err
|
||||
}
|
||||
cursor.Close()
|
||||
|
||||
return documentCount, nil
|
||||
}
|
||||
|
||||
func sortQuery(paramsSort []string, paramsDesc []bool, bindVars map[string]interface{}) string {
|
||||
func sortQuery(paramsSort []string, paramsDesc []bool, bindVars map[string]any) string {
|
||||
sort := ""
|
||||
if len(paramsSort) > 0 {
|
||||
var sorts []string
|
||||
@@ -572,21 +586,23 @@ func sortQuery(paramsSort []string, paramsDesc []bool, bindVars map[string]inter
|
||||
}
|
||||
sort = "SORT " + strings.Join(sorts, ", ")
|
||||
}
|
||||
|
||||
return sort
|
||||
}
|
||||
|
||||
func mergeMaps(a map[string]interface{}, b map[string]interface{}) map[string]interface{} {
|
||||
merged := map[string]interface{}{}
|
||||
func mergeMaps(a map[string]any, b map[string]any) map[string]any {
|
||||
merged := map[string]any{}
|
||||
for k, v := range a {
|
||||
merged[k] = v
|
||||
}
|
||||
for k, v := range b {
|
||||
merged[k] = v
|
||||
}
|
||||
|
||||
return merged
|
||||
}
|
||||
|
||||
func validate(e interface{}, schema *gojsonschema.Schema) error {
|
||||
func validate(e any, schema *gojsonschema.Schema) error {
|
||||
b, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -602,7 +618,9 @@ func validate(e interface{}, schema *gojsonschema.Schema) error {
|
||||
for _, e := range res.Errors() {
|
||||
l = append(l, e.String())
|
||||
}
|
||||
|
||||
return fmt.Errorf("validation failed: %v", strings.Join(l, ", "))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ func (db *Database) AddArtifact(ctx context.Context, id int64, artifact *model.A
|
||||
` + ticketFilterQuery + `
|
||||
UPDATE d WITH { "modified": @now, "artifacts": PUSH(NOT_NULL(d.artifacts, []), @artifact) } IN @@collection
|
||||
RETURN NEW`
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{"artifact": artifact, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{"artifact": artifact, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
Type: bus.DatabaseEntryUpdated,
|
||||
Ids: []driver.DocumentID{
|
||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||
@@ -57,6 +58,7 @@ func inferType(name string) string {
|
||||
case commonregex.SHA256HexRegex.MatchString(name):
|
||||
return "sha256"
|
||||
}
|
||||
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
@@ -73,7 +75,8 @@ func (db *Database) RemoveArtifact(ctx context.Context, id int64, name string) (
|
||||
LET newartifacts = REMOVE_VALUE(d.artifacts, a)
|
||||
UPDATE d WITH { "modified": @now, "artifacts": newartifacts } IN @@collection
|
||||
RETURN NEW`
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{"name": name, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{"name": name, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
Type: bus.DatabaseEntryUpdated,
|
||||
Ids: []driver.DocumentID{
|
||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||
@@ -91,7 +94,8 @@ func (db *Database) SetTemplate(ctx context.Context, id int64, schema string) (*
|
||||
` + ticketFilterQuery + `
|
||||
UPDATE d WITH { "schema": @schema } IN @@collection
|
||||
RETURN NEW`
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{"schema": schema}, ticketFilterVars), &busdb.Operation{
|
||||
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{"schema": schema}, ticketFilterVars), &busdb.Operation{
|
||||
Type: bus.DatabaseEntryUpdated,
|
||||
Ids: []driver.DocumentID{
|
||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||
@@ -122,7 +126,8 @@ func (db *Database) AddComment(ctx context.Context, id int64, comment *model.Com
|
||||
` + ticketFilterQuery + `
|
||||
UPDATE d WITH { "modified": @now, "comments": PUSH(NOT_NULL(d.comments, []), @comment) } IN @@collection
|
||||
RETURN NEW`
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{"comment": comment, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{"comment": comment, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
Type: bus.DatabaseEntryUpdated,
|
||||
Ids: []driver.DocumentID{
|
||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||
@@ -140,7 +145,8 @@ func (db *Database) RemoveComment(ctx context.Context, id int64, commentID int64
|
||||
` + ticketFilterQuery + `
|
||||
UPDATE d WITH { "modified": @now, "comments": REMOVE_NTH(d.comments, @commentID) } IN @@collection
|
||||
RETURN NEW`
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{"commentID": commentID, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{"commentID": commentID, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
Type: bus.DatabaseEntryUpdated,
|
||||
Ids: []driver.DocumentID{
|
||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||
@@ -158,7 +164,8 @@ func (db *Database) SetReferences(ctx context.Context, id int64, references []*m
|
||||
` + ticketFilterQuery + `
|
||||
UPDATE d WITH { "modified": @now, "references": @references } IN @@collection
|
||||
RETURN NEW`
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{"references": references, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{"references": references, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
Type: bus.DatabaseEntryUpdated,
|
||||
Ids: []driver.DocumentID{
|
||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||
@@ -176,7 +183,8 @@ func (db *Database) AddFile(ctx context.Context, id int64, file *model.File) (*m
|
||||
` + ticketFilterQuery + `
|
||||
UPDATE d WITH { "modified": @now, "files": APPEND(NOT_NULL(d.files, []), [@file]) } IN @@collection
|
||||
RETURN NEW`
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{"file": file, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{"file": file, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||
Type: bus.DatabaseEntryUpdated,
|
||||
Ids: []driver.DocumentID{
|
||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||
@@ -213,7 +221,7 @@ func (db *Database) AddTicketPlaybook(ctx context.Context, id int64, playbookTem
|
||||
LET newticket = MERGE(d, { "modified": @now, "playbooks": newplaybooks })
|
||||
REPLACE d WITH newticket IN @@collection
|
||||
RETURN NEW`
|
||||
ticket, err := db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{
|
||||
ticket, err := db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{
|
||||
"playbook": pb,
|
||||
"playbookID": findName(parentTicket.Playbooks, playbookID),
|
||||
"now": time.Now().UTC(),
|
||||
@@ -258,6 +266,7 @@ func runRootTask(ticket *model.TicketResponse, playbookID string, db *Database)
|
||||
}
|
||||
|
||||
runNextTasks(ticket.ID, playbookID, root.Next, root.Data, ticket, db)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -273,7 +282,8 @@ func (db *Database) RemoveTicketPlaybook(ctx context.Context, id int64, playbook
|
||||
LET newplaybooks = UNSET(d.playbooks, @playbookID)
|
||||
REPLACE d WITH MERGE(d, { "modified": @now, "playbooks": newplaybooks }) IN @@collection
|
||||
RETURN NEW`
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{
|
||||
|
||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{
|
||||
"playbookID": playbookID,
|
||||
"now": time.Now().UTC(),
|
||||
}, ticketFilterVars), &busdb.Operation{
|
||||
|
||||
@@ -41,7 +41,7 @@ func (db *Database) TaskGet(ctx context.Context, id int64, playbookID string, ta
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (db *Database) TaskComplete(ctx context.Context, id int64, playbookID string, taskID string, data interface{}) (*model.TicketWithTickets, error) {
|
||||
func (db *Database) TaskComplete(ctx context.Context, id int64, playbookID string, taskID string, data any) (*model.TicketWithTickets, error) {
|
||||
inc, err := db.TicketGet(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -68,7 +68,7 @@ func (db *Database) TaskComplete(ctx context.Context, id int64, playbookID strin
|
||||
|
||||
UPDATE d WITH { "modified": @now, "playbooks": newplaybooks } IN @@collection
|
||||
RETURN NEW`
|
||||
ticket, err := db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{
|
||||
ticket, err := db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{
|
||||
"playbookID": playbookID,
|
||||
"taskID": taskID,
|
||||
"data": data,
|
||||
@@ -130,7 +130,7 @@ func (db *Database) TaskUpdateOwner(ctx context.Context, id int64, playbookID st
|
||||
|
||||
UPDATE d WITH { "modified": @now, "playbooks": newplaybooks } IN @@collection
|
||||
RETURN NEW`
|
||||
ticket, err := db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{
|
||||
ticket, err := db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{
|
||||
"playbookID": playbookID,
|
||||
"taskID": taskID,
|
||||
"owner": owner,
|
||||
@@ -148,7 +148,7 @@ func (db *Database) TaskUpdateOwner(ctx context.Context, id int64, playbookID st
|
||||
return ticket, nil
|
||||
}
|
||||
|
||||
func (db *Database) TaskUpdateData(ctx context.Context, id int64, playbookID string, taskID string, data map[string]interface{}) (*model.TicketWithTickets, error) {
|
||||
func (db *Database) TaskUpdateData(ctx context.Context, id int64, playbookID string, taskID string, data map[string]any) (*model.TicketWithTickets, error) {
|
||||
ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -165,7 +165,7 @@ func (db *Database) TaskUpdateData(ctx context.Context, id int64, playbookID str
|
||||
|
||||
UPDATE d WITH { "modified": @now, "playbooks": newplaybooks } IN @@collection
|
||||
RETURN NEW`
|
||||
ticket, err := db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{
|
||||
ticket, err := db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]any{
|
||||
"playbookID": playbookID,
|
||||
"taskID": taskID,
|
||||
"data": data,
|
||||
@@ -198,7 +198,7 @@ func (db *Database) TaskRun(ctx context.Context, id int64, playbookID string, ta
|
||||
return nil
|
||||
}
|
||||
|
||||
func runNextTasks(id int64, playbookID string, next map[string]string, data interface{}, ticket *model.TicketResponse, db *Database) {
|
||||
func runNextTasks(id int64, playbookID string, next map[string]string, data any, ticket *model.TicketResponse, db *Database) {
|
||||
for nextTaskID, requirement := range next {
|
||||
nextTask := ticket.Playbooks[playbookID].Tasks[nextTaskID]
|
||||
if nextTask.Type == model.TaskTypeAutomation {
|
||||
@@ -220,5 +220,6 @@ func runTask(ticketID int64, playbookID string, taskID string, task *model.TaskR
|
||||
msgContext := &model.Context{Playbook: playbook, Task: task, Ticket: ticket}
|
||||
origin := &model.Origin{TaskOrigin: &model.TaskOrigin{TaskId: taskID, PlaybookId: playbookID, TicketId: ticketID}}
|
||||
jobID := uuid.NewString()
|
||||
|
||||
return publishJobMapping(jobID, *task.Automation, msgContext, origin, task.Payload, db)
|
||||
}
|
||||
|
||||
@@ -75,12 +75,13 @@ func (db *Database) TicketTypeUpdate(ctx context.Context, id string, tickettype
|
||||
|
||||
func (db *Database) TicketTypeDelete(ctx context.Context, id string) error {
|
||||
_, err := db.tickettypeCollection.RemoveDocument(ctx, id)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *Database) TicketTypeList(ctx context.Context) ([]*model.TicketTypeResponse, error) {
|
||||
query := "FOR d IN @@collection RETURN d"
|
||||
cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": TicketTypeCollectionName}, busdb.ReadOperation)
|
||||
cursor, _, err := db.Query(ctx, query, map[string]any{"@collection": TicketTypeCollectionName}, busdb.ReadOperation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ func generateKey() string {
|
||||
for i := range b {
|
||||
b[i] = letters[rand.Intn(len(letters))]
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
@@ -78,8 +79,10 @@ func (db *Database) UserGetOrCreate(ctx context.Context, newUser *model.UserForm
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.UserResponse{ID: newUser.ID, Roles: newUser.Roles, Blocked: newUser.Blocked}, nil
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
@@ -132,12 +135,13 @@ func (db *Database) UserGet(ctx context.Context, id string) (*model.UserResponse
|
||||
|
||||
func (db *Database) UserDelete(ctx context.Context, id string) error {
|
||||
_, err := db.userCollection.RemoveDocument(ctx, id)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *Database) UserList(ctx context.Context) ([]*model.UserResponse, error) {
|
||||
query := "FOR d IN @@collection RETURN d"
|
||||
cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": UserCollectionName}, busdb.ReadOperation)
|
||||
cursor, _, err := db.Query(ctx, query, map[string]any{"@collection": UserCollectionName}, busdb.ReadOperation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -163,7 +167,7 @@ func (db *Database) UserByHash(ctx context.Context, sha256 string) (*model.UserR
|
||||
FILTER d.sha256 == @sha256
|
||||
RETURN d`
|
||||
|
||||
cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": UserCollectionName, "sha256": sha256}, busdb.ReadOperation)
|
||||
cursor, _, err := db.Query(ctx, query, map[string]any{"@collection": UserCollectionName, "sha256": sha256}, busdb.ReadOperation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ func (db *Database) UserDataCreate(ctx context.Context, id string, userdata *mod
|
||||
}
|
||||
|
||||
_, err := db.userdataCollection.CreateDocument(ctx, ctx, id, userdata)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -37,6 +38,7 @@ func (db *Database) UserDataGetOrCreate(ctx context.Context, id string, newUserD
|
||||
if err != nil {
|
||||
return toUserDataResponse(id, newUserData), db.UserDataCreate(ctx, id, newUserData)
|
||||
}
|
||||
|
||||
return setting, nil
|
||||
}
|
||||
|
||||
@@ -52,7 +54,7 @@ func (db *Database) UserDataGet(ctx context.Context, id string) (*model.UserData
|
||||
|
||||
func (db *Database) UserDataList(ctx context.Context) ([]*model.UserDataResponse, error) {
|
||||
query := "FOR d IN @@collection SORT d.username ASC RETURN d"
|
||||
cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": UserDataCollectionName}, busdb.ReadOperation)
|
||||
cursor, _, err := db.Query(ctx, query, map[string]any{"@collection": UserDataCollectionName}, busdb.ReadOperation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ var bobResponse = &model.UserDataResponse{
|
||||
}
|
||||
|
||||
func TestDatabase_UserDataCreate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type args struct {
|
||||
id string
|
||||
setting *model.UserData
|
||||
@@ -37,7 +39,10 @@ func TestDatabase_UserDataCreate(t *testing.T) {
|
||||
{name: "Only settingname", args: args{id: "bob"}, wantErr: true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, _, _, _, db, cleanup, err := test.DB(t)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -52,6 +57,8 @@ func TestDatabase_UserDataCreate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDatabase_UserDataGet(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type args struct {
|
||||
id string
|
||||
}
|
||||
@@ -65,7 +72,10 @@ func TestDatabase_UserDataGet(t *testing.T) {
|
||||
{name: "Not existing", args: args{id: "foo"}, wantErr: true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, _, _, _, db, cleanup, err := test.DB(t)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -79,6 +89,7 @@ func TestDatabase_UserDataGet(t *testing.T) {
|
||||
got, err := db.UserDataGet(test.Context(), tt.args.id)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("UserDataGet() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
@@ -91,6 +102,8 @@ func TestDatabase_UserDataGet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDatabase_UserDataList(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
want []*model.UserDataResponse
|
||||
@@ -99,7 +112,10 @@ func TestDatabase_UserDataList(t *testing.T) {
|
||||
{name: "Normal list", want: []*model.UserDataResponse{bobResponse}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, _, _, _, db, cleanup, err := test.DB(t)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -113,6 +129,7 @@ func TestDatabase_UserDataList(t *testing.T) {
|
||||
got, err := db.UserDataList(test.Context())
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("UserDataList() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -122,6 +139,8 @@ func TestDatabase_UserDataList(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDatabase_UserDataUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type args struct {
|
||||
id string
|
||||
setting *model.UserData
|
||||
@@ -135,7 +154,10 @@ func TestDatabase_UserDataUpdate(t *testing.T) {
|
||||
{name: "Not existing", args: args{id: "foo"}, wantErr: true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, _, _, _, db, cleanup, err := test.DB(t)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
Reference in New Issue
Block a user