Files
mailgoserver/internal/webui/settings_scope_test.go
T

79 lines
2.8 KiB
Go

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")
}
}