package handler import ( "net/http" "net/http/httptest" "testing" ) // TestServeAuthAdmin pins the contract of the forward_auth endpoint // used by upstream proxies (Caddy in the dev-shell pod) to gate // admin-only routes: // // 200 → caller is in the root .zddc admins: list // 403 → anonymous, OR not in admins:, OR no admins configured // // Reuses the profileTestRoot fixture which materializes a temp .zddc // with the supplied admins, and the requestWithEmail helper that // injects the email into request context the same way ACLMiddleware // would in production. func TestServeAuthAdmin(t *testing.T) { cfg, _ := profileTestRoot(t, []string{"alice@example.com"}) cases := []struct { name string email string wantStatus int }{ {"empty email is denied", "", http.StatusForbidden}, {"non-admin is denied", "bob@example.com", http.StatusForbidden}, {"admin is allowed", "alice@example.com", http.StatusOK}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { req := requestWithEmail(http.MethodGet, AuthPathPrefix+"/admin", tc.email) rec := httptest.NewRecorder() ServeAuthAdmin(cfg, rec, req) if rec.Code != tc.wantStatus { t.Errorf("status = %d, want %d (body: %q)", rec.Code, tc.wantStatus, rec.Body.String()) } }) } } // TestServeAuthAdmin_NoZddcRootDeniesEverything covers the bootstrap- // state behaviour: when no /srv/.zddc exists, IsAdmin returns false for // everyone, which means /.auth/admin returns 403 universally. This is // the desired safe-default before an operator drops a root .zddc onto // the share. func TestServeAuthAdmin_NoZddcRootDeniesEverything(t *testing.T) { // profileTestRoot with nil admins skips writing the file entirely. cfg, _ := profileTestRoot(t, nil) for _, email := range []string{"", "alice@example.com", "anyone@example.com"} { req := requestWithEmail(http.MethodGet, AuthPathPrefix+"/admin", email) rec := httptest.NewRecorder() ServeAuthAdmin(cfg, rec, req) if rec.Code != http.StatusForbidden { t.Errorf("email %q without .zddc: status %d, want 403", email, rec.Code) } } }