From c4136cd8f36db8ed7d2871622853859fda439686 Mon Sep 17 00:00:00 2001 From: xuans Date: Thu, 24 Sep 2026 23:30:49 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AE=A1=E8=AE=A1=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E5=AD=97=E6=AE=B5=E6=A0=BC=E5=BC=8F=E4=B8=8E=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=A0=87=E8=AF=86=E5=B9=B6=E8=A1=A5=E5=85=85=E5=9B=9E?= =?UTF-8?q?=E5=BD=92=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/httpapi/task_api_test.go | 54 +++++++++++++++++++ backend/internal/repository/audit_reader.go | 4 +- .../internal/repository/audit_repository.go | 13 ++--- 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/backend/internal/httpapi/task_api_test.go b/backend/internal/httpapi/task_api_test.go index d72d167..0cb92e0 100644 --- a/backend/internal/httpapi/task_api_test.go +++ b/backend/internal/httpapi/task_api_test.go @@ -332,3 +332,57 @@ func TestIssueDomainSanitizesDeploymentReportWithoutTaskRepository(t *testing.T) t.Fatalf("直接证书申请响应未返回稳定部署错误摘要:%s", response.Body.String()) } } + +func TestAuditLogResponseUsesDashboardFieldNames(t *testing.T) { + server, _, auditRepo, closeDB := newTaskAPITestServer(t, nil) + defer closeDB() + ctx := context.Background() + createdAt := time.Date(2026, 9, 24, 12, 0, 0, 0, time.UTC) + for _, status := range []string{"success", "error"} { + if err := auditRepo.CreateAuditLog(ctx, repository.AuditLog{ + Action: "login", ResourceType: "auth", ResourceID: "admin", + Status: status, Message: "login", CreatedAt: createdAt, + }); err != nil { + t.Fatal(err) + } + } + response := httptest.NewRecorder() + serveAdminHTTP(server, response, httptest.NewRequest(http.MethodGet, "/api/v1/audit-logs?limit=2", nil)) + if response.Code != http.StatusOK { + t.Fatal(response.Code, response.Body.String()) + } + var payload struct { + Items []map[string]json.RawMessage `json:"items"` + } + if err := json.Unmarshal(response.Body.Bytes(), &payload); err != nil { + t.Fatal(err) + } + if len(payload.Items) != 2 { + t.Fatal(response.Body.String()) + } + var previousID int64 + for i, item := range payload.Items { + for _, field := range []string{"id", "action", "resource_type", "resource_id", "status", "message", "created_at"} { + if _, ok := item[field]; !ok { + t.Fatal(field, response.Body.String()) + } + } + if len(item) != 7 { + t.Fatal(response.Body.String()) + } + var id int64 + if err := json.Unmarshal(item["id"], &id); err != nil || id <= 0 || (i > 0 && id >= previousID) { + t.Fatal(id, previousID, err) + } + previousID = id + for field, expected := range map[string]string{ + "action": "login", "resource_type": "auth", "resource_id": "admin", + "status": []string{"error", "success"}[i], "message": "login", "created_at": createdAt.Format(time.RFC3339), + } { + var actual string + if err := json.Unmarshal(item[field], &actual); err != nil || actual != expected { + t.Fatal(field, actual, expected, err) + } + } + } +} diff --git a/backend/internal/repository/audit_reader.go b/backend/internal/repository/audit_reader.go index 834d3c8..23ed44e 100644 --- a/backend/internal/repository/audit_reader.go +++ b/backend/internal/repository/audit_reader.go @@ -18,7 +18,7 @@ func (r *SQLAuditRepository) ListAuditLogs(ctx context.Context, limit int) ([]Au if limit <= 0 || limit > 200 { limit = 50 } - rows, err := r.db.QueryContext(ctx, r.query(`SELECT action, resource_type, resource_id, status, message, created_at FROM audit_logs ORDER BY created_at DESC, id DESC LIMIT `+fmt.Sprintf("%d", limit))) + rows, err := r.db.QueryContext(ctx, r.query(`SELECT id, action, resource_type, resource_id, status, message, created_at FROM audit_logs ORDER BY created_at DESC, id DESC LIMIT `+fmt.Sprintf("%d", limit))) if err != nil { return nil, fmt.Errorf("查询审计日志失败:%w", err) } @@ -26,7 +26,7 @@ func (r *SQLAuditRepository) ListAuditLogs(ctx context.Context, limit int) ([]Au logs := make([]AuditLog, 0) for rows.Next() { var item AuditLog - if err := rows.Scan(&item.Action, &item.ResourceType, &item.ResourceID, &item.Status, &item.Message, &item.CreatedAt); err != nil { + if err := rows.Scan(&item.ID, &item.Action, &item.ResourceType, &item.ResourceID, &item.Status, &item.Message, &item.CreatedAt); err != nil { return nil, fmt.Errorf("读取审计日志失败:%w", err) } item.CreatedAt = item.CreatedAt.UTC() diff --git a/backend/internal/repository/audit_repository.go b/backend/internal/repository/audit_repository.go index c487a21..731cdcf 100644 --- a/backend/internal/repository/audit_repository.go +++ b/backend/internal/repository/audit_repository.go @@ -10,12 +10,13 @@ import ( ) type AuditLog struct { - Action string - ResourceType string - ResourceID string - Status string - Message string - CreatedAt time.Time + ID int64 `json:"id"` + Action string `json:"action"` + ResourceType string `json:"resource_type"` + ResourceID string `json:"resource_id"` + Status string `json:"status"` + Message string `json:"message"` + CreatedAt time.Time `json:"created_at"` } type AuditRepository interface {