save first version
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
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")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user