package webui import ( "net/http" "net/http/httptest" "strings" "testing" ) // TestScopedAdminCannotAccessServerSettingsOrLetsEncrypt guards against a regression // where a domain-scoped admin (delegated access to specific domains only, not a // global admin) could still read/change server-wide config that has nothing to do // with any one domain — the admin dashboard's own port, TLS certs, database URL, // Let's Encrypt/ACME credentials, etc. func TestScopedAdminCannotAccessServerSettingsOrLetsEncrypt(t *testing.T) { app := newTestApp(t) mux := app.Mux() domains, err := app.DB.ListDomains() if err != nil || len(domains) == 0 { t.Fatal("no seeded domain") } cookie := scopedLogin(t, app, "scoped-settings-admin", []int64{domains[0].ID}) routes := []struct { method, path string }{ {http.MethodGet, "/pymta-manager/settings"}, {http.MethodPost, "/pymta-manager/settings_update"}, {http.MethodGet, "/pymta-manager/letsencrypt"}, {http.MethodPost, "/pymta-manager/letsencrypt/save"}, {http.MethodPost, "/pymta-manager/letsencrypt/obtain"}, {http.MethodGet, "/pymta-manager/api/settings/get_public_ip"}, } for _, rt := range routes { req := httptest.NewRequest(rt.method, rt.path, nil) req.AddCookie(cookie) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) if rec.Code != http.StatusNotFound { t.Errorf("%s %s: status=%d, want 404 for a scoped admin", rt.method, rt.path, rec.Code) } } // A global admin must still reach these routes normally. globalCookie := loginSession(t, app) req := httptest.NewRequest(http.MethodGet, "/pymta-manager/settings", nil) req.AddCookie(globalCookie) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Errorf("global admin GET /settings: status=%d, want 200", rec.Code) } } // TestScopedAdminSidebarHidesServerWideLinks confirms the sidebar doesn't even show // Server Settings/Let's Encrypt to a scoped admin (backend enforcement is the real // gate, this is just the corresponding UI affordance). func TestScopedAdminSidebarHidesServerWideLinks(t *testing.T) { app := newTestApp(t) mux := app.Mux() domains, _ := app.DB.ListDomains() cookie := scopedLogin(t, app, "scoped-sidebar-admin", []int64{domains[0].ID}) req := httptest.NewRequest(http.MethodGet, "/pymta-manager/", nil) req.AddCookie(cookie) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Fatalf("dashboard: status=%d body=%s", rec.Code, rec.Body.String()) } body := rec.Body.String() if strings.Contains(body, `href="/pymta-manager/settings"`) { t.Error("scoped admin's sidebar should not link to Server Settings") } if strings.Contains(body, `href="/pymta-manager/letsencrypt"`) { t.Error("scoped admin's sidebar should not link to Let's Encrypt") } }