Pulse/internal/notifications/notifications_security_http_test.go
2026-02-04 10:28:41 +00:00

152 lines
4.3 KiB
Go

package notifications
import (
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestSendAppriseViaHTTPEmptyServerURL(t *testing.T) {
nm := NewNotificationManager("")
defer nm.Stop()
err := nm.sendAppriseViaHTTP(AppriseConfig{TimeoutSeconds: 1}, "title", "body", "info")
if err == nil || !strings.Contains(err.Error(), "server URL is not configured") {
t.Fatalf("expected missing server URL error, got %v", err)
}
}
func TestSendAppriseViaHTTPInvalidScheme(t *testing.T) {
nm := NewNotificationManager("")
defer nm.Stop()
err := nm.sendAppriseViaHTTP(AppriseConfig{ServerURL: "ftp://example.com", TimeoutSeconds: 1}, "title", "body", "info")
if err == nil || !strings.Contains(err.Error(), "must start with http or https") {
t.Fatalf("expected scheme validation error, got %v", err)
}
}
func TestSendAppriseViaHTTPSkipTLSVerifyAndDefaultHeader(t *testing.T) {
nm := NewNotificationManager("")
defer nm.Stop()
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if got := r.Header.Get("X-API-KEY"); got != "secret" {
t.Fatalf("expected default API key header, got %q", got)
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"ok":true}`))
}))
defer server.Close()
if err := nm.UpdateAllowedPrivateCIDRs("127.0.0.1/32"); err != nil {
t.Fatalf("allowlist: %v", err)
}
err := nm.sendAppriseViaHTTP(AppriseConfig{
ServerURL: server.URL,
SkipTLSVerify: true,
APIKey: "secret",
TimeoutSeconds: 2,
}, "title", "body", "info")
if err != nil {
t.Fatalf("expected HTTPS request to succeed, got %v", err)
}
}
func TestSendAppriseViaHTTPIncludesTargetsAndCustomHeader(t *testing.T) {
nm := NewNotificationManager("")
defer nm.Stop()
type payload struct {
Body string `json:"body"`
Title string `json:"title"`
Type string `json:"type"`
URLs []string `json:"urls"`
}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if got := r.Header.Get("X-Test-Key"); got != "secret" {
t.Fatalf("expected custom API key header, got %q", got)
}
if !strings.Contains(r.URL.Path, "/notify/") {
t.Fatalf("expected notify path, got %q", r.URL.Path)
}
var p payload
if err := json.NewDecoder(r.Body).Decode(&p); err != nil {
t.Fatalf("decode payload: %v", err)
}
if len(p.URLs) != 1 || p.URLs[0] != "discord://token" {
t.Fatalf("expected urls in payload, got %#v", p.URLs)
}
if p.Type != "warning" {
t.Fatalf("expected notify type warning, got %q", p.Type)
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"ok":true}`))
}))
defer server.Close()
if err := nm.UpdateAllowedPrivateCIDRs("127.0.0.1/32"); err != nil {
t.Fatalf("allowlist: %v", err)
}
err := nm.sendAppriseViaHTTP(AppriseConfig{
ServerURL: server.URL,
ConfigKey: "config key",
APIKey: "secret",
APIKeyHeader: "X-Test-Key",
Targets: []string{"discord://token"},
TimeoutSeconds: 2,
}, "title", "body", "warning")
if err != nil {
t.Fatalf("expected HTTP request to succeed, got %v", err)
}
}
func TestSendAppriseViaHTTPStatusErrorWithBody(t *testing.T) {
nm := NewNotificationManager("")
defer nm.Stop()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("boom"))
}))
defer server.Close()
if err := nm.UpdateAllowedPrivateCIDRs("127.0.0.1/32"); err != nil {
t.Fatalf("allowlist: %v", err)
}
err := nm.sendAppriseViaHTTP(AppriseConfig{
ServerURL: server.URL,
TimeoutSeconds: 2,
}, "title", "body", "info")
if err == nil || !strings.Contains(err.Error(), "HTTP 500") {
t.Fatalf("expected status error with body, got %v", err)
}
}
func TestSendAppriseViaHTTPStatusErrorWithoutBody(t *testing.T) {
nm := NewNotificationManager("")
defer nm.Stop()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
}))
defer server.Close()
if err := nm.UpdateAllowedPrivateCIDRs("127.0.0.1/32"); err != nil {
t.Fatalf("allowlist: %v", err)
}
err := nm.sendAppriseViaHTTP(AppriseConfig{
ServerURL: server.URL,
TimeoutSeconds: 2,
}, "title", "body", "info")
if err == nil || !strings.Contains(err.Error(), "HTTP 500") {
t.Fatalf("expected status error, got %v", err)
}
}