mirror of
https://github.com/SecurityBrewery/catalyst.git
synced 2025-12-07 07:42:45 +01:00
236 lines
6.5 KiB
Go
236 lines
6.5 KiB
Go
package fakedata
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"time"
|
|
|
|
"github.com/pocketbase/pocketbase/core"
|
|
"github.com/pocketbase/pocketbase/models"
|
|
"github.com/pocketbase/pocketbase/tools/types"
|
|
|
|
"github.com/SecurityBrewery/catalyst/migrations"
|
|
)
|
|
|
|
func defaultData() map[string]map[string]map[string]any {
|
|
var (
|
|
ticketCreated = time.Date(2025, 2, 1, 11, 29, 35, 0, time.UTC)
|
|
ticketUpdated = ticketCreated.Add(time.Minute * 5)
|
|
commentCreated = ticketCreated.Add(time.Minute * 10)
|
|
commentUpdated = commentCreated.Add(time.Minute * 5)
|
|
timelineCreated = ticketCreated.Add(time.Minute * 15)
|
|
timelineUpdated = timelineCreated.Add(time.Minute * 5)
|
|
taskCreated = ticketCreated.Add(time.Minute * 20)
|
|
taskUpdated = taskCreated.Add(time.Minute * 5)
|
|
linkCreated = ticketCreated.Add(time.Minute * 25)
|
|
linkUpdated = linkCreated.Add(time.Minute * 5)
|
|
reactionCreated = time.Date(2025, 2, 1, 11, 30, 0, 0, time.UTC)
|
|
reactionUpdated = reactionCreated.Add(time.Minute * 5)
|
|
)
|
|
|
|
createTicketActionData := `{"requirements":"pocketbase","script":"import sys\nimport json\nimport random\nimport os\n\nfrom pocketbase import PocketBase\n\n# Connect to the PocketBase server\nclient = PocketBase(os.environ[\"CATALYST_APP_URL\"])\nclient.auth_store.save(token=os.environ[\"CATALYST_TOKEN\"])\n\nnewtickets = client.collection(\"tickets\").get_list(1, 200, {\"filter\": 'name = \"New Ticket\"'})\nfor ticket in newtickets.items:\n\tclient.collection(\"tickets\").delete(ticket.id)\n\n# Create a new ticket\nclient.collection(\"tickets\").create({\n\t\"name\": \"New Ticket\",\n\t\"type\": \"alert\",\n\t\"open\": True,\n})"}`
|
|
|
|
return map[string]map[string]map[string]any{
|
|
migrations.TicketCollectionName: {
|
|
"t_0": {
|
|
"created": dateTime(ticketCreated),
|
|
"updated": dateTime(ticketUpdated),
|
|
"name": "phishing-123",
|
|
"type": "alert",
|
|
"description": "Phishing email reported by several employees.",
|
|
"open": true,
|
|
"schema": types.JsonRaw(`{"type":"object","properties":{"tlp":{"title":"TLP","type":"string"}}}`),
|
|
"state": types.JsonRaw(`{"severity":"Medium"}`),
|
|
"owner": "u_test",
|
|
},
|
|
},
|
|
migrations.CommentCollectionName: {
|
|
"c_0": {
|
|
"created": dateTime(commentCreated),
|
|
"updated": dateTime(commentUpdated),
|
|
"ticket": "t_0",
|
|
"author": "u_test",
|
|
"message": "This is a test comment.",
|
|
},
|
|
},
|
|
migrations.TimelineCollectionName: {
|
|
"tl_0": {
|
|
"created": dateTime(timelineCreated),
|
|
"updated": dateTime(timelineUpdated),
|
|
"ticket": "t_0",
|
|
"time": dateTime(timelineCreated),
|
|
"message": "This is a test timeline message.",
|
|
},
|
|
},
|
|
migrations.TaskCollectionName: {
|
|
"ts_0": {
|
|
"created": dateTime(taskCreated),
|
|
"updated": dateTime(taskUpdated),
|
|
"ticket": "t_0",
|
|
"name": "This is a test task.",
|
|
"open": true,
|
|
"owner": "u_test",
|
|
},
|
|
},
|
|
migrations.LinkCollectionName: {
|
|
"l_0": {
|
|
"created": dateTime(linkCreated),
|
|
"updated": dateTime(linkUpdated),
|
|
"ticket": "t_0",
|
|
"url": "https://www.example.com",
|
|
"name": "This is a test link.",
|
|
},
|
|
},
|
|
migrations.ReactionCollectionName: {
|
|
"w_0": {
|
|
"created": dateTime(reactionCreated),
|
|
"updated": dateTime(reactionUpdated),
|
|
"name": "Create New Ticket",
|
|
"trigger": "schedule",
|
|
"triggerdata": types.JsonRaw(triggerSchedule),
|
|
"action": "python",
|
|
"actiondata": types.JsonRaw(createTicketActionData),
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func GenerateDefaultData(app core.App) error {
|
|
var records []*models.Record
|
|
|
|
// users
|
|
userRecord, err := testUser(app.Dao())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
records = append(records, userRecord)
|
|
|
|
// records
|
|
for collectionName, collectionRecords := range defaultData() {
|
|
collection, err := app.Dao().FindCollectionByNameOrId(collectionName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for id, fields := range collectionRecords {
|
|
record := models.NewRecord(collection)
|
|
record.SetId(id)
|
|
|
|
for key, value := range fields {
|
|
record.Set(key, value)
|
|
}
|
|
|
|
records = append(records, record)
|
|
}
|
|
}
|
|
|
|
for _, record := range records {
|
|
if err := app.Dao().SaveRecord(record); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func ValidateDefaultData(app core.App) error { //nolint:cyclop,gocognit
|
|
// users
|
|
userRecord, err := app.Dao().FindRecordById(migrations.UserCollectionName, "u_test")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to find user record: %w", err)
|
|
}
|
|
|
|
if userRecord == nil {
|
|
return errors.New("user not found")
|
|
}
|
|
|
|
if userRecord.Username() != "u_test" {
|
|
return fmt.Errorf(`username does not match: got %q, want "u_test"`, userRecord.Username())
|
|
}
|
|
|
|
if !userRecord.ValidatePassword("1234567890") {
|
|
return errors.New("password does not match")
|
|
}
|
|
|
|
if userRecord.Get("name") != "Test User" {
|
|
return fmt.Errorf(`name does not match: got %q, want "Test User"`, userRecord.Get("name"))
|
|
}
|
|
|
|
if userRecord.Get("email") != "user@catalyst-soar.com" {
|
|
return fmt.Errorf(`email does not match: got %q, want "user@catalyst-soar.com"`, userRecord.Get("email"))
|
|
}
|
|
|
|
if !userRecord.Verified() {
|
|
return errors.New("user is not verified")
|
|
}
|
|
|
|
// records
|
|
for collectionName, collectionRecords := range defaultData() {
|
|
for id, fields := range collectionRecords {
|
|
record, err := app.Dao().FindRecordById(collectionName, id)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to find record %s: %w", id, err)
|
|
}
|
|
|
|
if record == nil {
|
|
return errors.New("record not found")
|
|
}
|
|
|
|
for key, value := range fields {
|
|
got := record.Get(key)
|
|
|
|
if wantJSON, ok := value.(types.JsonRaw); ok {
|
|
if err := compareJSON(got, wantJSON); err != nil {
|
|
return fmt.Errorf("record field %q does not match: %w", key, err)
|
|
}
|
|
|
|
continue
|
|
}
|
|
|
|
if got != value {
|
|
return fmt.Errorf("record field %s does not match: got %v (%T), want %v (%T)", key, got, got, value, value)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func compareJSON(got any, wantJSON types.JsonRaw) error {
|
|
gotJSON, ok := got.(types.JsonRaw)
|
|
if !ok {
|
|
return fmt.Errorf("got %T, want %T", got, wantJSON)
|
|
}
|
|
|
|
if !jsonEqual(gotJSON.String(), wantJSON.String()) {
|
|
return fmt.Errorf("got %v, want %v", gotJSON, wantJSON)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func jsonEqual(a, b string) bool {
|
|
var objA, objB interface{}
|
|
|
|
if err := json.Unmarshal([]byte(a), &objA); err != nil {
|
|
return false
|
|
}
|
|
|
|
if err := json.Unmarshal([]byte(b), &objB); err != nil {
|
|
return false
|
|
}
|
|
|
|
return reflect.DeepEqual(objA, objB)
|
|
}
|
|
|
|
func dateTime(t time.Time) types.DateTime {
|
|
dt := types.DateTime{}
|
|
_ = dt.Scan(t)
|
|
|
|
return dt
|
|
}
|