121 lines
2.7 KiB
Go
121 lines
2.7 KiB
Go
package transcript
|
|
|
|
import (
|
|
"bytes"
|
|
"html/template"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/leolionad58/ticketbot/internal/db"
|
|
)
|
|
|
|
func makeTicket() *db.Ticket {
|
|
return &db.Ticket{
|
|
ID: 1,
|
|
TicketNumber: 1,
|
|
Type: "support",
|
|
Panel: "support_panel",
|
|
ChannelID: "ch123456",
|
|
UserID: "user123",
|
|
OpenedAt: time.Now(),
|
|
Status: "open",
|
|
}
|
|
}
|
|
|
|
func TestTemplateRender(t *testing.T) {
|
|
ticket := makeTicket()
|
|
tmpl, err := template.New("t").Parse(HTMLTemplate)
|
|
if err != nil {
|
|
t.Fatalf("parse template: %v", err)
|
|
}
|
|
|
|
messages := []Message{
|
|
{
|
|
AuthorName: "TestUser",
|
|
AuthorInitial: "T",
|
|
Content: template.HTML("Hello world"),
|
|
Timestamp: "01/01/2024 12:00:00",
|
|
},
|
|
}
|
|
|
|
data := struct {
|
|
Ticket *db.Ticket
|
|
Messages []Message
|
|
Generated string
|
|
}{Ticket: ticket, Messages: messages, Generated: "test"}
|
|
|
|
var buf bytes.Buffer
|
|
if err := tmpl.Execute(&buf, data); err != nil {
|
|
t.Fatalf("execute template: %v", err)
|
|
}
|
|
|
|
dir := t.TempDir()
|
|
outPath := filepath.Join(dir, "support-0001-ch123456.html")
|
|
os.WriteFile(outPath, buf.Bytes(), 0644)
|
|
|
|
content, _ := os.ReadFile(outPath)
|
|
if !bytes.Contains(content, []byte("support-0001")) {
|
|
t.Error("missing ticket reference")
|
|
}
|
|
if !bytes.Contains(content, []byte("TestUser")) {
|
|
t.Error("missing author name")
|
|
}
|
|
if !bytes.Contains(content, []byte("Hello world")) {
|
|
t.Error("missing message content")
|
|
}
|
|
}
|
|
|
|
func TestXSSEscaping(t *testing.T) {
|
|
// renderMessage must escape all user-controlled content
|
|
// We test the escaping logic by simulating a message with XSS payload
|
|
msg := &struct {
|
|
Content string
|
|
Username string
|
|
}{
|
|
Content: "<script>alert('xss')</script>",
|
|
Username: "<b>user</b>",
|
|
}
|
|
|
|
escapedContent := template.HTMLEscapeString(msg.Content)
|
|
escapedName := template.HTMLEscapeString(msg.Username)
|
|
|
|
if escapedContent == msg.Content {
|
|
t.Error("content should be escaped")
|
|
}
|
|
if escapedName == msg.Username {
|
|
t.Error("username should be escaped")
|
|
}
|
|
if bytes.Contains([]byte(escapedContent), []byte("<script>")) {
|
|
t.Error("XSS payload not escaped in content")
|
|
}
|
|
}
|
|
|
|
func TestTemplateNoXSS(t *testing.T) {
|
|
ticket := makeTicket()
|
|
tmpl, _ := template.New("t").Parse(HTMLTemplate)
|
|
|
|
messages := []Message{
|
|
{
|
|
AuthorName: "<evil>",
|
|
AuthorInitial: "E",
|
|
Content: template.HTML(template.HTMLEscapeString("<script>alert(1)</script>")),
|
|
Timestamp: "01/01/2024 12:00:00",
|
|
},
|
|
}
|
|
|
|
data := struct {
|
|
Ticket *db.Ticket
|
|
Messages []Message
|
|
Generated string
|
|
}{Ticket: ticket, Messages: messages, Generated: "test"}
|
|
|
|
var buf bytes.Buffer
|
|
tmpl.Execute(&buf, data)
|
|
|
|
if bytes.Contains(buf.Bytes(), []byte("<script>alert")) {
|
|
t.Error("XSS: raw script tag in output")
|
|
}
|
|
}
|