Files
catalyst/database/busdb/busdb.go
2021-12-13 00:39:15 +01:00

183 lines
4.7 KiB
Go

package busdb
import (
"context"
"github.com/arangodb/go-driver"
"github.com/SecurityBrewery/catalyst/bus"
"github.com/SecurityBrewery/catalyst/generated/models"
)
type Hook interface {
PublishAction(action string, context, msg map[string]interface{}) error
PublishUpdate(col, id string) error
}
// BusDatabase
// 1. Save entry to log
// 2. Send update ticket to bus
// 3. Add document to index
type BusDatabase struct {
internal driver.Database
logCollection driver.Collection
bus *bus.Bus
// index *index.Index
}
func NewDatabase(ctx context.Context, internal driver.Database, b *bus.Bus) (*BusDatabase, error) {
logCollection, err := internal.Collection(ctx, LogCollectionName)
if err != nil {
return nil, err
}
return &BusDatabase{
internal: internal,
logCollection: logCollection,
bus: b,
}, nil
}
type OperationType int
const (
Create OperationType = iota
Read = iota
Update = iota
)
type Operation struct {
OperationType OperationType
Ids []driver.DocumentID
Msg string
}
var CreateOperation = &Operation{OperationType: Create}
var ReadOperation = &Operation{OperationType: Read}
func (db BusDatabase) Query(ctx context.Context, query string, vars map[string]interface{}, operation *Operation) (driver.Cursor, *models.LogEntry, error) {
cur, err := db.internal.Query(ctx, query, vars)
if err != nil {
return nil, nil, err
}
var logs *models.LogEntry
switch {
case operation.OperationType == Update:
if err := db.LogAndNotify(ctx, operation.Ids, operation.Msg); err != nil {
return nil, nil, err
}
}
return cur, logs, err
}
func (db BusDatabase) LogAndNotify(ctx context.Context, ids []driver.DocumentID, msg string) error {
var logEntries []*models.LogEntry
for _, i := range ids {
logEntries = append(logEntries, &models.LogEntry{Reference: i.String(), Message: msg})
}
if err := db.LogBatchCreate(ctx, logEntries); err != nil {
return err
}
return db.bus.PublishUpdate(ids)
}
func (db BusDatabase) Remove(ctx context.Context) error {
return db.internal.Remove(ctx)
}
func (db BusDatabase) Collection(ctx context.Context, name string) (driver.Collection, error) {
return db.internal.Collection(ctx, name)
}
type Collection struct {
internal driver.Collection
db *BusDatabase
}
func NewCollection(internal driver.Collection, db *BusDatabase) *Collection {
return &Collection{internal: internal, db: db}
}
func (c Collection) CreateDocument(ctx, newctx context.Context, key string, document interface{}) (driver.DocumentMeta, error) {
meta, err := c.internal.CreateDocument(newctx, &Keyed{Key: key, Doc: document})
if err != nil {
return meta, err
}
err = c.db.LogAndNotify(ctx, []driver.DocumentID{meta.ID}, "Document created")
if err != nil {
return meta, err
}
return meta, nil
}
func (c Collection) CreateEdge(ctx, newctx context.Context, edge *driver.EdgeDocument) (driver.DocumentMeta, error) {
meta, err := c.internal.CreateDocument(newctx, edge)
if err != nil {
return meta, err
}
err = c.db.LogAndNotify(ctx, []driver.DocumentID{meta.ID}, "Document created")
if err != nil {
return meta, err
}
return meta, nil
}
func (c Collection) CreateEdges(ctx context.Context, edges []*driver.EdgeDocument) (driver.DocumentMetaSlice, error) {
metas, errs, err := c.internal.CreateDocuments(ctx, edges)
if err != nil {
return nil, err
}
if errs.FirstNonNil() != nil {
return nil, errs.FirstNonNil()
}
var ids []driver.DocumentID
for _, meta := range metas {
ids = append(ids, meta.ID)
}
err = c.db.LogAndNotify(ctx, ids, "Document created")
if err != nil {
return metas, err
}
return metas, nil
}
func (c Collection) DocumentExists(ctx context.Context, id string) (bool, error) {
return c.internal.DocumentExists(ctx, id)
}
func (c Collection) ReadDocument(ctx context.Context, key string, result interface{}) (driver.DocumentMeta, error) {
return c.internal.ReadDocument(ctx, key, result)
}
func (c Collection) UpdateDocument(ctx context.Context, key string, update interface{}) (driver.DocumentMeta, error) {
meta, err := c.internal.UpdateDocument(ctx, key, update)
if err != nil {
return meta, err
}
return meta, c.db.bus.PublishUpdate([]driver.DocumentID{meta.ID})
}
func (c Collection) ReplaceDocument(ctx context.Context, key string, document interface{}) (driver.DocumentMeta, error) {
meta, err := c.internal.ReplaceDocument(ctx, key, document)
if err != nil {
return meta, err
}
return meta, c.db.bus.PublishUpdate([]driver.DocumentID{meta.ID})
}
func (c Collection) RemoveDocument(ctx context.Context, formatInt string) (driver.DocumentMeta, error) {
return c.internal.RemoveDocument(ctx, formatInt)
}