package api import ( "context" "net/http" "net/http/httptest" "strings" "testing" "tera-clone/services/tera-api/internal/adapters/mock" "tera-clone/services/tera-api/internal/domain" ) func TestPortLogClearRequiresAdminExactTargetAndConfirmation(t *testing.T) { store := mock.NewStore(fixedClock) for _, ch := range []string{"CH01", "CH02"} { if _, err := store.RecordPortLog(context.Background(), domain.PortLogEvent{Channel: ch, EventType: "command", Command: "show version", ReturnValue: "ok", Message: "command completed", Actor: "tester"}); err != nil { t.Fatal(err) } } handler := NewRouter(store) for _, tc := range []struct { actor, body string status int }{ {"mock-port-operator", `{"channel":"CH01","confirmation":"CH01"}`, 403}, {"mock-admin", `{"channel":"CH01"}`, 400}, {"mock-admin", `{"channel":"","confirmation":""}`, 400}, {"mock-admin", `{"channel":"CH01","confirmation":"CH02"}`, 400}, {"mock-admin", `{"channel":"../audit","confirmation":"../audit"}`, 400}, {"mock-admin", `{"channel":"CH01","confirmation":"CH01","class":"audit"}`, 400}, } { req := httptest.NewRequest(http.MethodPost, "/api/v1/logs/port/clear", strings.NewReader(tc.body)) req.Header.Set("X-Mock-Actor", tc.actor) res := httptest.NewRecorder() handler.ServeHTTP(res, req) if res.Code != tc.status { t.Fatalf("clear %s = %d: %s", tc.actor, res.Code, res.Body.String()) } } result := getJSONAs(t, handler, http.MethodPost, "/api/v1/logs/port/clear", `{"channel":"CH01","confirmation":"CH01"}`, "mock-admin") if result["deleted"] != float64(1) || result["channel"] != "CH01" { t.Fatalf("clear result = %+v", result) } rows, err := store.PortLogEvents(context.Background(), domain.PortLogFilter{}) if err != nil || len(rows) != 1 || rows[0].Channel != "CH02" { t.Fatalf("remaining logs = %+v, %v", rows, err) } audit, err := store.AuditEvents(context.Background()) if err != nil { t.Fatal(err) } found := false for _, event := range audit { if event.Action == "log.port.clear" && event.Target == "CH01" && event.Result == "succeeded" { found = true } } if !found { t.Fatal("successful deletion is not audited") } }