package service import ( "context" "errors" "fmt" "net/http" "github.com/arangodb/go-driver" "github.com/google/uuid" "github.com/SecurityBrewery/catalyst/bus" "github.com/SecurityBrewery/catalyst/database" "github.com/SecurityBrewery/catalyst/generated/api" "github.com/SecurityBrewery/catalyst/generated/model" ) func ticketWithTicketsID(ticketResponse *model.TicketWithTickets) []driver.DocumentID { if ticketResponse == nil { return nil } return ticketID(ticketResponse.ID) } func ticketID(ticketID int64) []driver.DocumentID { id := fmt.Sprintf("%s/%d", database.TicketCollectionName, ticketID) return []driver.DocumentID{driver.DocumentID(id)} } func ticketIDs(ticketResponses []*model.TicketResponse) []driver.DocumentID { var ids []driver.DocumentID for _, ticketResponse := range ticketResponses { ids = append(ids, ticketID(ticketResponse.ID)...) } return ids } func (s *Service) ListTickets(ctx context.Context, ticketType *string, offsetP, countP *int, sort []string, descending []bool, queryP *string) (*model.TicketList, error) { q := "" if queryP != nil && *queryP != "" { q = *queryP } t := "" if ticketType != nil && *ticketType != "" { t = *ticketType } offset := int64(0) if offsetP != nil { offset = int64(*offsetP) } count := int64(25) if countP != nil { count = int64(*countP) } return s.database.TicketList(ctx, t, q, sort, descending, offset, count) } func (s *Service) CreateTicket(ctx context.Context, form *model.TicketForm) (doc *model.TicketResponse, err error) { createdTickets, err := s.database.TicketBatchCreate(ctx, []*model.TicketForm{form}) defer s.publishRequest(ctx, err, "CreateTicket", ticketIDs(createdTickets)) if len(createdTickets) > 0 { return createdTickets[0], err } return nil, err } func (s *Service) CreateTicketBatch(ctx context.Context, ticketFormArray *model.TicketFormArray) error { if ticketFormArray == nil { return &api.HTTPError{Status: http.StatusUnprocessableEntity, Internal: errors.New("no tickets given")} } createdTickets, err := s.database.TicketBatchCreate(ctx, *ticketFormArray) defer s.publishRequest(ctx, err, "CreateTicket", ticketIDs(createdTickets)) return err } func (s *Service) GetTicket(ctx context.Context, i int64) (*model.TicketWithTickets, error) { return s.database.TicketGet(ctx, i) } func (s *Service) UpdateTicket(ctx context.Context, i int64, ticket *model.Ticket) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "UpdateTicket", ticketWithTicketsID(doc)) return s.database.TicketUpdate(ctx, i, ticket) } func (s *Service) DeleteTicket(ctx context.Context, i int64) (err error) { defer s.publishRequest(ctx, err, "DeleteTicket", ticketID(i)) return s.database.TicketDelete(ctx, i) } func (s *Service) AddArtifact(ctx context.Context, i int64, artifact *model.Artifact) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "AddArtifact", ticketWithTicketsID(doc)) return s.database.AddArtifact(ctx, i, artifact) } func (s *Service) GetArtifact(ctx context.Context, i int64, s2 string) (*model.Artifact, error) { return s.database.ArtifactGet(ctx, i, s2) } func (s *Service) SetArtifact(ctx context.Context, i int64, s2 string, artifact *model.Artifact) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "SetArtifact", ticketWithTicketsID(doc)) return s.database.ArtifactUpdate(ctx, i, s2, artifact) } func (s *Service) RemoveArtifact(ctx context.Context, i int64, s2 string) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "RemoveArtifact", ticketWithTicketsID(doc)) return s.database.RemoveArtifact(ctx, i, s2) } func (s *Service) EnrichArtifact(ctx context.Context, i int64, s2 string, form *model.EnrichmentForm) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "EnrichArtifact", ticketWithTicketsID(doc)) return s.database.EnrichArtifact(ctx, i, s2, form) } func (s *Service) RunArtifact(ctx context.Context, id int64, name string, automation string) error { artifact, err := s.database.ArtifactGet(ctx, id, name) if err != nil { return err } defer s.publishRequest(ctx, err, "RunArtifact", ticketID(id)) jobID := uuid.NewString() origin := &model.Origin{ArtifactOrigin: &model.ArtifactOrigin{TicketId: id, Artifact: name}} s.bus.JobChannel.Publish(&bus.JobMsg{ ID: jobID, Automation: automation, Origin: origin, Message: &model.Message{ Context: &model.Context{Artifact: artifact}, Payload: map[string]string{"default": name}, }, }) return nil } func (s *Service) AddComment(ctx context.Context, i int64, form *model.CommentForm) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "AddComment", ticketWithTicketsID(doc)) return s.database.AddComment(ctx, i, form) } func (s *Service) RemoveComment(ctx context.Context, i int64, i2 int) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "RemoveComment", ticketWithTicketsID(doc)) return s.database.RemoveComment(ctx, i, int64(i2)) } func (s *Service) AddTicketPlaybook(ctx context.Context, i int64, form *model.PlaybookTemplateForm) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "AddTicketPlaybook", ticketWithTicketsID(doc)) return s.database.AddTicketPlaybook(ctx, i, form) } func (s *Service) RemoveTicketPlaybook(ctx context.Context, i int64, s2 string) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "RemoveTicketPlaybook", ticketWithTicketsID(doc)) return s.database.RemoveTicketPlaybook(ctx, i, s2) } func (s *Service) SetTaskData(ctx context.Context, i int64, s3 string, s2 string, data map[string]any) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "SetTask", ticketWithTicketsID(doc)) return s.database.TaskUpdateData(ctx, i, s3, s2, data) } func (s *Service) SetTaskOwner(ctx context.Context, i int64, s3 string, s2 string, owner string) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "SetTask", ticketWithTicketsID(doc)) return s.database.TaskUpdateOwner(ctx, i, s3, s2, owner) } func (s *Service) CompleteTask(ctx context.Context, i int64, s3 string, s2 string, m map[string]any) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "CompleteTask", ticketWithTicketsID(doc)) return s.database.TaskComplete(ctx, i, s3, s2, m) } func (s *Service) RunTask(ctx context.Context, i int64, s3 string, s2 string) (err error) { defer s.publishRequest(ctx, err, "RunTask", ticketID(i)) return s.database.TaskRun(ctx, i, s3, s2) } func (s *Service) SetReferences(ctx context.Context, i int64, references *model.ReferenceArray) (doc *model.TicketWithTickets, err error) { if references == nil { return nil, &api.HTTPError{Status: http.StatusUnprocessableEntity, Internal: errors.New("no references given")} } defer s.publishRequest(ctx, err, "SetReferences", ticketID(i)) return s.database.SetReferences(ctx, i, *references) } func (s *Service) SetSchema(ctx context.Context, i int64, s2 string) (doc *model.TicketWithTickets, err error) { defer s.publishRequest(ctx, err, "SetSchema", ticketID(i)) return s.database.SetTemplate(ctx, i, s2) } func (s *Service) LinkTicket(ctx context.Context, i int64, i2 int64) (*model.TicketWithTickets, error) { err := s.database.RelatedCreate(ctx, i, i2) if err != nil { return nil, err } defer s.publishRequest(ctx, err, "LinkTicket", ticketID(i)) return s.GetTicket(ctx, i) } func (s *Service) UnlinkTicket(ctx context.Context, i int64, i2 int64) (*model.TicketWithTickets, error) { err := s.database.RelatedRemove(ctx, i, i2) if err != nil { return nil, err } defer s.publishRequest(ctx, err, "UnlinkTicket", ticketID(i)) return s.GetTicket(ctx, i) }