fix(admin): omit unresolved tenant header

This commit is contained in:
zhx 2026-07-15 16:44:07 +08:00
parent d6801f9de2
commit e7389c1e74
2 changed files with 12 additions and 0 deletions

View File

@ -8,6 +8,8 @@ import (
"strings"
"testing"
adminmiddleware "hyapp-admin-server/internal/middleware"
"github.com/DATA-DOG/go-sqlmock"
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
@ -76,6 +78,9 @@ func TestLoginIgnoresLegacyRequestAppAndAuditsUnknownAccountWithoutTenant(t *tes
gin.SetMode(gin.TestMode)
engine := gin.New()
// Production installs the global App middleware before external routes. Login
// must remove its fallback "lalu" response header until credentials resolve.
engine.Use(adminmiddleware.AppCode())
handler := New(adminDB, nil, Config{}, nil, WithLoginRateLimiter(allowFixedWindowLimiter{}))
RegisterExternalRoutes(engine.Group("/api/v1"), handler, BusinessHandlers{})
request := httptest.NewRequest(http.MethodPost, "/api/v1/external/auth/login", strings.NewReader(`{"appCode":"lalu","account":"missing-operator","password":"wrong-password"}`))
@ -86,6 +91,9 @@ func TestLoginIgnoresLegacyRequestAppAndAuditsUnknownAccountWithoutTenant(t *tes
if responseRecorder.Code != http.StatusUnauthorized {
t.Fatalf("status=%d body=%s", responseRecorder.Code, responseRecorder.Body.String())
}
if got := responseRecorder.Header().Get("X-App-Code"); got != "" {
t.Fatalf("failed tenant-less login exposed default App header %q", got)
}
if !strings.Contains(responseRecorder.Body.String(), `"code":40100`) || strings.Contains(responseRecorder.Body.String(), "App") {
t.Fatalf("login response must expose only stable auth code and generic text: %s", responseRecorder.Body.String())
}

View File

@ -233,6 +233,10 @@ func (h *Handler) ListApps(c *gin.Context) {
}
func (h *Handler) Login(c *gin.Context) {
// The global App middleware supplies the main-admin default before this anonymous
// route runs. No tenant is authoritative until a credential row resolves, so do
// not leak or imply that default on malformed, throttled or failed login responses.
c.Writer.Header().Del(appctx.HeaderAppCode)
// Limit parsing memory before decoding untrusted credentials. Binding tags are
// intentionally absent on loginRequest: every syntactically valid JSON attempt,
// including missing fields, must reach the distributed limiter before rejection.