mirror of
https://github.com/SecurityBrewery/catalyst.git
synced 2025-12-06 23:32:47 +01:00
Add Dashboards (#41)
This commit is contained in:
117
database/dashboard.go
Normal file
117
database/dashboard.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/arangodb/go-driver"
|
||||
"github.com/iancoleman/strcase"
|
||||
|
||||
"github.com/SecurityBrewery/catalyst/caql"
|
||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||
"github.com/SecurityBrewery/catalyst/generated/model"
|
||||
)
|
||||
|
||||
func toDashboardResponse(key string, doc *model.Dashboard) *model.DashboardResponse {
|
||||
return &model.DashboardResponse{
|
||||
ID: key,
|
||||
Name: doc.Name,
|
||||
Widgets: doc.Widgets,
|
||||
}
|
||||
}
|
||||
|
||||
func (db *Database) DashboardCreate(ctx context.Context, dashboard *model.Dashboard) (*model.DashboardResponse, error) {
|
||||
if dashboard == nil {
|
||||
return nil, errors.New("requires dashboard")
|
||||
}
|
||||
if dashboard.Name == "" {
|
||||
return nil, errors.New("requires dashboard name")
|
||||
}
|
||||
|
||||
if err := db.parseWidgets(dashboard); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var doc model.Dashboard
|
||||
newctx := driver.WithReturnNew(ctx, &doc)
|
||||
|
||||
meta, err := db.dashboardCollection.CreateDocument(ctx, newctx, strcase.ToKebab(dashboard.Name), dashboard)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return toDashboardResponse(meta.Key, &doc), nil
|
||||
}
|
||||
|
||||
func (db *Database) DashboardGet(ctx context.Context, id string) (*model.DashboardResponse, error) {
|
||||
var doc model.Dashboard
|
||||
meta, err := db.dashboardCollection.ReadDocument(ctx, id, &doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return toDashboardResponse(meta.Key, &doc), nil
|
||||
}
|
||||
|
||||
func (db *Database) DashboardUpdate(ctx context.Context, id string, dashboard *model.Dashboard) (*model.DashboardResponse, error) {
|
||||
if err := db.parseWidgets(dashboard); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var doc model.Dashboard
|
||||
ctx = driver.WithReturnNew(ctx, &doc)
|
||||
|
||||
meta, err := db.dashboardCollection.ReplaceDocument(ctx, id, dashboard)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return toDashboardResponse(meta.Key, &doc), nil
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close()
|
||||
var docs []*model.DashboardResponse
|
||||
for {
|
||||
var doc model.Dashboard
|
||||
meta, err := cursor.ReadDocument(ctx, &doc)
|
||||
if driver.IsNoMoreDocuments(err) {
|
||||
break
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
docs = append(docs, toDashboardResponse(meta.Key, &doc))
|
||||
}
|
||||
|
||||
return docs, err
|
||||
}
|
||||
|
||||
func (db *Database) parseWidgets(dashboard *model.Dashboard) error {
|
||||
for _, widget := range dashboard.Widgets {
|
||||
parser := &caql.Parser{Searcher: db.Index, Prefix: "d."}
|
||||
|
||||
_, err := parser.Parse(widget.Aggregation)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid aggregation query (%s): syntax error\n", 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 nil
|
||||
}
|
||||
Reference in New Issue
Block a user