mirror of
https://github.com/SecurityBrewery/catalyst.git
synced 2026-06-15 13:28:39 +02:00
@@ -1,26 +0,0 @@
|
|||||||
package automation
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/SecurityBrewery/catalyst/bus"
|
|
||||||
"github.com/SecurityBrewery/catalyst/database"
|
|
||||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
|
||||||
"github.com/SecurityBrewery/catalyst/role"
|
|
||||||
)
|
|
||||||
|
|
||||||
func New(apiurl, apikey string, bus *bus.Bus, db *database.Database) error {
|
|
||||||
if err := jobAutomation(jobContext(), apiurl, apikey, bus, db); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return resultAutomation(bus, db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func jobContext() context.Context {
|
|
||||||
// TODO: change roles?
|
|
||||||
bot := &models.UserResponse{ID: "bot", Roles: []string{role.Admin}}
|
|
||||||
return busdb.UserContext(context.Background(), bot)
|
|
||||||
}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
package automation
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
|
|
||||||
"github.com/SecurityBrewery/catalyst/bus"
|
|
||||||
"github.com/SecurityBrewery/catalyst/database"
|
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
func jobAutomation(ctx context.Context, apiurl, apikey string, catalystBus *bus.Bus, db *database.Database) error {
|
|
||||||
return catalystBus.SubscribeJob(func(automationMsg *bus.JobMsg) {
|
|
||||||
job, err := db.JobCreate(ctx, automationMsg.ID, &models.JobForm{
|
|
||||||
Automation: automationMsg.Automation,
|
|
||||||
Payload: automationMsg.Message.Payload,
|
|
||||||
Origin: automationMsg.Origin,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
automation, err := db.AutomationGet(ctx, automationMsg.Automation)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if automation.Script == "" {
|
|
||||||
log.Println("automation is empty")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if automationMsg.Message.Secrets == nil {
|
|
||||||
automationMsg.Message.Secrets = map[string]string{}
|
|
||||||
}
|
|
||||||
automationMsg.Message.Secrets["catalyst_apikey"] = apikey
|
|
||||||
automationMsg.Message.Secrets["catalyst_apiurl"] = apiurl
|
|
||||||
|
|
||||||
scriptMessage, _ := json.Marshal(automationMsg.Message)
|
|
||||||
|
|
||||||
containerID, logs, err := createContainer(ctx, automation.Image, automation.Script, string(scriptMessage))
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := db.JobUpdate(ctx, automationMsg.ID, &models.Job{
|
|
||||||
Automation: job.Automation,
|
|
||||||
Container: &containerID,
|
|
||||||
Origin: job.Origin,
|
|
||||||
Output: job.Output,
|
|
||||||
Log: &logs,
|
|
||||||
Payload: job.Payload,
|
|
||||||
Status: job.Status,
|
|
||||||
}); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var result map[string]interface{}
|
|
||||||
|
|
||||||
stdout, _, err := runDocker(ctx, automationMsg.ID, containerID, db)
|
|
||||||
if err != nil {
|
|
||||||
result = map[string]interface{}{"error": fmt.Sprintf("error running script %s %s", err, string(stdout))}
|
|
||||||
} else {
|
|
||||||
var data map[string]interface{}
|
|
||||||
if err := json.Unmarshal(stdout, &data); err != nil {
|
|
||||||
result = map[string]interface{}{"error": string(stdout)}
|
|
||||||
} else {
|
|
||||||
result = data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := catalystBus.PublishResult(automationMsg.Automation, result, automationMsg.Origin); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := db.JobComplete(ctx, automationMsg.ID, result); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
func getAutomation(automationID string, config *Config) (*models.AutomationResponse, error) {
|
|
||||||
req, err := http.NewRequest(http.MethodGet, config.CatalystAPIUrl+"/automations/"+automationID, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("PRIVATE-TOKEN", config.CatalystAPIKey)
|
|
||||||
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
b, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var automation models.AutomationResponse
|
|
||||||
if err := json.Unmarshal(b, &automation); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &automation, nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package automation
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/SecurityBrewery/catalyst/bus"
|
|
||||||
"github.com/SecurityBrewery/catalyst/database"
|
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
func resultAutomation(catalystBus *bus.Bus, db *database.Database) error {
|
|
||||||
return catalystBus.SubscribeResult(func(resultMsg *bus.ResultMsg) {
|
|
||||||
if resultMsg.Target != nil {
|
|
||||||
ctx := jobContext()
|
|
||||||
switch {
|
|
||||||
case resultMsg.Target.TaskOrigin != nil:
|
|
||||||
if _, err := db.TaskComplete(
|
|
||||||
ctx,
|
|
||||||
resultMsg.Target.TaskOrigin.TicketId,
|
|
||||||
resultMsg.Target.TaskOrigin.PlaybookId,
|
|
||||||
resultMsg.Target.TaskOrigin.TaskId,
|
|
||||||
resultMsg.Data,
|
|
||||||
); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
case resultMsg.Target.ArtifactOrigin != nil:
|
|
||||||
enrichment := &models.EnrichmentForm{
|
|
||||||
Data: resultMsg.Data,
|
|
||||||
Name: resultMsg.Automation,
|
|
||||||
}
|
|
||||||
_, err := db.EnrichArtifact(ctx, resultMsg.Target.ArtifactOrigin.TicketId, resultMsg.Target.ArtifactOrigin.Artifact, enrichment)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
+12
-82
@@ -4,16 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
|
||||||
emitter "github.com/emitter-io/go/v2"
|
emitter "github.com/emitter-io/go/v2"
|
||||||
|
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
channelUpdate = "data"
|
|
||||||
channelJob = "job"
|
|
||||||
channelResult = "result"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bus struct {
|
type Bus struct {
|
||||||
@@ -22,25 +13,13 @@ type Bus struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Host string
|
Host string
|
||||||
Key string
|
Key string
|
||||||
resultBusKey string
|
databaseUpdateBusKey string
|
||||||
jobBusKey string
|
jobBusKey string
|
||||||
dataBusKey string
|
resultBusKey string
|
||||||
APIUrl string
|
requestKey string
|
||||||
}
|
APIUrl string
|
||||||
|
|
||||||
type JobMsg struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Automation string `json:"automation"`
|
|
||||||
Origin *models.Origin `json:"origin"`
|
|
||||||
Message *models.Message `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResultMsg struct {
|
|
||||||
Automation string `json:"automation"`
|
|
||||||
Data map[string]interface{} `json:"data,omitempty"`
|
|
||||||
Target *models.Origin `json:"target"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(c *Config) (*Bus, error) {
|
func New(c *Config) (*Bus, error) {
|
||||||
@@ -51,7 +30,7 @@ func New(c *Config) (*Bus, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.dataBusKey, err = client.GenerateKey(c.Key, channelUpdate+"/", "rwls", 0)
|
c.databaseUpdateBusKey, err = client.GenerateKey(c.Key, channelDatabaseUpdate+"/", "rwls", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -63,30 +42,14 @@ func New(c *Config) (*Bus, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
c.requestKey, err = client.GenerateKey(c.Key, ChannelRequest+"/", "rwls", 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &Bus{config: c, client: client}, err
|
return &Bus{config: c, client: client}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bus) PublishUpdate(ids []driver.DocumentID) error {
|
|
||||||
return b.jsonPublish(ids, channelUpdate, b.config.dataBusKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Bus) PublishJob(id, automation string, payload interface{}, context *models.Context, origin *models.Origin) error {
|
|
||||||
return b.jsonPublish(&JobMsg{
|
|
||||||
ID: id,
|
|
||||||
Automation: automation,
|
|
||||||
Origin: origin,
|
|
||||||
Message: &models.Message{
|
|
||||||
Context: context,
|
|
||||||
Payload: payload,
|
|
||||||
},
|
|
||||||
}, channelJob, b.config.jobBusKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Bus) PublishResult(automation string, data map[string]interface{}, target *models.Origin) error {
|
|
||||||
return b.jsonPublish(&ResultMsg{Automation: automation, Data: data, Target: target}, channelResult, b.config.resultBusKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Bus) jsonPublish(msg interface{}, channel, key string) error {
|
func (b *Bus) jsonPublish(msg interface{}, channel, key string) error {
|
||||||
payload, err := json.Marshal(msg)
|
payload, err := json.Marshal(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -96,39 +59,6 @@ func (b *Bus) jsonPublish(msg interface{}, channel, key string) error {
|
|||||||
return b.client.Publish(key, channel, payload)
|
return b.client.Publish(key, channel, payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bus) SubscribeUpdate(f func(ids []driver.DocumentID)) error {
|
|
||||||
return b.safeSubscribe(b.config.dataBusKey, channelUpdate, func(c *emitter.Client, m emitter.Message) {
|
|
||||||
var msg []driver.DocumentID
|
|
||||||
if err := json.Unmarshal(m.Payload(), &msg); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
go f(msg)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Bus) SubscribeJob(f func(msg *JobMsg)) error {
|
|
||||||
return b.safeSubscribe(b.config.jobBusKey, channelJob, func(c *emitter.Client, m emitter.Message) {
|
|
||||||
var msg JobMsg
|
|
||||||
if err := json.Unmarshal(m.Payload(), &msg); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
go f(&msg)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Bus) SubscribeResult(f func(msg *ResultMsg)) error {
|
|
||||||
return b.safeSubscribe(b.config.resultBusKey, channelResult, func(c *emitter.Client, m emitter.Message) {
|
|
||||||
var msg ResultMsg
|
|
||||||
if err := json.Unmarshal(m.Payload(), &msg); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
go f(&msg)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Bus) safeSubscribe(key, channel string, handler func(c *emitter.Client, m emitter.Message)) error {
|
func (b *Bus) safeSubscribe(key, channel string, handler func(c *emitter.Client, m emitter.Message)) error {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package bus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
emitter "github.com/emitter-io/go/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const channelDatabaseUpdate = "databaseupdate"
|
||||||
|
|
||||||
|
type DatabaseUpdateType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
DatabaseEntryRead DatabaseUpdateType = "read"
|
||||||
|
DatabaseEntryCreated DatabaseUpdateType = "created"
|
||||||
|
DatabaseEntryUpdated DatabaseUpdateType = "updated"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DatabaseUpdateMsg struct {
|
||||||
|
IDs []driver.DocumentID `json:"ids"`
|
||||||
|
Type DatabaseUpdateType `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bus) PublishDatabaseUpdate(ids []driver.DocumentID, databaseUpdateType DatabaseUpdateType) error {
|
||||||
|
return b.jsonPublish(&DatabaseUpdateMsg{
|
||||||
|
IDs: ids,
|
||||||
|
Type: databaseUpdateType,
|
||||||
|
}, channelDatabaseUpdate, b.config.databaseUpdateBusKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bus) SubscribeDatabaseUpdate(f func(msg *DatabaseUpdateMsg)) error {
|
||||||
|
return b.safeSubscribe(b.config.databaseUpdateBusKey, channelDatabaseUpdate, func(c *emitter.Client, m emitter.Message) {
|
||||||
|
var msg DatabaseUpdateMsg
|
||||||
|
if err := json.Unmarshal(m.Payload(), &msg); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go f(&msg)
|
||||||
|
})
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
package bus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
emitter "github.com/emitter-io/go/v2"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
const channelJob = "job"
|
||||||
|
|
||||||
|
type JobMsg struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Automation string `json:"automation"`
|
||||||
|
Origin *models.Origin `json:"origin"`
|
||||||
|
Message *models.Message `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bus) PublishJob(id, automation string, payload interface{}, context *models.Context, origin *models.Origin) error {
|
||||||
|
return b.jsonPublish(&JobMsg{
|
||||||
|
ID: id,
|
||||||
|
Automation: automation,
|
||||||
|
Origin: origin,
|
||||||
|
Message: &models.Message{
|
||||||
|
Context: context,
|
||||||
|
Payload: payload,
|
||||||
|
},
|
||||||
|
}, channelJob, b.config.jobBusKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bus) SubscribeJob(f func(msg *JobMsg)) error {
|
||||||
|
return b.safeSubscribe(b.config.jobBusKey, channelJob, func(c *emitter.Client, m emitter.Message) {
|
||||||
|
var msg JobMsg
|
||||||
|
if err := json.Unmarshal(m.Payload(), &msg); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go f(&msg)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package bus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
emitter "github.com/emitter-io/go/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ChannelRequest = "request"
|
||||||
|
|
||||||
|
type RequestMsg struct {
|
||||||
|
IDs []driver.DocumentID `json:"ids"`
|
||||||
|
Function string `json:"function"`
|
||||||
|
User string `json:"user"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bus) PublishRequest(user, f string, ids []driver.DocumentID) error {
|
||||||
|
return b.jsonPublish(&RequestMsg{
|
||||||
|
User: user,
|
||||||
|
Function: f,
|
||||||
|
IDs: ids,
|
||||||
|
}, ChannelRequest, b.config.requestKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bus) SubscribeRequest(f func(msg *RequestMsg)) error {
|
||||||
|
return b.safeSubscribe(b.config.requestKey, ChannelRequest, func(c *emitter.Client, m emitter.Message) {
|
||||||
|
var msg RequestMsg
|
||||||
|
if err := json.Unmarshal(m.Payload(), &msg); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go f(&msg)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package bus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
emitter "github.com/emitter-io/go/v2"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
const channelResult = "result"
|
||||||
|
|
||||||
|
type ResultMsg struct {
|
||||||
|
Automation string `json:"automation"`
|
||||||
|
Data map[string]interface{} `json:"data,omitempty"`
|
||||||
|
Target *models.Origin `json:"target"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bus) PublishResult(automation string, data map[string]interface{}, target *models.Origin) error {
|
||||||
|
return b.jsonPublish(&ResultMsg{Automation: automation, Data: data, Target: target}, channelResult, b.config.resultBusKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bus) SubscribeResult(f func(msg *ResultMsg)) error {
|
||||||
|
return b.safeSubscribe(b.config.resultBusKey, channelResult, func(c *emitter.Client, m emitter.Message) {
|
||||||
|
var msg ResultMsg
|
||||||
|
if err := json.Unmarshal(m.Payload(), &msg); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go f(&msg)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package busservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
|
"github.com/SecurityBrewery/catalyst/database"
|
||||||
|
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||||
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
|
"github.com/SecurityBrewery/catalyst/role"
|
||||||
|
"github.com/SecurityBrewery/catalyst/time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type busService struct {
|
||||||
|
db *database.Database
|
||||||
|
apiURL string
|
||||||
|
apiKey string
|
||||||
|
catalystBus *bus.Bus
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(apiurl, apikey string, catalystBus *bus.Bus, db *database.Database) error {
|
||||||
|
|
||||||
|
h := &busService{db: db, apiURL: apiurl, apiKey: apikey, catalystBus: catalystBus}
|
||||||
|
|
||||||
|
if err := catalystBus.SubscribeRequest(h.logRequest); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := catalystBus.SubscribeResult(h.handleResult); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := catalystBus.SubscribeJob(h.handleJob); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func busContext() context.Context {
|
||||||
|
// TODO: change roles?
|
||||||
|
bot := &models.UserResponse{ID: "bot", Roles: []string{role.Admin}}
|
||||||
|
return busdb.UserContext(context.Background(), bot)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *busService) logRequest(msg *bus.RequestMsg) {
|
||||||
|
var logEntries []*models.LogEntry
|
||||||
|
for _, i := range msg.IDs {
|
||||||
|
logEntries = append(logEntries, &models.LogEntry{
|
||||||
|
Type: bus.ChannelRequest,
|
||||||
|
Reference: i.String(),
|
||||||
|
Creator: msg.User,
|
||||||
|
Message: msg.Function,
|
||||||
|
Created: time.Now().UTC(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.db.LogBatchCreate(busContext(), logEntries); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package automation
|
package busservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package busservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *busService) handleJob(automationMsg *bus.JobMsg) {
|
||||||
|
ctx := busContext()
|
||||||
|
|
||||||
|
job, err := h.db.JobCreate(ctx, automationMsg.ID, &models.JobForm{
|
||||||
|
Automation: automationMsg.Automation,
|
||||||
|
Payload: automationMsg.Message.Payload,
|
||||||
|
Origin: automationMsg.Origin,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
automation, err := h.db.AutomationGet(ctx, automationMsg.Automation)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if automation.Script == "" {
|
||||||
|
log.Println("automation is empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if automationMsg.Message.Secrets == nil {
|
||||||
|
automationMsg.Message.Secrets = map[string]string{}
|
||||||
|
}
|
||||||
|
automationMsg.Message.Secrets["catalyst_apikey"] = h.apiKey
|
||||||
|
automationMsg.Message.Secrets["catalyst_apiurl"] = h.apiURL
|
||||||
|
|
||||||
|
scriptMessage, _ := json.Marshal(automationMsg.Message)
|
||||||
|
|
||||||
|
containerID, logs, err := createContainer(ctx, automation.Image, automation.Script, string(scriptMessage))
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := h.db.JobUpdate(ctx, automationMsg.ID, &models.Job{
|
||||||
|
Automation: job.Automation,
|
||||||
|
Container: &containerID,
|
||||||
|
Origin: job.Origin,
|
||||||
|
Output: job.Output,
|
||||||
|
Log: &logs,
|
||||||
|
Payload: job.Payload,
|
||||||
|
Status: job.Status,
|
||||||
|
}); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var result map[string]interface{}
|
||||||
|
|
||||||
|
stdout, _, err := runDocker(ctx, automationMsg.ID, containerID, h.db)
|
||||||
|
if err != nil {
|
||||||
|
result = map[string]interface{}{"error": fmt.Sprintf("error running script %s %s", err, string(stdout))}
|
||||||
|
} else {
|
||||||
|
var data map[string]interface{}
|
||||||
|
if err := json.Unmarshal(stdout, &data); err != nil {
|
||||||
|
result = map[string]interface{}{"error": string(stdout)}
|
||||||
|
} else {
|
||||||
|
result = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.catalystBus.PublishResult(automationMsg.Automation, result, automationMsg.Origin); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.db.JobComplete(ctx, automationMsg.ID, result); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func getAutomation(automationID string, config *Config) (*models.AutomationResponse, error) {
|
||||||
|
req, err := http.NewRequest(http.MethodGet, config.CatalystAPIUrl+"/automations/"+automationID, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("PRIVATE-TOKEN", config.CatalystAPIKey)
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
b, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var automation models.AutomationResponse
|
||||||
|
if err := json.Unmarshal(b, &automation); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &automation, nil
|
||||||
|
}
|
||||||
|
*/
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package busservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *busService) handleResult(resultMsg *bus.ResultMsg) {
|
||||||
|
if resultMsg.Target != nil {
|
||||||
|
ctx := busContext()
|
||||||
|
switch {
|
||||||
|
case resultMsg.Target.TaskOrigin != nil:
|
||||||
|
if _, err := h.db.TaskComplete(
|
||||||
|
ctx,
|
||||||
|
resultMsg.Target.TaskOrigin.TicketId,
|
||||||
|
resultMsg.Target.TaskOrigin.PlaybookId,
|
||||||
|
resultMsg.Target.TaskOrigin.TaskId,
|
||||||
|
resultMsg.Data,
|
||||||
|
); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
case resultMsg.Target.ArtifactOrigin != nil:
|
||||||
|
enrichment := &models.EnrichmentForm{
|
||||||
|
Data: resultMsg.Data,
|
||||||
|
Name: resultMsg.Automation,
|
||||||
|
}
|
||||||
|
_, err := h.db.EnrichArtifact(ctx, resultMsg.Target.ArtifactOrigin.TicketId, resultMsg.Target.ArtifactOrigin.Artifact, enrichment)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
"github.com/SecurityBrewery/catalyst/time"
|
"github.com/SecurityBrewery/catalyst/time"
|
||||||
@@ -60,11 +61,10 @@ func (db *Database) ArtifactUpdate(ctx context.Context, id int64, name string, a
|
|||||||
"name": name,
|
"name": name,
|
||||||
"artifact": artifact,
|
"artifact": artifact,
|
||||||
}, ticketFilterVars), &busdb.Operation{
|
}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||||
},
|
},
|
||||||
Msg: fmt.Sprintf("Update artifact %s", name),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,10 +92,9 @@ func (db *Database) EnrichArtifact(ctx context.Context, id int64, name string, e
|
|||||||
"enrichmentname": enrichment.Name,
|
"enrichmentname": enrichment.Name,
|
||||||
"enrichment": enrichment,
|
"enrichment": enrichment,
|
||||||
}, ticketFilterVars), &busdb.Operation{
|
}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||||
},
|
},
|
||||||
Msg: fmt.Sprintf("Run %s on artifact", enrichment.Name),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-33
@@ -33,22 +33,13 @@ func NewDatabase(ctx context.Context, internal driver.Database, b *bus.Bus) (*Bu
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type OperationType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
Create OperationType = iota
|
|
||||||
Read = iota
|
|
||||||
Update = iota
|
|
||||||
)
|
|
||||||
|
|
||||||
type Operation struct {
|
type Operation struct {
|
||||||
OperationType OperationType
|
Type bus.DatabaseUpdateType
|
||||||
Ids []driver.DocumentID
|
Ids []driver.DocumentID
|
||||||
Msg string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var CreateOperation = &Operation{OperationType: Create}
|
var CreateOperation = &Operation{Type: bus.DatabaseEntryCreated}
|
||||||
var ReadOperation = &Operation{OperationType: Read}
|
var ReadOperation = &Operation{Type: bus.DatabaseEntryRead}
|
||||||
|
|
||||||
func (db BusDatabase) Query(ctx context.Context, query string, vars map[string]interface{}, operation *Operation) (driver.Cursor, *models.LogEntry, error) {
|
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)
|
cur, err := db.internal.Query(ctx, query, vars)
|
||||||
@@ -59,8 +50,8 @@ func (db BusDatabase) Query(ctx context.Context, query string, vars map[string]i
|
|||||||
var logs *models.LogEntry
|
var logs *models.LogEntry
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case operation.OperationType == Update:
|
case operation.Type == bus.DatabaseEntryCreated, operation.Type == bus.DatabaseEntryUpdated:
|
||||||
if err := db.LogAndNotify(ctx, operation.Ids, operation.Msg); err != nil {
|
if err := db.bus.PublishDatabaseUpdate(operation.Ids, operation.Type); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,19 +59,6 @@ func (db BusDatabase) Query(ctx context.Context, query string, vars map[string]i
|
|||||||
return cur, logs, 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 {
|
func (db BusDatabase) Remove(ctx context.Context) error {
|
||||||
return db.internal.Remove(ctx)
|
return db.internal.Remove(ctx)
|
||||||
}
|
}
|
||||||
@@ -104,7 +82,7 @@ func (c Collection) CreateDocument(ctx, newctx context.Context, key string, docu
|
|||||||
return meta, err
|
return meta, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.db.LogAndNotify(ctx, []driver.DocumentID{meta.ID}, "Document created")
|
err = c.db.bus.PublishDatabaseUpdate([]driver.DocumentID{meta.ID}, bus.DatabaseEntryCreated)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return meta, err
|
return meta, err
|
||||||
}
|
}
|
||||||
@@ -117,7 +95,7 @@ func (c Collection) CreateEdge(ctx, newctx context.Context, edge *driver.EdgeDoc
|
|||||||
return meta, err
|
return meta, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.db.LogAndNotify(ctx, []driver.DocumentID{meta.ID}, "Document created")
|
err = c.db.bus.PublishDatabaseUpdate([]driver.DocumentID{meta.ID}, bus.DatabaseEntryCreated)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return meta, err
|
return meta, err
|
||||||
}
|
}
|
||||||
@@ -138,7 +116,7 @@ func (c Collection) CreateEdges(ctx context.Context, edges []*driver.EdgeDocumen
|
|||||||
ids = append(ids, meta.ID)
|
ids = append(ids, meta.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.db.LogAndNotify(ctx, ids, "Document created")
|
err = c.db.bus.PublishDatabaseUpdate(ids, bus.DatabaseEntryCreated)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return metas, err
|
return metas, err
|
||||||
}
|
}
|
||||||
@@ -160,7 +138,7 @@ func (c Collection) UpdateDocument(ctx context.Context, key string, update inter
|
|||||||
return meta, err
|
return meta, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return meta, c.db.bus.PublishUpdate([]driver.DocumentID{meta.ID})
|
return meta, c.db.bus.PublishDatabaseUpdate([]driver.DocumentID{meta.ID}, bus.DatabaseEntryUpdated)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Collection) ReplaceDocument(ctx context.Context, key string, document interface{}) (driver.DocumentMeta, error) {
|
func (c Collection) ReplaceDocument(ctx context.Context, key string, document interface{}) (driver.DocumentMeta, error) {
|
||||||
@@ -169,7 +147,7 @@ func (c Collection) ReplaceDocument(ctx context.Context, key string, document in
|
|||||||
return meta, err
|
return meta, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return meta, c.db.bus.PublishUpdate([]driver.DocumentID{meta.ID})
|
return meta, c.db.bus.PublishDatabaseUpdate([]driver.DocumentID{meta.ID}, bus.DatabaseEntryUpdated)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Collection) RemoveDocument(ctx context.Context, formatInt string) (driver.DocumentMeta, error) {
|
func (c Collection) RemoveDocument(ctx context.Context, formatInt string) (driver.DocumentMeta, error) {
|
||||||
|
|||||||
+14
-20
@@ -3,6 +3,8 @@ package busdb
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
|
|
||||||
@@ -12,15 +14,16 @@ import (
|
|||||||
|
|
||||||
const LogCollectionName = "logs"
|
const LogCollectionName = "logs"
|
||||||
|
|
||||||
func (db *BusDatabase) LogCreate(ctx context.Context, reference, message string) (*models.LogEntry, error) {
|
func (db *BusDatabase) LogCreate(ctx context.Context, logType, reference, message string) (*models.LogEntry, error) {
|
||||||
user, ok := UserFromContext(ctx)
|
user, ok := UserFromContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("no user in context")
|
return nil, errors.New("no user in context")
|
||||||
}
|
}
|
||||||
|
|
||||||
logentry := &models.LogEntry{
|
logentry := &models.LogEntry{
|
||||||
|
Type: logType,
|
||||||
Reference: reference,
|
Reference: reference,
|
||||||
Created: time.Now(),
|
Created: time.Now().UTC(),
|
||||||
Creator: user.ID,
|
Creator: user.ID,
|
||||||
Message: message,
|
Message: message,
|
||||||
}
|
}
|
||||||
@@ -31,27 +34,18 @@ func (db *BusDatabase) LogCreate(ctx context.Context, reference, message string)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &doc, db.bus.PublishUpdate([]driver.DocumentID{driver.DocumentID(logentry.Reference)})
|
return &doc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *BusDatabase) LogBatchCreate(ctx context.Context, logEntryForms []*models.LogEntry) error {
|
func (db *BusDatabase) LogBatchCreate(ctx context.Context, logentries []*models.LogEntry) error {
|
||||||
user, ok := UserFromContext(ctx)
|
|
||||||
if !ok {
|
|
||||||
return errors.New("no user in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
var ids []driver.DocumentID
|
var ids []driver.DocumentID
|
||||||
var logentries []*models.LogEntry
|
for _, entry := range logentries {
|
||||||
for _, logEntryForm := range logEntryForms {
|
if strings.HasPrefix(entry.Reference, "tickets/") {
|
||||||
logentry := &models.LogEntry{
|
ids = append(ids, driver.DocumentID(entry.Reference))
|
||||||
Reference: logEntryForm.Reference,
|
|
||||||
Created: time.Now(),
|
|
||||||
Creator: user.ID,
|
|
||||||
Message: logEntryForm.Message,
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
logentries = append(logentries, logentry)
|
if ids != nil {
|
||||||
ids = append(ids, driver.DocumentID(logentry.Reference))
|
go db.bus.PublishDatabaseUpdate(ids, bus.DatabaseEntryCreated)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, errs, err := db.logCollection.CreateDocuments(ctx, logentries)
|
_, errs, err := db.logCollection.CreateDocuments(ctx, logentries)
|
||||||
@@ -63,7 +57,7 @@ func (db *BusDatabase) LogBatchCreate(ctx context.Context, logEntryForms []*mode
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return db.bus.PublishUpdate(ids)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *BusDatabase) LogList(ctx context.Context, reference string) ([]*models.LogEntry, error) {
|
func (db *BusDatabase) LogList(ctx context.Context, reference string) ([]*models.LogEntry, error) {
|
||||||
|
|||||||
+3
-4
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/xeipuuv/gojsonschema"
|
"github.com/xeipuuv/gojsonschema"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
"github.com/SecurityBrewery/catalyst/caql"
|
"github.com/SecurityBrewery/catalyst/caql"
|
||||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
@@ -144,11 +145,10 @@ func (db *Database) JobLogAppend(ctx context.Context, id string, logLine string)
|
|||||||
"ID": id,
|
"ID": id,
|
||||||
"logline": logLine,
|
"logline": logLine,
|
||||||
}, &busdb.Operation{
|
}, &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(fmt.Sprintf("%s/%s", JobCollectionName, id)),
|
driver.DocumentID(fmt.Sprintf("%s/%s", JobCollectionName, id)),
|
||||||
},
|
},
|
||||||
Msg: fmt.Sprintf("Append logline"),
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -166,11 +166,10 @@ func (db *Database) JobComplete(ctx context.Context, id string, out interface{})
|
|||||||
"ID": id,
|
"ID": id,
|
||||||
"out": out,
|
"out": out,
|
||||||
}, &busdb.Operation{
|
}, &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(fmt.Sprintf("%s/%s", JobCollectionName, id)),
|
driver.DocumentID(fmt.Sprintf("%s/%s", JobCollectionName, id)),
|
||||||
},
|
},
|
||||||
Msg: fmt.Sprintf("Set output"),
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,12 +38,11 @@ func (db *Database) RelatedRemove(ctx context.Context, id, id2 int64) error {
|
|||||||
"id": driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id))),
|
"id": driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id))),
|
||||||
"id2": driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id2))),
|
"id2": driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id2))),
|
||||||
}, &busdb.Operation{
|
}, &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id))),
|
driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id))),
|
||||||
driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id2))),
|
driver.DocumentID(TicketCollectionName + "/" + strconv.Itoa(int(id2))),
|
||||||
},
|
},
|
||||||
Msg: "Removed ticket/artifact relation",
|
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-7
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
"github.com/xeipuuv/gojsonschema"
|
"github.com/xeipuuv/gojsonschema"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
"github.com/SecurityBrewery/catalyst/caql"
|
"github.com/SecurityBrewery/catalyst/caql"
|
||||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
@@ -133,7 +134,7 @@ func toTicketSimpleResponse(key string, ticket *models.Ticket) (*models.TicketSi
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toTicketWithTickets(ticketResponse *models.TicketResponse, tickets []*models.TicketSimpleResponse) *models.TicketWithTickets {
|
func toTicketWithTickets(ticketResponse *models.TicketResponse, tickets []*models.TicketSimpleResponse, logs []*models.LogEntry) *models.TicketWithTickets {
|
||||||
return &models.TicketWithTickets{
|
return &models.TicketWithTickets{
|
||||||
Artifacts: ticketResponse.Artifacts,
|
Artifacts: ticketResponse.Artifacts,
|
||||||
Comments: ticketResponse.Comments,
|
Comments: ticketResponse.Comments,
|
||||||
@@ -152,6 +153,7 @@ func toTicketWithTickets(ticketResponse *models.TicketResponse, tickets []*model
|
|||||||
Type: ticketResponse.Type,
|
Type: ticketResponse.Type,
|
||||||
Write: ticketResponse.Write,
|
Write: ticketResponse.Write,
|
||||||
|
|
||||||
|
Logs: logs,
|
||||||
Tickets: tickets,
|
Tickets: tickets,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,9 +246,8 @@ func (db *Database) TicketBatchCreate(ctx context.Context, ticketForms []*models
|
|||||||
for _, apiTicket := range apiTickets {
|
for _, apiTicket := range apiTickets {
|
||||||
ids = append(ids, driver.NewDocumentID(TicketCollectionName, fmt.Sprint(apiTicket.ID)))
|
ids = append(ids, driver.NewDocumentID(TicketCollectionName, fmt.Sprint(apiTicket.ID)))
|
||||||
}
|
}
|
||||||
if err := db.BusDatabase.LogAndNotify(ctx, ids, "Ticket created"); err != nil {
|
|
||||||
return nil, err
|
go db.bus.PublishDatabaseUpdate(ids, bus.DatabaseEntryUpdated)
|
||||||
}
|
|
||||||
|
|
||||||
ticketResponses, err := toTicketResponses(apiTickets)
|
ticketResponses, err := toTicketResponses(apiTickets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -405,7 +406,12 @@ func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query st
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return toTicketWithTickets(ticketResponse, tickets), nil
|
logs, err := db.LogList(ctx, fmt.Sprintf("%s/%d", TicketCollectionName, ticketID))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return toTicketWithTickets(ticketResponse, tickets, logs), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *Database) TicketUpdate(ctx context.Context, ticketID int64, ticket *models.Ticket) (*models.TicketWithTickets, error) {
|
func (db *Database) TicketUpdate(ctx context.Context, ticketID int64, ticket *models.Ticket) (*models.TicketWithTickets, error) {
|
||||||
@@ -420,10 +426,9 @@ func (db *Database) TicketUpdate(ctx context.Context, ticketID int64, ticket *mo
|
|||||||
RETURN NEW`
|
RETURN NEW`
|
||||||
ticket.Modified = time.Now().UTC() // TODO make setable?
|
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]interface{}{"ticket": ticket}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update, Ids: []driver.DocumentID{
|
Type: bus.DatabaseEntryUpdated, Ids: []driver.DocumentID{
|
||||||
driver.NewDocumentID(TicketCollectionName, strconv.FormatInt(ticketID, 10)),
|
driver.NewDocumentID(TicketCollectionName, strconv.FormatInt(ticketID, 10)),
|
||||||
},
|
},
|
||||||
Msg: "Ticket updated",
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-18
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/iancoleman/strcase"
|
"github.com/iancoleman/strcase"
|
||||||
"github.com/mingrammer/commonregex"
|
"github.com/mingrammer/commonregex"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
"github.com/SecurityBrewery/catalyst/pointer"
|
"github.com/SecurityBrewery/catalyst/pointer"
|
||||||
@@ -34,11 +35,10 @@ func (db *Database) AddArtifact(ctx context.Context, id int64, artifact *models.
|
|||||||
UPDATE d WITH { "modified": @now, "artifacts": PUSH(NOT_NULL(d.artifacts, []), @artifact) } IN @@collection
|
UPDATE d WITH { "modified": @now, "artifacts": PUSH(NOT_NULL(d.artifacts, []), @artifact) } IN @@collection
|
||||||
RETURN NEW`
|
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]interface{}{"artifact": artifact, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||||
},
|
},
|
||||||
Msg: "Add artifact",
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,11 +74,10 @@ func (db *Database) RemoveArtifact(ctx context.Context, id int64, name string) (
|
|||||||
UPDATE d WITH { "modified": @now, "artifacts": newartifacts } IN @@collection
|
UPDATE d WITH { "modified": @now, "artifacts": newartifacts } IN @@collection
|
||||||
RETURN NEW`
|
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]interface{}{"name": name, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||||
},
|
},
|
||||||
Msg: "Remove artifact",
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,11 +92,10 @@ func (db *Database) SetTemplate(ctx context.Context, id int64, schema string) (*
|
|||||||
UPDATE d WITH { "schema": @schema } IN @@collection
|
UPDATE d WITH { "schema": @schema } IN @@collection
|
||||||
RETURN NEW`
|
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]interface{}{"schema": schema}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||||
},
|
},
|
||||||
Msg: "Set Template",
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,11 +123,10 @@ func (db *Database) AddComment(ctx context.Context, id int64, comment *models.Co
|
|||||||
UPDATE d WITH { "modified": @now, "comments": PUSH(NOT_NULL(d.comments, []), @comment) } IN @@collection
|
UPDATE d WITH { "modified": @now, "comments": PUSH(NOT_NULL(d.comments, []), @comment) } IN @@collection
|
||||||
RETURN NEW`
|
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]interface{}{"comment": comment, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||||
},
|
},
|
||||||
Msg: "Add comment",
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,11 +141,10 @@ func (db *Database) RemoveComment(ctx context.Context, id int64, commentID int64
|
|||||||
UPDATE d WITH { "modified": @now, "comments": REMOVE_NTH(d.comments, @commentID) } IN @@collection
|
UPDATE d WITH { "modified": @now, "comments": REMOVE_NTH(d.comments, @commentID) } IN @@collection
|
||||||
RETURN NEW`
|
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]interface{}{"commentID": commentID, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||||
},
|
},
|
||||||
Msg: "Remove comment",
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,11 +159,10 @@ func (db *Database) SetReferences(ctx context.Context, id int64, references []*m
|
|||||||
UPDATE d WITH { "modified": @now, "references": @references } IN @@collection
|
UPDATE d WITH { "modified": @now, "references": @references } IN @@collection
|
||||||
RETURN NEW`
|
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]interface{}{"references": references, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||||
},
|
},
|
||||||
Msg: "Changed references",
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,11 +177,10 @@ func (db *Database) LinkFiles(ctx context.Context, id int64, files []*models.Fil
|
|||||||
UPDATE d WITH { "modified": @now, "files": @files } IN @@collection
|
UPDATE d WITH { "modified": @now, "files": @files } IN @@collection
|
||||||
RETURN NEW`
|
RETURN NEW`
|
||||||
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{"files": files, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
return db.ticketGetQuery(ctx, id, query, mergeMaps(map[string]interface{}{"files": files, "now": time.Now().UTC()}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
driver.DocumentID(fmt.Sprintf("%s/%d", TicketCollectionName, id)),
|
||||||
},
|
},
|
||||||
Msg: "Linked files",
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,11 +218,10 @@ func (db *Database) AddTicketPlaybook(ctx context.Context, id int64, playbookTem
|
|||||||
"playbookID": findName(parentTicket.Playbooks, playbookID),
|
"playbookID": findName(parentTicket.Playbooks, playbookID),
|
||||||
"now": time.Now().UTC(),
|
"now": time.Now().UTC(),
|
||||||
}, ticketFilterVars), &busdb.Operation{
|
}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.NewDocumentID(TicketCollectionName, fmt.Sprintf("%d", id)),
|
driver.NewDocumentID(TicketCollectionName, fmt.Sprintf("%d", id)),
|
||||||
},
|
},
|
||||||
Msg: "Added playbook",
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -284,10 +277,9 @@ func (db *Database) RemoveTicketPlaybook(ctx context.Context, id int64, playbook
|
|||||||
"playbookID": playbookID,
|
"playbookID": playbookID,
|
||||||
"now": time.Now().UTC(),
|
"now": time.Now().UTC(),
|
||||||
}, ticketFilterVars), &busdb.Operation{
|
}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.NewDocumentID(TicketCollectionName, fmt.Sprintf("%d", id)),
|
driver.NewDocumentID(TicketCollectionName, fmt.Sprintf("%d", id)),
|
||||||
},
|
},
|
||||||
Msg: fmt.Sprintf("Removed playbook %s", playbookID),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
"github.com/SecurityBrewery/catalyst/time"
|
"github.com/SecurityBrewery/catalyst/time"
|
||||||
@@ -74,11 +75,10 @@ func (db *Database) TaskComplete(ctx context.Context, id int64, playbookID strin
|
|||||||
"closed": time.Now().UTC(),
|
"closed": time.Now().UTC(),
|
||||||
"now": time.Now().UTC(),
|
"now": time.Now().UTC(),
|
||||||
}, ticketFilterVars), &busdb.Operation{
|
}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.NewDocumentID(TicketCollectionName, fmt.Sprintf("%d", id)),
|
driver.NewDocumentID(TicketCollectionName, fmt.Sprintf("%d", id)),
|
||||||
},
|
},
|
||||||
Msg: fmt.Sprintf("Completed task %s in playbook %s", taskID, playbookID),
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -136,11 +136,10 @@ func (db *Database) TaskUpdate(ctx context.Context, id int64, playbookID string,
|
|||||||
"task": task,
|
"task": task,
|
||||||
"now": time.Now().UTC(),
|
"now": time.Now().UTC(),
|
||||||
}, ticketFilterVars), &busdb.Operation{
|
}, ticketFilterVars), &busdb.Operation{
|
||||||
OperationType: busdb.Update,
|
Type: bus.DatabaseEntryUpdated,
|
||||||
Ids: []driver.DocumentID{
|
Ids: []driver.DocumentID{
|
||||||
driver.NewDocumentID(TicketCollectionName, fmt.Sprintf("%d", id)),
|
driver.NewDocumentID(TicketCollectionName, fmt.Sprintf("%d", id)),
|
||||||
},
|
},
|
||||||
Msg: fmt.Sprintf("Saved task %s in playbook %s", taskID, playbookID),
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -16,14 +16,15 @@ paths:
|
|||||||
schema: { type: array, items: { $ref: "#/definitions/LogEntry" } }
|
schema: { type: array, items: { $ref: "#/definitions/LogEntry" } }
|
||||||
examples:
|
examples:
|
||||||
test:
|
test:
|
||||||
- { "created": "2021-12-12T12:12:12.000000012Z","creator": "bob","reference": "tickets/294511","message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim." }
|
- { type: "manual", "created": "2021-12-12T12:12:12.000000012Z","creator": "bob","reference": "tickets/294511","message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim." }
|
||||||
security: [ { roles: [ "log:read" ] } ]
|
security: [ { roles: [ "log:read" ] } ]
|
||||||
|
|
||||||
definitions:
|
definitions:
|
||||||
LogEntry:
|
LogEntry:
|
||||||
type: object
|
type: object
|
||||||
required: [ reference, creator, created, message ]
|
required: [ type, reference, creator, created, message ]
|
||||||
properties:
|
properties:
|
||||||
|
type: { type: string }
|
||||||
reference: { type: string }
|
reference: { type: string }
|
||||||
creator: { type: string }
|
creator: { type: string }
|
||||||
created: { type: string, format: "date-time" }
|
created: { type: string, format: "date-time" }
|
||||||
|
|||||||
@@ -1037,6 +1037,8 @@ definitions:
|
|||||||
comments: { type: array, items: { $ref: '#/definitions/Comment' } }
|
comments: { type: array, items: { $ref: '#/definitions/Comment' } }
|
||||||
artifacts: { type: array, items: { $ref: "#/definitions/Artifact" } }
|
artifacts: { type: array, items: { $ref: "#/definitions/Artifact" } }
|
||||||
|
|
||||||
|
logs: { type: array, items: { $ref: '#/definitions/LogEntry' } }
|
||||||
|
|
||||||
created: { type: string, format: "date-time", example: "1985-04-12T23:20:50.52Z" }
|
created: { type: string, format: "date-time", example: "1985-04-12T23:20:50.52Z" }
|
||||||
modified: { type: string, format: "date-time", example: "1985-04-12T23:20:50.52Z" }
|
modified: { type: string, format: "date-time", example: "1985-04-12T23:20:50.52Z" }
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -723,7 +723,8 @@
|
|||||||
"created" : "2021-12-12T12:12:12.000+0000",
|
"created" : "2021-12-12T12:12:12.000+0000",
|
||||||
"creator" : "bob",
|
"creator" : "bob",
|
||||||
"message" : "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.",
|
"message" : "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.",
|
||||||
"reference" : "tickets/294511"
|
"reference" : "tickets/294511",
|
||||||
|
"type" : "manual"
|
||||||
} ]
|
} ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -5418,9 +5419,12 @@
|
|||||||
},
|
},
|
||||||
"reference" : {
|
"reference" : {
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
|
},
|
||||||
|
"type" : {
|
||||||
|
"type" : "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required" : [ "created", "creator", "message", "reference" ],
|
"required" : [ "created", "creator", "message", "reference", "type" ],
|
||||||
"type" : "object"
|
"type" : "object"
|
||||||
},
|
},
|
||||||
"Message" : {
|
"Message" : {
|
||||||
@@ -6445,6 +6449,12 @@
|
|||||||
"format" : "int64",
|
"format" : "int64",
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
|
"logs" : {
|
||||||
|
"items" : {
|
||||||
|
"$ref" : "#/components/schemas/LogEntry"
|
||||||
|
},
|
||||||
|
"type" : "array"
|
||||||
|
},
|
||||||
"modified" : {
|
"modified" : {
|
||||||
"format" : "date-time",
|
"format" : "date-time",
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
|
|||||||
@@ -312,7 +312,10 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
reference:
|
reference:
|
||||||
type: string
|
type: string
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
required:
|
required:
|
||||||
|
- type
|
||||||
- reference
|
- reference
|
||||||
- creator
|
- creator
|
||||||
- created
|
- created
|
||||||
@@ -1152,6 +1155,10 @@ definitions:
|
|||||||
example: 123
|
example: 123
|
||||||
format: int64
|
format: int64
|
||||||
type: integer
|
type: integer
|
||||||
|
logs:
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/LogEntry'
|
||||||
|
type: array
|
||||||
modified:
|
modified:
|
||||||
example: 1985-04-12T23:20:50.52Z
|
example: 1985-04-12T23:20:50.52Z
|
||||||
format: date-time
|
format: date-time
|
||||||
@@ -1945,6 +1952,7 @@ paths:
|
|||||||
combine wish influence income guess run stand. Charge limit crime
|
combine wish influence income guess run stand. Charge limit crime
|
||||||
ignore statement foundation study issue stop claim.
|
ignore statement foundation study issue stop claim.
|
||||||
reference: tickets/294511
|
reference: tickets/294511
|
||||||
|
type: manual
|
||||||
schema:
|
schema:
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/LogEntry'
|
$ref: '#/definitions/LogEntry'
|
||||||
|
|||||||
@@ -491,7 +491,8 @@
|
|||||||
"created" : "2021-12-12T12:12:12.000+0000",
|
"created" : "2021-12-12T12:12:12.000+0000",
|
||||||
"creator" : "bob",
|
"creator" : "bob",
|
||||||
"message" : "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.",
|
"message" : "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.",
|
||||||
"reference" : "tickets/294511"
|
"reference" : "tickets/294511",
|
||||||
|
"type" : "manual"
|
||||||
} ]
|
} ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -4905,9 +4906,12 @@
|
|||||||
},
|
},
|
||||||
"reference" : {
|
"reference" : {
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
|
},
|
||||||
|
"type" : {
|
||||||
|
"type" : "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required" : [ "created", "creator", "message", "reference" ],
|
"required" : [ "created", "creator", "message", "reference", "type" ],
|
||||||
"type" : "object"
|
"type" : "object"
|
||||||
},
|
},
|
||||||
"Message" : {
|
"Message" : {
|
||||||
@@ -5866,6 +5870,12 @@
|
|||||||
"format" : "int64",
|
"format" : "int64",
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
|
"logs" : {
|
||||||
|
"items" : {
|
||||||
|
"$ref" : "#/components/schemas/LogEntry"
|
||||||
|
},
|
||||||
|
"type" : "array"
|
||||||
|
},
|
||||||
"modified" : {
|
"modified" : {
|
||||||
"format" : "date-time",
|
"format" : "date-time",
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
|
|||||||
@@ -247,7 +247,10 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
reference:
|
reference:
|
||||||
type: string
|
type: string
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
required:
|
required:
|
||||||
|
- type
|
||||||
- reference
|
- reference
|
||||||
- creator
|
- creator
|
||||||
- created
|
- created
|
||||||
@@ -1033,6 +1036,10 @@ definitions:
|
|||||||
example: 123
|
example: 123
|
||||||
format: int64
|
format: int64
|
||||||
type: integer
|
type: integer
|
||||||
|
logs:
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/LogEntry'
|
||||||
|
type: array
|
||||||
modified:
|
modified:
|
||||||
example: 1985-04-12T23:20:50.52Z
|
example: 1985-04-12T23:20:50.52Z
|
||||||
format: date-time
|
format: date-time
|
||||||
@@ -1674,6 +1681,7 @@ paths:
|
|||||||
combine wish influence income guess run stand. Charge limit crime
|
combine wish influence income guess run stand. Charge limit crime
|
||||||
ignore statement foundation study issue stop claim.
|
ignore statement foundation study issue stop claim.
|
||||||
reference: tickets/294511
|
reference: tickets/294511
|
||||||
|
type: manual
|
||||||
schema:
|
schema:
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/LogEntry'
|
$ref: '#/definitions/LogEntry'
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ func init() {
|
|||||||
gojsonschema.NewStringLoader(`{"type":"object","required":["automation","running","status"],"x-embed":"","properties":{"automation":{"type":"string"},"container":{"type":"string"},"log":{"type":"string"},"origin":{"$ref":"#/definitions/Origin"},"output":{"type":"object"},"payload":{},"running":{"type":"boolean"},"status":{"type":"string"}},"$id":"#/definitions/Job"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","required":["automation","running","status"],"x-embed":"","properties":{"automation":{"type":"string"},"container":{"type":"string"},"log":{"type":"string"},"origin":{"$ref":"#/definitions/Origin"},"output":{"type":"object"},"payload":{},"running":{"type":"boolean"},"status":{"type":"string"}},"$id":"#/definitions/Job"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","required":["automation"],"x-embed":"","properties":{"automation":{"type":"string"},"origin":{"$ref":"#/definitions/Origin"},"payload":{}},"$id":"#/definitions/JobForm"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","required":["automation"],"x-embed":"","properties":{"automation":{"type":"string"},"origin":{"$ref":"#/definitions/Origin"},"payload":{}},"$id":"#/definitions/JobForm"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","required":["id","automation","status"],"x-embed":"","properties":{"automation":{"type":"string"},"container":{"type":"string"},"id":{"type":"string"},"log":{"type":"string"},"origin":{"$ref":"#/definitions/Origin"},"output":{"type":"object"},"payload":{},"status":{"type":"string"}},"$id":"#/definitions/JobResponse"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","required":["id","automation","status"],"x-embed":"","properties":{"automation":{"type":"string"},"container":{"type":"string"},"id":{"type":"string"},"log":{"type":"string"},"origin":{"$ref":"#/definitions/Origin"},"output":{"type":"object"},"payload":{},"status":{"type":"string"}},"$id":"#/definitions/JobResponse"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","required":["reference","creator","created","message"],"x-embed":"","properties":{"created":{"format":"date-time","type":"string"},"creator":{"type":"string"},"message":{"type":"string"},"reference":{"type":"string"}},"$id":"#/definitions/LogEntry"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","required":["type","reference","creator","created","message"],"x-embed":"","properties":{"created":{"format":"date-time","type":"string"},"creator":{"type":"string"},"message":{"type":"string"},"reference":{"type":"string"},"type":{"type":"string"}},"$id":"#/definitions/LogEntry"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","x-embed":"","properties":{"context":{"$ref":"#/definitions/Context"},"payload":{"type":"object"},"secrets":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"#/definitions/Message"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","x-embed":"","properties":{"context":{"$ref":"#/definitions/Context"},"payload":{"type":"object"},"secrets":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"#/definitions/Message"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","required":["id","blocked","roles"],"x-embed":"","properties":{"blocked":{"type":"boolean"},"id":{"type":"string"},"roles":{"items":{"type":"string"},"type":"array"},"secret":{"type":"string"}},"$id":"#/definitions/NewUserResponse"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","required":["id","blocked","roles"],"x-embed":"","properties":{"blocked":{"type":"boolean"},"id":{"type":"string"},"roles":{"items":{"type":"string"},"type":"array"},"secret":{"type":"string"}},"$id":"#/definitions/NewUserResponse"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","x-embed":"","properties":{"artifact_origin":{"$ref":"#/definitions/ArtifactOrigin"},"task_origin":{"$ref":"#/definitions/TaskOrigin"}},"$id":"#/definitions/Origin"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","x-embed":"","properties":{"artifact_origin":{"$ref":"#/definitions/ArtifactOrigin"},"task_origin":{"$ref":"#/definitions/TaskOrigin"}},"$id":"#/definitions/Origin"}`),
|
||||||
@@ -105,7 +105,7 @@ func init() {
|
|||||||
gojsonschema.NewStringLoader(`{"type":"object","required":["name","icon","default_template","default_playbooks"],"x-embed":"","properties":{"default_groups":{"items":{"type":"string"},"type":"array"},"default_playbooks":{"items":{"type":"string"},"type":"array"},"default_template":{"type":"string"},"icon":{"type":"string"},"name":{"type":"string"}},"$id":"#/definitions/TicketType"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","required":["name","icon","default_template","default_playbooks"],"x-embed":"","properties":{"default_groups":{"items":{"type":"string"},"type":"array"},"default_playbooks":{"items":{"type":"string"},"type":"array"},"default_template":{"type":"string"},"icon":{"type":"string"},"name":{"type":"string"}},"$id":"#/definitions/TicketType"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","required":["name","icon","default_template","default_playbooks"],"x-embed":"","properties":{"default_groups":{"items":{"type":"string"},"type":"array"},"default_playbooks":{"items":{"type":"string"},"type":"array"},"default_template":{"type":"string"},"icon":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}},"$id":"#/definitions/TicketTypeForm"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","required":["name","icon","default_template","default_playbooks"],"x-embed":"","properties":{"default_groups":{"items":{"type":"string"},"type":"array"},"default_playbooks":{"items":{"type":"string"},"type":"array"},"default_template":{"type":"string"},"icon":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}},"$id":"#/definitions/TicketTypeForm"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","required":["id","name","icon","default_template","default_playbooks"],"x-embed":"","properties":{"default_groups":{"items":{"type":"string"},"type":"array"},"default_playbooks":{"items":{"type":"string"},"type":"array"},"default_template":{"type":"string"},"icon":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}},"$id":"#/definitions/TicketTypeResponse"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","required":["id","name","icon","default_template","default_playbooks"],"x-embed":"","properties":{"default_groups":{"items":{"type":"string"},"type":"array"},"default_playbooks":{"items":{"type":"string"},"type":"array"},"default_template":{"type":"string"},"icon":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}},"$id":"#/definitions/TicketTypeResponse"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","required":["id","name","type","status","created","modified","schema"],"x-embed":"","properties":{"artifacts":{"items":{"$ref":"#/definitions/Artifact"},"type":"array"},"comments":{"items":{"$ref":"#/definitions/Comment"},"type":"array"},"created":{"format":"date-time","type":"string"},"details":{"type":"object"},"files":{"items":{"$ref":"#/definitions/File"},"type":"array"},"id":{"format":"int64","type":"integer"},"modified":{"format":"date-time","type":"string"},"name":{"type":"string"},"owner":{"type":"string"},"playbooks":{"type":"object","additionalProperties":{"$ref":"#/definitions/PlaybookResponse"}},"read":{"items":{"type":"string"},"type":"array"},"references":{"items":{"$ref":"#/definitions/Reference"},"type":"array"},"schema":{"type":"string"},"status":{"type":"string"},"tickets":{"items":{"$ref":"#/definitions/TicketSimpleResponse"},"type":"array"},"type":{"type":"string"},"write":{"items":{"type":"string"},"type":"array"}},"$id":"#/definitions/TicketWithTickets"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","required":["id","name","type","status","created","modified","schema"],"x-embed":"","properties":{"artifacts":{"items":{"$ref":"#/definitions/Artifact"},"type":"array"},"comments":{"items":{"$ref":"#/definitions/Comment"},"type":"array"},"created":{"format":"date-time","type":"string"},"details":{"type":"object"},"files":{"items":{"$ref":"#/definitions/File"},"type":"array"},"id":{"format":"int64","type":"integer"},"logs":{"items":{"$ref":"#/definitions/LogEntry"},"type":"array"},"modified":{"format":"date-time","type":"string"},"name":{"type":"string"},"owner":{"type":"string"},"playbooks":{"type":"object","additionalProperties":{"$ref":"#/definitions/PlaybookResponse"}},"read":{"items":{"type":"string"},"type":"array"},"references":{"items":{"$ref":"#/definitions/Reference"},"type":"array"},"schema":{"type":"string"},"status":{"type":"string"},"tickets":{"items":{"$ref":"#/definitions/TicketSimpleResponse"},"type":"array"},"type":{"type":"string"},"write":{"items":{"type":"string"},"type":"array"}},"$id":"#/definitions/TicketWithTickets"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","required":["id","name","icon"],"x-embed":"","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"}},"$id":"#/definitions/Type"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","required":["id","name","icon"],"x-embed":"","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"}},"$id":"#/definitions/Type"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","required":["blocked","apikey","roles"],"x-embed":"","properties":{"apikey":{"type":"boolean"},"blocked":{"type":"boolean"},"roles":{"items":{"type":"string"},"type":"array"},"sha256":{"type":"string"}},"$id":"#/definitions/User"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","required":["blocked","apikey","roles"],"x-embed":"","properties":{"apikey":{"type":"boolean"},"blocked":{"type":"boolean"},"roles":{"items":{"type":"string"},"type":"array"},"sha256":{"type":"string"}},"$id":"#/definitions/User"}`),
|
||||||
gojsonschema.NewStringLoader(`{"type":"object","x-embed":"","properties":{"email":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"timeformat":{"title":"Time Format (https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens)","type":"string"}},"$id":"#/definitions/UserData"}`),
|
gojsonschema.NewStringLoader(`{"type":"object","x-embed":"","properties":{"email":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"timeformat":{"title":"Time Format (https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens)","type":"string"}},"$id":"#/definitions/UserData"}`),
|
||||||
@@ -271,6 +271,7 @@ type LogEntry struct {
|
|||||||
Creator string `json:"creator"`
|
Creator string `json:"creator"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Reference string `json:"reference"`
|
Reference string `json:"reference"`
|
||||||
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
@@ -530,6 +531,7 @@ type TicketWithTickets struct {
|
|||||||
Details interface{} `json:"details,omitempty"`
|
Details interface{} `json:"details,omitempty"`
|
||||||
Files []*File `json:"files,omitempty"`
|
Files []*File `json:"files,omitempty"`
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
|
Logs []*LogEntry `json:"logs,omitempty"`
|
||||||
Modified time.Time `json:"modified"`
|
Modified time.Time `json:"modified"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Owner *string `json:"owner,omitempty"`
|
Owner *string `json:"owner,omitempty"`
|
||||||
|
|||||||
@@ -640,7 +640,8 @@ func init() {
|
|||||||
"created": "2021-12-12T12:12:12.000000012Z",
|
"created": "2021-12-12T12:12:12.000000012Z",
|
||||||
"creator": "bob",
|
"creator": "bob",
|
||||||
"message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.",
|
"message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.",
|
||||||
"reference": "tickets/294511"
|
"reference": "tickets/294511",
|
||||||
|
"type": "manual"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -5680,6 +5681,7 @@ func init() {
|
|||||||
"LogEntry": {
|
"LogEntry": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
"type",
|
||||||
"reference",
|
"reference",
|
||||||
"creator",
|
"creator",
|
||||||
"created",
|
"created",
|
||||||
@@ -5698,6 +5700,9 @@ func init() {
|
|||||||
},
|
},
|
||||||
"reference": {
|
"reference": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -6816,6 +6821,12 @@ func init() {
|
|||||||
"format": "int64",
|
"format": "int64",
|
||||||
"example": 123
|
"example": 123
|
||||||
},
|
},
|
||||||
|
"logs": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/LogEntry"
|
||||||
|
}
|
||||||
|
},
|
||||||
"modified": {
|
"modified": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
@@ -7668,7 +7679,8 @@ func init() {
|
|||||||
"created": "2021-12-12T12:12:12.000000012Z",
|
"created": "2021-12-12T12:12:12.000000012Z",
|
||||||
"creator": "bob",
|
"creator": "bob",
|
||||||
"message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.",
|
"message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.",
|
||||||
"reference": "tickets/294511"
|
"reference": "tickets/294511",
|
||||||
|
"type": "manual"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -12708,6 +12720,7 @@ func init() {
|
|||||||
"LogEntry": {
|
"LogEntry": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
|
"type",
|
||||||
"reference",
|
"reference",
|
||||||
"creator",
|
"creator",
|
||||||
"created",
|
"created",
|
||||||
@@ -12726,6 +12739,9 @@ func init() {
|
|||||||
},
|
},
|
||||||
"reference": {
|
"reference": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -13844,6 +13860,12 @@ func init() {
|
|||||||
"format": "int64",
|
"format": "int64",
|
||||||
"example": 123
|
"example": 123
|
||||||
},
|
},
|
||||||
|
"logs": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/LogEntry"
|
||||||
|
}
|
||||||
|
},
|
||||||
"modified": {
|
"modified": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ func TestService(t *testing.T) {
|
|||||||
args: args{method: "GET", url: "/api/logs/tickets%252F294511"},
|
args: args{method: "GET", url: "/api/logs/tickets%252F294511"},
|
||||||
want: want{
|
want: want{
|
||||||
status: 200,
|
status: 200,
|
||||||
body: []interface{}{map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "creator": "bob", "message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.", "reference": "tickets/294511"}},
|
body: []interface{}{map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "creator": "bob", "message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.", "reference": "tickets/294511", "type": "manual"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ require (
|
|||||||
go.etcd.io/bbolt v1.3.6 // indirect
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.7.4 // indirect
|
go.mongodb.org/mongo-driver v1.7.4 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
|
||||||
golang.org/x/net v0.0.0-20211105192438-b53810dc28af
|
golang.org/x/net v0.0.0-20211105192438-b53810dc28af // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||||
golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c // indirect
|
golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
"github.com/gin-contrib/sessions"
|
"github.com/gin-contrib/sessions"
|
||||||
"github.com/gin-contrib/sessions/cookie"
|
"github.com/gin-contrib/sessions/cookie"
|
||||||
|
|
||||||
"github.com/SecurityBrewery/catalyst/automation"
|
|
||||||
"github.com/SecurityBrewery/catalyst/bus"
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
|
"github.com/SecurityBrewery/catalyst/busservice"
|
||||||
"github.com/SecurityBrewery/catalyst/database"
|
"github.com/SecurityBrewery/catalyst/database"
|
||||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
@@ -72,7 +72,7 @@ func New(hooks *hooks.Hooks, config *Config) (*Server, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = automation.New(config.Bus.APIUrl, config.InitialAPIKey, catalystBus, catalystDatabase)
|
err = busservice.New(config.Bus.APIUrl, config.InitialAPIKey, catalystBus, catalystDatabase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-6
@@ -10,25 +10,29 @@ import (
|
|||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickets"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickets"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Service) RunArtifact(ctx context.Context, params *tickets.RunArtifactParams) *api.Response {
|
func (s *Service) RunArtifact(ctx context.Context, params *tickets.RunArtifactParams) (r *api.Response) {
|
||||||
artifact, err := s.database.ArtifactGet(ctx, params.ID, params.Name)
|
artifact, err := s.database.ArtifactGet(ctx, params.ID, params.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response(nil, err)
|
return s.response(ctx, "RunArtifact", ticketID(params.ID), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
jobID := uuid.NewString()
|
jobID := uuid.NewString()
|
||||||
origin := &models.Origin{ArtifactOrigin: &models.ArtifactOrigin{TicketId: params.ID, Artifact: params.Name}}
|
origin := &models.Origin{ArtifactOrigin: &models.ArtifactOrigin{TicketId: params.ID, Artifact: params.Name}}
|
||||||
return response(nil, s.bus.PublishJob(jobID, params.Automation, params.Name, &models.Context{Artifact: artifact}, origin))
|
err = s.bus.PublishJob(jobID, params.Automation, params.Name, &models.Context{Artifact: artifact}, origin)
|
||||||
|
return s.response(ctx, "RunArtifact", ticketID(params.ID), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) EnrichArtifact(ctx context.Context, params *tickets.EnrichArtifactParams) *api.Response {
|
func (s *Service) EnrichArtifact(ctx context.Context, params *tickets.EnrichArtifactParams) *api.Response {
|
||||||
return response(s.database.EnrichArtifact(ctx, params.ID, params.Name, params.Data))
|
i, err := s.database.EnrichArtifact(ctx, params.ID, params.Name, params.Data)
|
||||||
|
return s.response(ctx, "EnrichArtifact", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) SetArtifact(ctx context.Context, params *tickets.SetArtifactParams) *api.Response {
|
func (s *Service) SetArtifact(ctx context.Context, params *tickets.SetArtifactParams) *api.Response {
|
||||||
return response(s.database.ArtifactUpdate(ctx, params.ID, params.Name, params.Artifact))
|
i, err := s.database.ArtifactUpdate(ctx, params.ID, params.Name, params.Artifact)
|
||||||
|
return s.response(ctx, "SetArtifact", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetArtifact(ctx context.Context, params *tickets.GetArtifactParams) *api.Response {
|
func (s *Service) GetArtifact(ctx context.Context, params *tickets.GetArtifactParams) *api.Response {
|
||||||
return response(s.database.ArtifactGet(ctx, params.ID, params.Name))
|
i, err := s.database.ArtifactGet(ctx, params.ID, params.Name)
|
||||||
|
return s.response(ctx, "GetArtifact", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-5
@@ -2,27 +2,40 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/database"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/automations"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/automations"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func automationID(id string) []driver.DocumentID {
|
||||||
|
return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.AutomationCollectionName, id))}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) CreateAutomation(ctx context.Context, params *automations.CreateAutomationParams) *api.Response {
|
func (s *Service) CreateAutomation(ctx context.Context, params *automations.CreateAutomationParams) *api.Response {
|
||||||
return response(s.database.AutomationCreate(ctx, params.Automation))
|
i, err := s.database.AutomationCreate(ctx, params.Automation)
|
||||||
|
return s.response(ctx, "CreateAutomation", automationID(i.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetAutomation(ctx context.Context, params *automations.GetAutomationParams) *api.Response {
|
func (s *Service) GetAutomation(ctx context.Context, params *automations.GetAutomationParams) *api.Response {
|
||||||
return response(s.database.AutomationGet(ctx, params.ID))
|
i, err := s.database.AutomationGet(ctx, params.ID)
|
||||||
|
return s.response(ctx, "GetAutomation", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UpdateAutomation(ctx context.Context, params *automations.UpdateAutomationParams) *api.Response {
|
func (s *Service) UpdateAutomation(ctx context.Context, params *automations.UpdateAutomationParams) *api.Response {
|
||||||
return response(s.database.AutomationUpdate(ctx, params.ID, params.Automation))
|
i, err := s.database.AutomationUpdate(ctx, params.ID, params.Automation)
|
||||||
|
return s.response(ctx, "UpdateAutomation", automationID(i.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) DeleteAutomation(ctx context.Context, params *automations.DeleteAutomationParams) *api.Response {
|
func (s *Service) DeleteAutomation(ctx context.Context, params *automations.DeleteAutomationParams) *api.Response {
|
||||||
return response(nil, s.database.AutomationDelete(ctx, params.ID))
|
err := s.database.AutomationDelete(ctx, params.ID)
|
||||||
|
return s.response(ctx, "DeleteAutomation", automationID(params.ID), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) ListAutomations(ctx context.Context) *api.Response {
|
func (s *Service) ListAutomations(ctx context.Context) *api.Response {
|
||||||
return response(s.database.AutomationList(ctx))
|
i, err := s.database.AutomationList(ctx)
|
||||||
|
return s.response(ctx, "ListAutomations", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-6
@@ -2,28 +2,38 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/database"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/jobs"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/jobs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Service) RunJob(_ context.Context, params *jobs.RunJobParams) *api.Response {
|
func jobID(id string) []driver.DocumentID {
|
||||||
|
return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.JobCollectionName, id))}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) RunJob(ctx context.Context, params *jobs.RunJobParams) *api.Response {
|
||||||
msgContext := &models.Context{}
|
msgContext := &models.Context{}
|
||||||
jobID := uuid.NewString()
|
newJobID := uuid.NewString()
|
||||||
return response(nil, s.bus.PublishJob(jobID, params.Job.Automation, params.Job.Payload, msgContext, params.Job.Origin))
|
return s.response(ctx, "RunJob", jobID(newJobID), nil, s.bus.PublishJob(newJobID, params.Job.Automation, params.Job.Payload, msgContext, params.Job.Origin))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetJob(ctx context.Context, params *jobs.GetJobParams) *api.Response {
|
func (s *Service) GetJob(ctx context.Context, params *jobs.GetJobParams) *api.Response {
|
||||||
return response(s.database.JobGet(ctx, params.ID))
|
i, err := s.database.JobGet(ctx, params.ID)
|
||||||
|
return s.response(ctx, "GetJob", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) ListJobs(ctx context.Context) *api.Response {
|
func (s *Service) ListJobs(ctx context.Context) *api.Response {
|
||||||
return response(s.database.JobList(ctx))
|
i, err := s.database.JobList(ctx)
|
||||||
|
return s.response(ctx, "ListJobs", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UpdateJob(ctx context.Context, params *jobs.UpdateJobParams) *api.Response {
|
func (s *Service) UpdateJob(ctx context.Context, params *jobs.UpdateJobParams) *api.Response {
|
||||||
return response(s.database.JobUpdate(ctx, params.ID, params.Job))
|
i, err := s.database.JobUpdate(ctx, params.ID, params.Job)
|
||||||
|
return s.response(ctx, "UpdateJob", jobID(i.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -10,5 +10,6 @@ import (
|
|||||||
|
|
||||||
func (s *Service) GetLogs(ctx context.Context, params *logs.GetLogsParams) *api.Response {
|
func (s *Service) GetLogs(ctx context.Context, params *logs.GetLogsParams) *api.Response {
|
||||||
id, _ := url.QueryUnescape(params.Reference)
|
id, _ := url.QueryUnescape(params.Reference)
|
||||||
return response(s.database.LogList(ctx, id))
|
i, err := s.database.LogList(ctx, id)
|
||||||
|
return s.response(ctx, "GetLogs", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-6
@@ -5,35 +5,46 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
"github.com/xeipuuv/gojsonschema"
|
"github.com/xeipuuv/gojsonschema"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/database"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/playbooks"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/playbooks"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func playbookID(id string) []driver.DocumentID {
|
||||||
|
return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.PlaybookCollectionName, id))}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) CreatePlaybook(ctx context.Context, params *playbooks.CreatePlaybookParams) *api.Response {
|
func (s *Service) CreatePlaybook(ctx context.Context, params *playbooks.CreatePlaybookParams) *api.Response {
|
||||||
return response(s.database.PlaybookCreate(ctx, params.Playbook))
|
i, err := s.database.PlaybookCreate(ctx, params.Playbook)
|
||||||
|
return s.response(ctx, "CreatePlaybook", playbookID(i.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetPlaybook(ctx context.Context, params *playbooks.GetPlaybookParams) *api.Response {
|
func (s *Service) GetPlaybook(ctx context.Context, params *playbooks.GetPlaybookParams) *api.Response {
|
||||||
return response(s.database.PlaybookGet(ctx, params.ID))
|
i, err := s.database.PlaybookGet(ctx, params.ID)
|
||||||
|
return s.response(ctx, "GetPlaybook", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UpdatePlaybook(ctx context.Context, params *playbooks.UpdatePlaybookParams) *api.Response {
|
func (s *Service) UpdatePlaybook(ctx context.Context, params *playbooks.UpdatePlaybookParams) *api.Response {
|
||||||
if err := validate(params.Playbook, models.PlaybookTemplateFormSchema); err != nil {
|
if err := validate(params.Playbook, models.PlaybookTemplateFormSchema); err != nil {
|
||||||
return response(nil, err)
|
return s.response(ctx, "UpdatePlaybook", nil, nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response(s.database.PlaybookUpdate(ctx, params.ID, params.Playbook))
|
i, err := s.database.PlaybookUpdate(ctx, params.ID, params.Playbook)
|
||||||
|
return s.response(ctx, "UpdatePlaybook", playbookID(i.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) DeletePlaybook(ctx context.Context, params *playbooks.DeletePlaybookParams) *api.Response {
|
func (s *Service) DeletePlaybook(ctx context.Context, params *playbooks.DeletePlaybookParams) *api.Response {
|
||||||
return response(nil, s.database.PlaybookDelete(ctx, params.ID))
|
err := s.database.PlaybookDelete(ctx, params.ID)
|
||||||
|
return s.response(ctx, "DeletePlaybook", playbookID(params.ID), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) ListPlaybooks(ctx context.Context) *api.Response {
|
func (s *Service) ListPlaybooks(ctx context.Context) *api.Response {
|
||||||
return response(s.database.PlaybookList(ctx))
|
i, err := s.database.PlaybookList(ctx)
|
||||||
|
return s.response(ctx, "ListPlaybooks", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validate(e interface{}, schema *gojsonschema.Schema) error {
|
func validate(e interface{}, schema *gojsonschema.Schema) error {
|
||||||
|
|||||||
+14
-1
@@ -1,6 +1,7 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -10,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/SecurityBrewery/catalyst/bus"
|
"github.com/SecurityBrewery/catalyst/bus"
|
||||||
"github.com/SecurityBrewery/catalyst/database"
|
"github.com/SecurityBrewery/catalyst/database"
|
||||||
|
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
||||||
"github.com/SecurityBrewery/catalyst/storage"
|
"github.com/SecurityBrewery/catalyst/storage"
|
||||||
@@ -30,11 +32,22 @@ func (s *Service) Healthy() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func response(v interface{}, err error) *api.Response {
|
func (s *Service) response(ctx context.Context, function string, ids []driver.DocumentID, v interface{}, err error) *api.Response {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return &api.Response{Code: httpStatus(err), Body: gin.H{"error": err.Error()}}
|
return &api.Response{Code: httpStatus(err), Body: gin.H{"error": err.Error()}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ids != nil {
|
||||||
|
userID := "unknown"
|
||||||
|
user, ok := busdb.UserFromContext(ctx)
|
||||||
|
if ok {
|
||||||
|
userID = user.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
go s.bus.PublishRequest(userID, function, ids)
|
||||||
|
}
|
||||||
|
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return &api.Response{Code: http.StatusNoContent, Body: v}
|
return &api.Response{Code: http.StatusNoContent, Body: v}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (s *Service) GetStatistics(ctx context.Context) *api.Response {
|
func (s *Service) GetStatistics(ctx context.Context) *api.Response {
|
||||||
return response(s.database.Statistics(ctx))
|
i, err := s.database.Statistics(ctx)
|
||||||
|
return s.response(ctx, "GetStatistics", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -7,5 +7,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (s *Service) ListTasks(ctx context.Context) *api.Response {
|
func (s *Service) ListTasks(ctx context.Context) *api.Response {
|
||||||
return response(s.database.TaskList(ctx))
|
i, err := s.database.TaskList(ctx)
|
||||||
|
return s.response(ctx, "ListTasks", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-5
@@ -2,27 +2,40 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/database"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/templates"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/templates"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func templateID(s string) []driver.DocumentID {
|
||||||
|
return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.TemplateCollectionName, s))}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) CreateTemplate(ctx context.Context, params *templates.CreateTemplateParams) *api.Response {
|
func (s *Service) CreateTemplate(ctx context.Context, params *templates.CreateTemplateParams) *api.Response {
|
||||||
return response(s.database.TemplateCreate(ctx, params.Template))
|
i, err := s.database.TemplateCreate(ctx, params.Template)
|
||||||
|
return s.response(ctx, "CreateTemplate", templateID(i.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetTemplate(ctx context.Context, params *templates.GetTemplateParams) *api.Response {
|
func (s *Service) GetTemplate(ctx context.Context, params *templates.GetTemplateParams) *api.Response {
|
||||||
return response(s.database.TemplateGet(ctx, params.ID))
|
i, err := s.database.TemplateGet(ctx, params.ID)
|
||||||
|
return s.response(ctx, "GetTemplate", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UpdateTemplate(ctx context.Context, params *templates.UpdateTemplateParams) *api.Response {
|
func (s *Service) UpdateTemplate(ctx context.Context, params *templates.UpdateTemplateParams) *api.Response {
|
||||||
return response(s.database.TemplateUpdate(ctx, params.ID, params.Template))
|
i, err := s.database.TemplateUpdate(ctx, params.ID, params.Template)
|
||||||
|
return s.response(ctx, "UpdateTemplate", templateID(i.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) DeleteTemplate(ctx context.Context, params *templates.DeleteTemplateParams) *api.Response {
|
func (s *Service) DeleteTemplate(ctx context.Context, params *templates.DeleteTemplateParams) *api.Response {
|
||||||
return response(nil, s.database.TemplateDelete(ctx, params.ID))
|
err := s.database.TemplateDelete(ctx, params.ID)
|
||||||
|
return s.response(ctx, "DeleteTemplate", templateID(params.ID), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) ListTemplates(ctx context.Context) *api.Response {
|
func (s *Service) ListTemplates(ctx context.Context) *api.Response {
|
||||||
return response(s.database.TemplateList(ctx))
|
i, err := s.database.TemplateList(ctx)
|
||||||
|
return s.response(ctx, "ListTemplates", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-9
@@ -4,39 +4,56 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/database"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/models"
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickets"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickets"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ticketID(id int64) []driver.DocumentID {
|
||||||
|
return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%d", database.TicketCollectionName, id))}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ticketIDs(ticketResponses []*models.TicketResponse) []driver.DocumentID {
|
||||||
|
var ids []driver.DocumentID
|
||||||
|
for _, ticketResponse := range ticketResponses {
|
||||||
|
ids = append(ids, ticketID(ticketResponse.ID)...)
|
||||||
|
}
|
||||||
|
return ids
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) CreateTicket(ctx context.Context, params *tickets.CreateTicketParams) *api.Response {
|
func (s *Service) CreateTicket(ctx context.Context, params *tickets.CreateTicketParams) *api.Response {
|
||||||
createdTickets, err := s.database.TicketBatchCreate(ctx, []*models.TicketForm{params.Ticket})
|
createdTickets, err := s.database.TicketBatchCreate(ctx, []*models.TicketForm{params.Ticket})
|
||||||
if len(createdTickets) > 0 {
|
if len(createdTickets) > 0 {
|
||||||
return response(createdTickets[0], err)
|
return s.response(ctx, "CreateTicket", ticketIDs(createdTickets), createdTickets[0], err)
|
||||||
}
|
}
|
||||||
return response(nil, err)
|
return s.response(ctx, "CreateTicket", ticketIDs(createdTickets), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) CreateTicketBatch(ctx context.Context, params *tickets.CreateTicketBatchParams) *api.Response {
|
func (s *Service) CreateTicketBatch(ctx context.Context, params *tickets.CreateTicketBatchParams) *api.Response {
|
||||||
_, err := s.database.TicketBatchCreate(ctx, params.Ticket)
|
ticketBatch, err := s.database.TicketBatchCreate(ctx, params.Ticket)
|
||||||
return response(nil, err)
|
return s.response(ctx, "CreateTicketBatch", ticketIDs(ticketBatch), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetTicket(ctx context.Context, params *tickets.GetTicketParams) *api.Response {
|
func (s *Service) GetTicket(ctx context.Context, params *tickets.GetTicketParams) *api.Response {
|
||||||
return response(s.database.TicketGet(ctx, params.ID))
|
ticket, err := s.database.TicketGet(ctx, params.ID)
|
||||||
|
return s.response(ctx, "GetTicket", nil, ticket, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UpdateTicket(ctx context.Context, params *tickets.UpdateTicketParams) *api.Response {
|
func (s *Service) UpdateTicket(ctx context.Context, params *tickets.UpdateTicketParams) *api.Response {
|
||||||
return response(s.database.TicketUpdate(ctx, params.ID, params.Ticket))
|
ticket, err := s.database.TicketUpdate(ctx, params.ID, params.Ticket)
|
||||||
|
return s.response(ctx, "UpdateTicket", ticketID(ticket.ID), ticket, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) DeleteTicket(ctx context.Context, params *tickets.DeleteTicketParams) *api.Response {
|
func (s *Service) DeleteTicket(ctx context.Context, params *tickets.DeleteTicketParams) *api.Response {
|
||||||
if err := s.database.TicketDelete(ctx, params.ID); err != nil {
|
if err := s.database.TicketDelete(ctx, params.ID); err != nil {
|
||||||
return response(nil, err)
|
return s.response(ctx, "DeleteTicket", ticketID(params.ID), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = s.storage.DeleteBucket(fmt.Sprint(params.ID))
|
_ = s.storage.DeleteBucket(fmt.Sprint(params.ID))
|
||||||
return response(nil, nil)
|
return s.response(ctx, "DeleteTicket", ticketID(params.ID), nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) ListTickets(ctx context.Context, params *tickets.ListTicketsParams) *api.Response {
|
func (s *Service) ListTickets(ctx context.Context, params *tickets.ListTicketsParams) *api.Response {
|
||||||
@@ -48,5 +65,7 @@ func (s *Service) ListTickets(ctx context.Context, params *tickets.ListTicketsPa
|
|||||||
if params.Type != nil && *params.Type != "" {
|
if params.Type != nil && *params.Type != "" {
|
||||||
t = *params.Type
|
t = *params.Type
|
||||||
}
|
}
|
||||||
return response(s.database.TicketList(ctx, t, q, params.Sort, params.Desc, *params.Offset, *params.Count))
|
|
||||||
|
ticketList, err := s.database.TicketList(ctx, t, q, params.Sort, params.Desc, *params.Offset, *params.Count)
|
||||||
|
return s.response(ctx, "ListTickets", nil, ticketList, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-16
@@ -8,67 +8,81 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (s *Service) AddArtifact(ctx context.Context, params *tickets.AddArtifactParams) *api.Response {
|
func (s *Service) AddArtifact(ctx context.Context, params *tickets.AddArtifactParams) *api.Response {
|
||||||
return response(s.database.AddArtifact(ctx, params.ID, params.Artifact))
|
i, err := s.database.AddArtifact(ctx, params.ID, params.Artifact)
|
||||||
|
return s.response(ctx, "AddArtifact", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) RemoveArtifact(ctx context.Context, params *tickets.RemoveArtifactParams) *api.Response {
|
func (s *Service) RemoveArtifact(ctx context.Context, params *tickets.RemoveArtifactParams) *api.Response {
|
||||||
return response(s.database.RemoveArtifact(ctx, params.ID, params.Name))
|
i, err := s.database.RemoveArtifact(ctx, params.ID, params.Name)
|
||||||
|
return s.response(ctx, "RemoveArtifact", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) SetSchema(ctx context.Context, params *tickets.SetSchemaParams) *api.Response {
|
func (s *Service) SetSchema(ctx context.Context, params *tickets.SetSchemaParams) *api.Response {
|
||||||
return response(s.database.SetTemplate(ctx, params.ID, params.Schema))
|
i, err := s.database.SetTemplate(ctx, params.ID, params.Schema)
|
||||||
|
return s.response(ctx, "SetSchema", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) AddComment(ctx context.Context, params *tickets.AddCommentParams) *api.Response {
|
func (s *Service) AddComment(ctx context.Context, params *tickets.AddCommentParams) *api.Response {
|
||||||
return response(s.database.AddComment(ctx, params.ID, params.Comment))
|
i, err := s.database.AddComment(ctx, params.ID, params.Comment)
|
||||||
|
return s.response(ctx, "AddComment", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) RemoveComment(ctx context.Context, params *tickets.RemoveCommentParams) *api.Response {
|
func (s *Service) RemoveComment(ctx context.Context, params *tickets.RemoveCommentParams) *api.Response {
|
||||||
return response(s.database.RemoveComment(ctx, params.ID, params.CommentID))
|
i, err := s.database.RemoveComment(ctx, params.ID, params.CommentID)
|
||||||
|
return s.response(ctx, "RemoveComment", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) LinkTicket(ctx context.Context, params *tickets.LinkTicketParams) *api.Response {
|
func (s *Service) LinkTicket(ctx context.Context, params *tickets.LinkTicketParams) *api.Response {
|
||||||
err := s.database.RelatedCreate(ctx, params.ID, params.LinkedID)
|
err := s.database.RelatedCreate(ctx, params.ID, params.LinkedID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response(nil, err)
|
return s.response(ctx, "LinkTicket", ticketID(params.ID), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.GetTicket(ctx, &tickets.GetTicketParams{ID: params.ID})
|
i, err := s.database.TicketGet(ctx, params.ID)
|
||||||
|
return s.response(ctx, "LinkTicket", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UnlinkTicket(ctx context.Context, params *tickets.UnlinkTicketParams) *api.Response {
|
func (s *Service) UnlinkTicket(ctx context.Context, params *tickets.UnlinkTicketParams) *api.Response {
|
||||||
err := s.database.RelatedRemove(ctx, params.ID, params.LinkedID)
|
err := s.database.RelatedRemove(ctx, params.ID, params.LinkedID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response(nil, err)
|
return s.response(ctx, "UnlinkTicket", ticketID(params.ID), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.GetTicket(ctx, &tickets.GetTicketParams{ID: params.ID})
|
i, err := s.database.TicketGet(ctx, params.ID)
|
||||||
|
return s.response(ctx, "UnlinkTicket", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Service) SetReferences(ctx context.Context, params *tickets.SetReferencesParams) *api.Response {
|
func (s Service) SetReferences(ctx context.Context, params *tickets.SetReferencesParams) *api.Response {
|
||||||
return response(s.database.SetReferences(ctx, params.ID, params.References))
|
i, err := s.database.SetReferences(ctx, params.ID, params.References)
|
||||||
|
return s.response(ctx, "SetReferences", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Service) LinkFiles(ctx context.Context, params *tickets.LinkFilesParams) *api.Response {
|
func (s Service) LinkFiles(ctx context.Context, params *tickets.LinkFilesParams) *api.Response {
|
||||||
return response(s.database.LinkFiles(ctx, params.ID, params.Files))
|
i, err := s.database.LinkFiles(ctx, params.ID, params.Files)
|
||||||
|
return s.response(ctx, "LinkFiles", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Service) AddTicketPlaybook(ctx context.Context, params *tickets.AddTicketPlaybookParams) *api.Response {
|
func (s Service) AddTicketPlaybook(ctx context.Context, params *tickets.AddTicketPlaybookParams) *api.Response {
|
||||||
return response(s.database.AddTicketPlaybook(ctx, params.ID, params.Playbook))
|
i, err := s.database.AddTicketPlaybook(ctx, params.ID, params.Playbook)
|
||||||
|
return s.response(ctx, "AddTicketPlaybook", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Service) RemoveTicketPlaybook(ctx context.Context, params *tickets.RemoveTicketPlaybookParams) *api.Response {
|
func (s Service) RemoveTicketPlaybook(ctx context.Context, params *tickets.RemoveTicketPlaybookParams) *api.Response {
|
||||||
return response(s.database.RemoveTicketPlaybook(ctx, params.ID, params.PlaybookID))
|
i, err := s.database.RemoveTicketPlaybook(ctx, params.ID, params.PlaybookID)
|
||||||
|
return s.response(ctx, "RemoveTicketPlaybook", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Service) CompleteTask(ctx context.Context, params *tickets.CompleteTaskParams) *api.Response {
|
func (s Service) CompleteTask(ctx context.Context, params *tickets.CompleteTaskParams) *api.Response {
|
||||||
return response(s.database.TaskComplete(ctx, params.ID, params.PlaybookID, params.TaskID, params.Data))
|
i, err := s.database.TaskComplete(ctx, params.ID, params.PlaybookID, params.TaskID, params.Data)
|
||||||
|
return s.response(ctx, "CompleteTask", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Service) SetTask(ctx context.Context, params *tickets.SetTaskParams) *api.Response {
|
func (s Service) SetTask(ctx context.Context, params *tickets.SetTaskParams) *api.Response {
|
||||||
return response(s.database.TaskUpdate(ctx, params.ID, params.PlaybookID, params.TaskID, params.Task))
|
i, err := s.database.TaskUpdate(ctx, params.ID, params.PlaybookID, params.TaskID, params.Task)
|
||||||
|
return s.response(ctx, "SetTask", ticketID(params.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) RunTask(ctx context.Context, params *tickets.RunTaskParams) *api.Response {
|
func (s *Service) RunTask(ctx context.Context, params *tickets.RunTaskParams) *api.Response {
|
||||||
return response(nil, s.database.TaskRun(ctx, params.ID, params.PlaybookID, params.TaskID))
|
err := s.database.TaskRun(ctx, params.ID, params.PlaybookID, params.TaskID)
|
||||||
|
return s.response(ctx, "RunTask", ticketID(params.ID), nil, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-5
@@ -2,27 +2,40 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/database"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickettypes"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickettypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ticketTypeID(id string) []driver.DocumentID {
|
||||||
|
return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.TicketTypeCollectionName, id))}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) CreateTicketType(ctx context.Context, params *tickettypes.CreateTicketTypeParams) *api.Response {
|
func (s *Service) CreateTicketType(ctx context.Context, params *tickettypes.CreateTicketTypeParams) *api.Response {
|
||||||
return response(s.database.TicketTypeCreate(ctx, params.Tickettype))
|
ticketType, err := s.database.TicketTypeCreate(ctx, params.Tickettype)
|
||||||
|
return s.response(ctx, "CreateTicketType", ticketTypeID(ticketType.ID), ticketType, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetTicketType(ctx context.Context, params *tickettypes.GetTicketTypeParams) *api.Response {
|
func (s *Service) GetTicketType(ctx context.Context, params *tickettypes.GetTicketTypeParams) *api.Response {
|
||||||
return response(s.database.TicketTypeGet(ctx, params.ID))
|
ticketType, err := s.database.TicketTypeGet(ctx, params.ID)
|
||||||
|
return s.response(ctx, "GetTicketType", nil, ticketType, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UpdateTicketType(ctx context.Context, params *tickettypes.UpdateTicketTypeParams) *api.Response {
|
func (s *Service) UpdateTicketType(ctx context.Context, params *tickettypes.UpdateTicketTypeParams) *api.Response {
|
||||||
return response(s.database.TicketTypeUpdate(ctx, params.ID, params.Tickettype))
|
ticketType, err := s.database.TicketTypeUpdate(ctx, params.ID, params.Tickettype)
|
||||||
|
return s.response(ctx, "UpdateTicketType", ticketTypeID(ticketType.ID), ticketType, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) DeleteTicketType(ctx context.Context, params *tickettypes.DeleteTicketTypeParams) *api.Response {
|
func (s *Service) DeleteTicketType(ctx context.Context, params *tickettypes.DeleteTicketTypeParams) *api.Response {
|
||||||
return response(nil, s.database.TicketTypeDelete(ctx, params.ID))
|
err := s.database.TicketTypeDelete(ctx, params.ID)
|
||||||
|
return s.response(ctx, "DeleteTicketType", ticketTypeID(params.ID), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) ListTicketTypes(ctx context.Context) *api.Response {
|
func (s *Service) ListTicketTypes(ctx context.Context) *api.Response {
|
||||||
return response(s.database.TicketTypeList(ctx))
|
ticketTypes, err := s.database.TicketTypeList(ctx)
|
||||||
|
return s.response(ctx, "ListTicketTypes", nil, ticketTypes, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,24 +14,24 @@ import (
|
|||||||
func (s *Service) GetSettings(ctx context.Context) *api.Response {
|
func (s *Service) GetSettings(ctx context.Context) *api.Response {
|
||||||
user, ok := busdb.UserFromContext(ctx)
|
user, ok := busdb.UserFromContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return response(nil, errors.New("no user in context"))
|
return s.response(ctx, "GetSettings", nil, nil, errors.New("no user in context"))
|
||||||
}
|
}
|
||||||
|
|
||||||
setting, err := s.database.UserDataGet(ctx, user.ID)
|
setting, err := s.database.UserDataGet(ctx, user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response(nil, err)
|
return s.response(ctx, "GetSettings", nil, nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
settings := mergeSettings(s.settings, setting)
|
settings := mergeSettings(s.settings, setting)
|
||||||
|
|
||||||
ticketTypeList, err := s.database.TicketTypeList(ctx)
|
ticketTypeList, err := s.database.TicketTypeList(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response(nil, err)
|
return s.response(ctx, "GetSettings", nil, nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.TicketTypes = ticketTypeList
|
settings.TicketTypes = ticketTypeList
|
||||||
|
|
||||||
return response(settings, nil)
|
return s.response(ctx, "GetSettings", nil, settings, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mergeSettings(globalSettings *models.Settings, user *models.UserDataResponse) *models.Settings {
|
func mergeSettings(globalSettings *models.Settings, user *models.UserDataResponse) *models.Settings {
|
||||||
|
|||||||
+20
-7
@@ -3,36 +3,49 @@ package service
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/database"
|
||||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/users"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func userID(id string) []driver.DocumentID {
|
||||||
|
return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.UserCollectionName, id))}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) GetUser(ctx context.Context, params *users.GetUserParams) *api.Response {
|
func (s *Service) GetUser(ctx context.Context, params *users.GetUserParams) *api.Response {
|
||||||
return response(s.database.UserGet(ctx, params.ID))
|
i, err := s.database.UserGet(ctx, params.ID)
|
||||||
|
return s.response(ctx, "GetUser", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) ListUsers(ctx context.Context) *api.Response {
|
func (s *Service) ListUsers(ctx context.Context) *api.Response {
|
||||||
return response(s.database.UserList(ctx))
|
i, err := s.database.UserList(ctx)
|
||||||
|
return s.response(ctx, "ListUsers", nil, i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) CreateUser(ctx context.Context, params *users.CreateUserParams) *api.Response {
|
func (s *Service) CreateUser(ctx context.Context, params *users.CreateUserParams) *api.Response {
|
||||||
return response(s.database.UserCreate(ctx, params.User))
|
i, err := s.database.UserCreate(ctx, params.User)
|
||||||
|
return s.response(ctx, "CreateUser", userID(i.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) DeleteUser(ctx context.Context, params *users.DeleteUserParams) *api.Response {
|
func (s *Service) DeleteUser(ctx context.Context, params *users.DeleteUserParams) *api.Response {
|
||||||
return response(nil, s.database.UserDelete(ctx, params.ID))
|
err := s.database.UserDelete(ctx, params.ID)
|
||||||
|
return s.response(ctx, "DeleteUser", userID(params.ID), nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) CurrentUser(ctx context.Context) *api.Response {
|
func (s *Service) CurrentUser(ctx context.Context) *api.Response {
|
||||||
user, ok := busdb.UserFromContext(ctx)
|
user, ok := busdb.UserFromContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return response(nil, errors.New("no user in context"))
|
return s.response(ctx, "CurrentUser", nil, nil, errors.New("no user in context"))
|
||||||
}
|
}
|
||||||
return response(user, nil)
|
return s.response(ctx, "CurrentUser", nil, user, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UpdateUser(ctx context.Context, params *users.UpdateUserParams) *api.Response {
|
func (s *Service) UpdateUser(ctx context.Context, params *users.UpdateUserParams) *api.Response {
|
||||||
return response(s.database.UserUpdate(ctx, params.ID, params.User))
|
i, err := s.database.UserUpdate(ctx, params.ID, params.User)
|
||||||
|
return s.response(ctx, "UpdateUser", userID(i.ID), i, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-7
@@ -3,37 +3,50 @@ package service
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
|
||||||
|
"github.com/SecurityBrewery/catalyst/database"
|
||||||
"github.com/SecurityBrewery/catalyst/database/busdb"
|
"github.com/SecurityBrewery/catalyst/database/busdb"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
|
||||||
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/userdata"
|
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/userdata"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func userdataID(id string) []driver.DocumentID {
|
||||||
|
return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.UserDataCollectionName, id))}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) GetUserData(ctx context.Context, params *userdata.GetUserDataParams) *api.Response {
|
func (s *Service) GetUserData(ctx context.Context, params *userdata.GetUserDataParams) *api.Response {
|
||||||
return response(s.database.UserDataGet(ctx, params.ID))
|
userData, err := s.database.UserDataGet(ctx, params.ID)
|
||||||
|
return s.response(ctx, "GetUserData", nil, userData, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) ListUserData(ctx context.Context) *api.Response {
|
func (s *Service) ListUserData(ctx context.Context) *api.Response {
|
||||||
return response(s.database.UserDataList(ctx))
|
userData, err := s.database.UserDataList(ctx)
|
||||||
|
return s.response(ctx, "ListUserData", nil, userData, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UpdateUserData(ctx context.Context, params *userdata.UpdateUserDataParams) *api.Response {
|
func (s *Service) UpdateUserData(ctx context.Context, params *userdata.UpdateUserDataParams) *api.Response {
|
||||||
return response(s.database.UserDataUpdate(ctx, params.ID, params.Userdata))
|
userData, err := s.database.UserDataUpdate(ctx, params.ID, params.Userdata)
|
||||||
|
return s.response(ctx, "UpdateUserData", userdataID(userData.ID), userData, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) CurrentUserData(ctx context.Context) *api.Response {
|
func (s *Service) CurrentUserData(ctx context.Context) *api.Response {
|
||||||
user, ok := busdb.UserFromContext(ctx)
|
user, ok := busdb.UserFromContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return response(nil, errors.New("no user in context"))
|
return s.response(ctx, "CurrentUserData", userdataID(user.ID), nil, errors.New("no user in context"))
|
||||||
}
|
}
|
||||||
return s.GetUserData(ctx, &userdata.GetUserDataParams{ID: user.ID})
|
userData, err := s.database.UserDataGet(ctx, user.ID)
|
||||||
|
return s.response(ctx, "GetUserData", nil, userData, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) UpdateCurrentUserData(ctx context.Context, params *userdata.UpdateCurrentUserDataParams) *api.Response {
|
func (s *Service) UpdateCurrentUserData(ctx context.Context, params *userdata.UpdateCurrentUserDataParams) *api.Response {
|
||||||
user, ok := busdb.UserFromContext(ctx)
|
user, ok := busdb.UserFromContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return response(nil, errors.New("no user in context"))
|
return s.response(ctx, "UpdateCurrentUserData", userdataID(user.ID), nil, errors.New("no user in context"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return response(s.database.UserDataUpdate(ctx, user.ID, params.Userdata))
|
userData, err := s.database.UserDataUpdate(ctx, user.ID, params.Userdata)
|
||||||
|
return s.response(ctx, "UpdateCurrentUserData", userdataID(user.ID), userData, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -77,7 +77,7 @@ func SetupTestData(ctx context.Context, db *database.Database) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := db.LogCreate(ctx, "tickets/294511", "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim."); err != nil {
|
if _, err := db.LogCreate(ctx, "manual", "tickets/294511", "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim."); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -612,6 +612,12 @@ export interface LogEntry {
|
|||||||
* @memberof LogEntry
|
* @memberof LogEntry
|
||||||
*/
|
*/
|
||||||
reference: string;
|
reference: string;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof LogEntry
|
||||||
|
*/
|
||||||
|
type: string;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -2026,6 +2032,12 @@ export interface TicketWithTickets {
|
|||||||
* @memberof TicketWithTickets
|
* @memberof TicketWithTickets
|
||||||
*/
|
*/
|
||||||
id: number;
|
id: number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {Array<LogEntry>}
|
||||||
|
* @memberof TicketWithTickets
|
||||||
|
*/
|
||||||
|
logs?: Array<LogEntry>;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
|||||||
+13
-3
@@ -200,8 +200,15 @@
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
</v-textarea>
|
</v-textarea>
|
||||||
<div v-for="(comment, id) in ticket.comments" :key="id" class="pb-2">
|
<div v-for="(comment, id) in logs(ticket)" :key="id" class="pb-2">
|
||||||
<v-card elevation="0" color="cards">
|
<div v-if="'type' in comment && comment.message !== 'AddComment'" style="text-align: center">
|
||||||
|
<span class="text--disabled" :title="comment.created">
|
||||||
|
{{ comment.message }} ·
|
||||||
|
<strong> {{ comment.creator }}</strong> ·
|
||||||
|
{{ relDate(comment.created) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<v-card v-else-if="!('type' in comment)" elevation="0" color="cards">
|
||||||
<v-card-subtitle class="pb-0">
|
<v-card-subtitle class="pb-0">
|
||||||
<strong> {{ comment.creator }}</strong>
|
<strong> {{ comment.creator }}</strong>
|
||||||
<span class="text--disabled ml-3" :title="comment.created">
|
<span class="text--disabled ml-3" :title="comment.created">
|
||||||
@@ -791,7 +798,7 @@ import {
|
|||||||
Task,
|
Task,
|
||||||
Type,
|
Type,
|
||||||
TypeColorEnum,
|
TypeColorEnum,
|
||||||
TaskResponse, PlaybookResponse, UserResponse, TaskTypeEnum
|
TaskResponse, PlaybookResponse, UserResponse, TaskTypeEnum, TicketWithTickets,
|
||||||
} from "../client";
|
} from "../client";
|
||||||
import {API} from "@/services/api";
|
import {API} from "@/services/api";
|
||||||
|
|
||||||
@@ -1520,6 +1527,9 @@ export default Vue.extend({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return relDate;
|
return relDate;
|
||||||
|
},
|
||||||
|
logs: function(ticket: TicketWithTickets) {
|
||||||
|
return this.lodash.reverse(this.lodash.sortBy(this.lodash.union(ticket.comments, ticket.logs), ['created']))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|||||||
+2
-3
@@ -6,7 +6,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gobwas/ws"
|
"github.com/gobwas/ws"
|
||||||
"github.com/gobwas/ws/wsutil"
|
"github.com/gobwas/ws/wsutil"
|
||||||
@@ -48,10 +47,10 @@ func handleWebSocket(catalystBus *bus.Bus) func(ctx *gin.Context) {
|
|||||||
broker := websocketBroker{clients: map[string]chan []byte{}}
|
broker := websocketBroker{clients: map[string]chan []byte{}}
|
||||||
|
|
||||||
// send all messages from bus to websocket
|
// send all messages from bus to websocket
|
||||||
err := catalystBus.SubscribeUpdate(func(ids []driver.DocumentID) {
|
err := catalystBus.SubscribeDatabaseUpdate(func(msg *bus.DatabaseUpdateMsg) {
|
||||||
b, err := json.Marshal(map[string]interface{}{
|
b, err := json.Marshal(map[string]interface{}{
|
||||||
"action": "update",
|
"action": "update",
|
||||||
"ids": ids,
|
"ids": msg.IDs,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user