package app import ( "archive/zip" "bytes" "io" "net/http" "net/http/httptest" "os" "strings" "testing" "time" ) func TestWriteAuditWorkbookCreatesSafeExcelFile(t *testing.T) { t.Parallel() location, err := time.LoadLocation("America/Chicago") if err != nil { t.Fatal(err) } createdAt := time.Date(2026, time.July, 28, 20, 10, 32, 0, location) records := []auditRecord{{ EventType: "code_exchange_failed", CustomerLabel: "Acme & Sons", User: "taiadmin", Hostname: "=HYPERLINK(\"https://invalid.example\")", PackageSlug: "sentinelone-linux", SourceIP: "203.0.113.10", Details: "reason=code_not_found code_hint=ABCDE", CreatedAt: createdAt, }} var output bytes.Buffer if err := writeAuditWorkbook( &output, records, auditFilters{TimeRange: "all"}, createdAt, location, ); err != nil { t.Fatal(err) } if !bytes.HasPrefix(output.Bytes(), []byte("PK")) { t.Fatal("workbook is not a ZIP-based Excel file") } archive, err := zip.NewReader(bytes.NewReader(output.Bytes()), int64(output.Len())) if err != nil { t.Fatal(err) } required := map[string]bool{ "[Content_Types].xml": false, "xl/workbook.xml": false, "xl/styles.xml": false, "xl/worksheets/sheet1.xml": false, "xl/_rels/workbook.xml.rels": false, } var worksheet string for _, file := range archive.File { if _, ok := required[file.Name]; ok { required[file.Name] = true } if file.Name != "xl/worksheets/sheet1.xml" { continue } reader, err := file.Open() if err != nil { t.Fatal(err) } content, err := io.ReadAll(reader) _ = reader.Close() if err != nil { t.Fatal(err) } worksheet = string(content) } for file, found := range required { if !found { t.Errorf("workbook is missing %s", file) } } if !strings.Contains(worksheet, "Acme & Sons") { t.Fatal("worksheet text was not XML escaped") } if strings.Contains(worksheet, "") { t.Fatal("untrusted audit text must not be written as a formula") } if !strings.Contains(worksheet, `t="inlineStr"`) || !strings.Contains(worksheet, `=HYPERLINK`) { t.Fatal("formula-looking audit text was not preserved as a text cell") } if samplePath := os.Getenv("TAPM_AUDIT_SAMPLE_PATH"); samplePath != "" { if err := os.WriteFile(samplePath, output.Bytes(), 0o600); err != nil { t.Fatal(err) } } } func TestAuditExportReturnsAllRowsAndRecordsDownload(t *testing.T) { server, sessionToken := newAuthorizationTestServer(t) server.cfg.DisplayTimeZone = time.UTC for _, eventType := range []string{"older_event", "newer_event"} { if _, err := server.db.Exec( `INSERT INTO audit_events (event_type, details) VALUES (?, '')`, eventType, ); err != nil { t.Fatal(err) } } request := httptest.NewRequest(http.MethodGet, "/portal/audit/export?audit_range=all", nil) request.AddCookie(&http.Cookie{Name: sessionCookieName, Value: sessionToken}) response := httptest.NewRecorder() server.handleAuditExport(response, request) if response.Code != http.StatusOK { t.Fatalf("status = %d, body = %s", response.Code, response.Body.String()) } if contentType := response.Header().Get("Content-Type"); contentType != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" { t.Fatalf("content type = %q", contentType) } if disposition := response.Header().Get("Content-Disposition"); !strings.Contains( disposition, `attachment; filename="tapm-audit-`, ) { t.Fatalf("content disposition = %q", disposition) } archive, err := zip.NewReader( bytes.NewReader(response.Body.Bytes()), int64(response.Body.Len()), ) if err != nil { t.Fatal(err) } var worksheet string for _, file := range archive.File { if file.Name != "xl/worksheets/sheet1.xml" { continue } reader, err := file.Open() if err != nil { t.Fatal(err) } content, err := io.ReadAll(reader) _ = reader.Close() if err != nil { t.Fatal(err) } worksheet = string(content) } if !strings.Contains(worksheet, "older_event") || !strings.Contains(worksheet, "newer_event") { t.Fatal("complete export did not contain all retained audit rows") } var exportEvents int if err := server.db.QueryRow( `SELECT COUNT(*) FROM audit_events WHERE event_type = 'audit_exported'`, ).Scan(&exportEvents); err != nil { t.Fatal(err) } if exportEvents != 1 { t.Fatalf("audit_exported events = %d, want 1", exportEvents) } } func TestAuditExportRequiresTechnicianSession(t *testing.T) { server, _ := newAuthorizationTestServer(t) request := httptest.NewRequest(http.MethodGet, "/portal/audit/export?audit_range=all", nil) response := httptest.NewRecorder() server.Routes().ServeHTTP(response, request) if response.Code != http.StatusSeeOther { t.Fatalf("status = %d, want redirect", response.Code) } }