package api import ( "net/http" "net/http/httptest" "strings" "testing" ) func TestPortOperatorLogAccessAndExportAreDenied(t *testing.T) { handler := NewRouter(newPasswordAuthTestStore(t, fixedClock)) getJSONAs(t, handler, http.MethodPost, "/api/v1/auth/users", `{"username":"logoperator","password":"strong-pass-123","role":"port_operator","force_change":false,"port_permissions":[{"channel":"CH18","access":"read"},{"channel":"CH01","access":"deny"}]}`, "mock-admin") session := getJSON(t, handler, http.MethodPost, "/api/v1/auth/login", `{"username":"logoperator","password":"strong-pass-123"}`) token := session["session_token"].(string) for _, tc := range []struct { method, path, body string status int }{ {"GET", "/api/v1/logs/port?channel=CH18", "", 403}, {"GET", "/api/v1/logs/port", "", 403}, {"GET", "/api/v1/logs/port?channel=CH01", "", 403}, {"GET", "/api/v1/logs/system", "", 403}, {"POST", "/api/v1/logs/export/download", `{"log_type":"system","format":"csv"}`, 403}, {"POST", "/api/v1/logs/export/download", `{"log_type":"port","channel":"CH01","format":"csv"}`, 403}, {"POST", "/api/v1/logs/export/download", `{"log_type":"port","channel":"CH18","format":"csv"}`, 403}, {"POST", "/api/v1/logs/export", `{"log_type":"port","channel":"CH18","format":"csv"}`, 403}, {"POST", "/api/v1/logs/port/clear", `{"channel":"CH18","confirm":"CH18"}`, 403}, {"PATCH", "/api/v1/logs/retention", `{"port_days":30}`, 403}, } { t.Run(tc.method+tc.path+tc.body, func(t *testing.T) { r := httptest.NewRequest(tc.method, tc.path, strings.NewReader(tc.body)) r.Header.Set("Authorization", "Bearer "+token) r.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != tc.status { t.Fatalf("status %d want %d: %s", w.Code, tc.status, w.Body.String()) } }) } }