package service import ( "net/http" "net/http/httptest" "strings" "testing" "time" ) func TestOperationLogCapturesAdminMutationAndRedactsSecrets(t *testing.T) { service, err := NewService(t.TempDir()+"/onelink_mock.db") if err != nil { t.Fatal(err) } req := httptest.NewRequest(http.MethodPost, "/api/appids", strings.NewReader(`{"appid":"demo","password":"plain-secret","name":"演示"}`)) req.RemoteAddr = "192.0.2.10:1234" req.Header.Set("Content-Type", "application/json") res := httptest.NewRecorder() service.Router().ServeHTTP(res, req) if res.Code != http.StatusOK { t.Fatalf("status = %d body = %s", res.Code, res.Body.String()) } page := service.operationLogs.Query("", "管理台", "success", 1, 20) if page.Total != 1 || page.Items[0].Action != "新增 AppID" { t.Fatalf("logs = %#v", page.Items) } if strings.Contains(page.Items[0].Params, "plain-secret") || !strings.Contains(page.Items[0].Params, "***") { t.Fatalf("secret was not redacted: %s", page.Items[0].Params) } } func TestOperationLogQueryReturnsNewestFirst(t *testing.T) { store := newOperationLogStore(func() time.Time { return time.Date(2026, 8, 13, 10, 0, 0, 0, time.Local) }) store.Add(OperationLog{Category: "管理台", Action: "第一条", Result: "success"}) store.Add(OperationLog{Category: "管理台", Action: "第二条", Result: "success"}) page := store.Query("", "", "", 1, 1) if page.Total != 2 || len(page.Items) != 1 || page.Items[0].Action != "第二条" { t.Fatalf("page = %#v", page) } }