First release of open core
This commit is contained in:
131
pkg/datastore/sqlite_tickets.go
Normal file
131
pkg/datastore/sqlite_tickets.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package datastore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
||||
)
|
||||
|
||||
func (s *SQLiteStore) GetTickets(ctx context.Context) ([]domain.Ticket, error) {
|
||||
rows, err := s.DB.QueryContext(ctx, "SELECT id, title, severity, status FROM tickets LIMIT 100")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var tickets []domain.Ticket
|
||||
for rows.Next() {
|
||||
var t domain.Ticket
|
||||
rows.Scan(&t.ID, &t.Title, &t.Severity, &t.Status)
|
||||
tickets = append(tickets, t)
|
||||
}
|
||||
return tickets, nil
|
||||
}
|
||||
|
||||
func (s *SQLiteStore) CreateTicket(ctx context.Context, t *domain.Ticket) error {
|
||||
if t.Status == "" {
|
||||
t.Status = "Waiting to be Triaged"
|
||||
}
|
||||
if t.Domain == "" {
|
||||
t.Domain = "Vulnerability"
|
||||
}
|
||||
if t.Source == "" {
|
||||
t.Source = "Manual"
|
||||
}
|
||||
if t.AssetIdentifier == "" {
|
||||
t.AssetIdentifier = "Default"
|
||||
}
|
||||
|
||||
rawHash := fmt.Sprintf("%s-%s-%s-%s", t.Source, t.AssetIdentifier, t.Title, t.Severity)
|
||||
hashBytes := sha256.Sum256([]byte(rawHash))
|
||||
t.DedupeHash = hex.EncodeToString(hashBytes[:])
|
||||
|
||||
query := `
|
||||
INSERT INTO tickets (
|
||||
domain, source, asset_identifier, title, description, recommended_remediation,
|
||||
severity, status, dedupe_hash,
|
||||
triage_due_date, remediation_due_date, created_at, updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, DATETIME('now', '+3 days'), DATETIME('now', '+14 days'), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
`
|
||||
|
||||
res, err := s.DB.ExecContext(ctx, query,
|
||||
t.Domain, t.Source, t.AssetIdentifier, t.Title, t.Description, t.RecommendedRemediation,
|
||||
t.Severity, t.Status, t.DedupeHash,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
id, _ := res.LastInsertId()
|
||||
t.ID = int(id)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateTicketInline handles a single UI edit and updates the flattened comment tracking
|
||||
func (s *SQLiteStore) UpdateTicketInline(ctx context.Context, ticketID int, severity, description, remediation, comment, actor, status, assignee string) error {
|
||||
query := `
|
||||
UPDATE tickets
|
||||
SET severity = ?, description = ?, recommended_remediation = ?,
|
||||
status = ?, assignee = ?,
|
||||
latest_comment = CASE WHEN ? != '' THEN ? ELSE latest_comment END,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?`
|
||||
|
||||
formattedComment := ""
|
||||
if comment != "" {
|
||||
formattedComment = "[" + actor + "] " + comment
|
||||
}
|
||||
|
||||
_, err := s.DB.ExecContext(ctx, query, severity, description, remediation, status, assignee, formattedComment, formattedComment, ticketID)
|
||||
return err
|
||||
}
|
||||
|
||||
// RejectTicketFromWrangler puts a ticket back into the Holding Pen
|
||||
func (s *SQLiteStore) RejectTicketFromWrangler(ctx context.Context, ticketIDs []int, reason, comment string) error {
|
||||
tx, err := s.DB.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
for _, id := range ticketIDs {
|
||||
fullComment := "[Wrangler Reject: " + reason + "] " + comment
|
||||
_, err := tx.ExecContext(ctx, "UPDATE tickets SET status = 'Returned to Security', assignee = 'Unassigned', latest_comment = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?", fullComment, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (s *SQLiteStore) GetTicketByID(ctx context.Context, id int) (domain.Ticket, error) {
|
||||
var t domain.Ticket
|
||||
var triageDue, remDue, created, updated string
|
||||
var patchedAt *string
|
||||
|
||||
query := `SELECT id, domain, source, asset_identifier, title, description, recommended_remediation, severity, status, dedupe_hash, triage_due_date, remediation_due_date, created_at, updated_at, patched_at, assignee, latest_comment FROM tickets WHERE id = ?`
|
||||
|
||||
err := s.DB.QueryRowContext(ctx, query, id).Scan(
|
||||
&t.ID, &t.Domain, &t.Source, &t.AssetIdentifier, &t.Title, &t.Description, &t.RecommendedRemediation, &t.Severity, &t.Status, &t.DedupeHash, &triageDue, &remDue, &created, &updated, &patchedAt, &t.Assignee, &t.LatestComment,
|
||||
)
|
||||
if err != nil {
|
||||
return t, err
|
||||
}
|
||||
|
||||
t.TriageDueDate, _ = time.Parse(time.RFC3339, triageDue)
|
||||
t.RemediationDueDate, _ = time.Parse(time.RFC3339, remDue)
|
||||
t.CreatedAt, _ = time.Parse(time.RFC3339, created)
|
||||
t.UpdatedAt, _ = time.Parse(time.RFC3339, updated)
|
||||
|
||||
if patchedAt != nil {
|
||||
pTime, _ := time.Parse(time.RFC3339, *patchedAt)
|
||||
t.PatchedAt = &pTime
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
Reference in New Issue
Block a user