add MFA, user web mail portal
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
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")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user