feat(models): add alert and box models

Adds comprehensive data structures for Alert and Box functionality across models.
This commit is contained in:
2026-04-30 19:45:22 +03:00
parent 2714907ff4
commit e103829870
16 changed files with 2359 additions and 10 deletions

View File

@@ -0,0 +1,155 @@
package server
import (
"encoding/json"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"warpbox/lib/metastore"
)
func TestAccountAlertsPageListsAndFiltersAlerts(t *testing.T) {
app, user := setupAccountTestApp(t)
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
createTestAlert(t, app, "601", metastore.AlertSeverityMedium, "thumbnail.generate.failed")
createTestAlert(t, app, "701", metastore.AlertSeverityHigh, "storage.connector.health_failed")
request := httptest.NewRequest(http.MethodGet, "/account/alerts?severity=high", nil)
request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token})
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
if response.Code != http.StatusOK {
t.Fatalf("expected alerts page, got %d body=%s", response.Code, response.Body.String())
}
body := response.Body.String()
if !strings.Contains(body, "storage.connector.health_failed") {
t.Fatal("expected high severity alert")
}
if strings.Contains(body, "thumbnail.generate.failed") {
t.Fatal("did not expect medium severity alert in high filter")
}
}
func TestAccountAlertAcknowledgeAndClose(t *testing.T) {
app, user := setupAccountTestApp(t)
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
alert := createTestAlert(t, app, "601", metastore.AlertSeverityMedium, "thumbnail.generate.failed")
response := postAlertAction(router, session, "/account/alerts/"+alert.ID+"/acknowledge", nil)
if response.Code != http.StatusSeeOther {
t.Fatalf("expected acknowledge redirect, got %d", response.Code)
}
updated, ok, err := app.store.GetAlert(alert.ID)
if err != nil || !ok {
t.Fatalf("GetAlert returned ok=%v err=%v", ok, err)
}
if updated.Status != metastore.AlertStatusAcknowledged {
t.Fatalf("expected acknowledged alert, got %s", updated.Status)
}
response = postAlertAction(router, session, "/account/alerts/"+alert.ID+"/close", nil)
if response.Code != http.StatusSeeOther {
t.Fatalf("expected close redirect, got %d", response.Code)
}
updated, ok, err = app.store.GetAlert(alert.ID)
if err != nil || !ok {
t.Fatalf("GetAlert returned ok=%v err=%v", ok, err)
}
if updated.Status != metastore.AlertStatusClosed {
t.Fatalf("expected closed alert, got %s", updated.Status)
}
}
func TestAccountAlertManagePermissionDenied(t *testing.T) {
app, _ := setupAccountTestApp(t)
regular, err := app.store.CreateUserWithPassword("regular-alerts", "regular-alerts@example.test", "secret", nil)
if err != nil {
t.Fatalf("CreateUserWithPassword returned error: %v", err)
}
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, regular)
alert := createTestAlert(t, app, "601", metastore.AlertSeverityMedium, "thumbnail.generate.failed")
response := postAlertAction(router, session, "/account/alerts/"+alert.ID+"/acknowledge", nil)
if response.Code != http.StatusForbidden {
t.Fatalf("expected permission denied, got %d", response.Code)
}
}
func TestDashboardUsesRealAlertCount(t *testing.T) {
app, user := setupAccountTestApp(t)
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
createTestAlert(t, app, "601", metastore.AlertSeverityMedium, "thumbnail.generate.failed")
request := httptest.NewRequest(http.MethodGet, "/account", nil)
request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token})
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
if response.Code != http.StatusOK {
t.Fatalf("expected dashboard, got %d", response.Code)
}
if !strings.Contains(response.Body.String(), "1 alerts") {
t.Fatal("expected dashboard alert chip/count")
}
if !strings.Contains(response.Body.String(), "Thumbnail alert") {
t.Fatal("expected dashboard alert preview")
}
}
func TestAccountAlertsExportJSON(t *testing.T) {
app, user := setupAccountTestApp(t)
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
createTestAlert(t, app, "601", metastore.AlertSeverityMedium, "thumbnail.generate.failed")
request := httptest.NewRequest(http.MethodGet, "/account/alerts/export.json", nil)
request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token})
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
if response.Code != http.StatusOK {
t.Fatalf("expected export success, got %d", response.Code)
}
var payload map[string]any
if err := json.Unmarshal(response.Body.Bytes(), &payload); err != nil {
t.Fatalf("Unmarshal returned error: %v", err)
}
if _, ok := payload["alerts"]; !ok {
t.Fatal("expected alerts export shape")
}
}
func createTestAlert(t *testing.T, app *App, code string, severity string, trace string) metastore.Alert {
t.Helper()
alert, err := app.store.CreateAlert(metastore.AlertInput{
Title: "Thumbnail alert",
Description: "Alert test description.",
Severity: severity,
Code: code,
Trace: trace,
Metadata: json.RawMessage(`{"box":"box-1","file":"photo.jpg"}`),
CreatedBy: "system",
})
if err != nil {
t.Fatalf("CreateAlert returned error: %v", err)
}
return alert
}
func postAlertAction(router http.Handler, session metastore.Session, path string, values url.Values) *httptest.ResponseRecorder {
if values == nil {
values = url.Values{}
}
values.Set("csrf_token", session.CSRFToken)
request := httptest.NewRequest(http.MethodPost, path, strings.NewReader(values.Encode()))
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token})
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
return response
}