From ded9ff7883c3107b3758f62163edced5fb7cf162 Mon Sep 17 00:00:00 2001 From: ZDDC Date: Mon, 18 May 2026 09:29:23 -0500 Subject: [PATCH] refactor(handler): adminOnly helper for /.profile admin gates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Five identical 'if !zddc.IsAdmin { 404 }' guards on /whoami /config /logs /effective-policy /reindex collapse to a single adminOnly closure inside ServeProfile. Behavior unchanged — same 404-leakage property, same elevation-gated authority — just one site to audit instead of five. Co-Authored-By: Claude Opus 4.7 (1M context) --- zddc/internal/handler/profilehandler.go | 55 ++++++++++++++----------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/zddc/internal/handler/profilehandler.go b/zddc/internal/handler/profilehandler.go index 684ff3c..c1e6013 100644 --- a/zddc/internal/handler/profilehandler.go +++ b/zddc/internal/handler/profilehandler.go @@ -49,6 +49,21 @@ func ServeProfile(cfg config.Config, ring *LogRing, idx *archive.Index, w http.R email := EmailFromContext(r) + // adminOnly wraps an admin-gated sub-handler. Routes that need root- + // admin authority (sudo-style, elevation-gated) deny with 404 (not + // 403) so a non-admin probing the namespace can't enumerate which + // admin-only resources exist. Single helper instead of five copy- + // pasted gates. + adminOnly := func(fn http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if !zddc.IsAdmin(cfg.Root, PrincipalFromContext(r)) { + http.NotFound(w, r) + return + } + fn(w, r) + } + } + switch sub { case "/", "": serveProfilePage(cfg, w, r) @@ -57,35 +72,25 @@ func ServeProfile(cfg config.Config, ring *LogRing, idx *archive.Index, w http.R case "/projects": serveProfileProjectsCreate(cfg, w, r) case "/whoami": - if !zddc.IsAdmin(cfg.Root, PrincipalFromContext(r)) { - http.NotFound(w, r) - return - } - serveProfileWhoami(cfg, email, w, r) + adminOnly(func(w http.ResponseWriter, r *http.Request) { + serveProfileWhoami(cfg, email, w, r) + })(w, r) case "/config": - if !zddc.IsAdmin(cfg.Root, PrincipalFromContext(r)) { - http.NotFound(w, r) - return - } - serveProfileConfig(cfg, w, r) + adminOnly(func(w http.ResponseWriter, r *http.Request) { + serveProfileConfig(cfg, w, r) + })(w, r) case "/logs": - if !zddc.IsAdmin(cfg.Root, PrincipalFromContext(r)) { - http.NotFound(w, r) - return - } - serveProfileLogs(ring, w, r) + adminOnly(func(w http.ResponseWriter, r *http.Request) { + serveProfileLogs(ring, w, r) + })(w, r) case "/effective-policy": - if !zddc.IsAdmin(cfg.Root, PrincipalFromContext(r)) { - http.NotFound(w, r) - return - } - serveProfileEffectivePolicy(cfg, w, r) + adminOnly(func(w http.ResponseWriter, r *http.Request) { + serveProfileEffectivePolicy(cfg, w, r) + })(w, r) case "/reindex": - if !zddc.IsAdmin(cfg.Root, PrincipalFromContext(r)) { - http.NotFound(w, r) - return - } - serveProfileReindex(cfg, idx, email, w, r) + adminOnly(func(w http.ResponseWriter, r *http.Request) { + serveProfileReindex(cfg, idx, email, w, r) + })(w, r) default: http.NotFound(w, r) }