Files
nezha_domains/cmd/dashboard/controller/frontend_fallback_api_tokens_test.go
T
naibaandcloudcode e8dabf5bc6 feat(auth): add PAT auth, scoped REST/MCP access, CSRF, and tenant isolation
Introduce Personal Access Tokens (nzp_*) as a stateless auth path alongside
JWT, gated per-endpoint by a scope middleware (nezha:{resource}:{verb}) with
fail-closed empty-scope defaults and a server-id whitelist. Self-management
endpoints (profile, api-tokens, oauth2 bind, refresh-token) explicitly reject
PATs to block privilege-escalation chains. A revoke registry tears down active
long-lived connections (terminal, fm, ws, transfer, mcp) the moment a PAT is
deleted, with a tombstone closing the revoke->register race.

Add an MCP endpoint that proxies tool calls (exec, fs read/write/delete,
transfer) to agents over gRPC, guarded by origin/DNS-rebinding checks, a
per-token rate limiter, audit logging, and a kill switch. Serialize all
sends through the IOStream wrapper to honour grpc-go's concurrency contract.

Add CSRF double-submit protection on unsafe cookie-authenticated methods,
exempting authenticated PAT requests by context identity (not a forgeable
Authorization header). Apply visibility/whitelist filtering consistently
across list, get-by-id, and mutate paths to enforce tenant isolation.

Migrate legacy mcp:* scopes: rewrite read/exec to nezha:* equivalents and
drop dangerous write/delete/wildcard grants.

Co-authored-by: cloudcode <cloudcode@users.noreply.github.com>
2026-05-30 15:56:44 +00:00

26 lines
956 B
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package controller
import (
"net/http"
"strings"
"testing"
)
// 前端在 main.tsx 注册了 /dashboard/settings/api-tokens,但后端 fallback 白名单
// 漏加这条会让用户直接刷新该页面拿到 HTTP 404body 还是 index.html)。
// controller.go 旁边的注释明确说「新增前端路由时必须在 main.tsx 与这里同步加」。
func TestFallbackToFrontend_APITokensRouteReturns200(t *testing.T) {
t.Chdir(t.TempDir())
router := newFrontendFallbackTestRouter(t)
w := performFrontendFallbackRequest(t, router, "/dashboard/settings/api-tokens")
if w.Code != http.StatusOK {
t.Fatalf("/dashboard/settings/api-tokens fallback status = %d, want 200 "+
"(front-end main.tsx registered the route — backend SPA fallback regex must mirror it)",
w.Code)
}
if !strings.Contains(w.Body.String(), "admin index") {
t.Fatalf("/dashboard/settings/api-tokens must serve admin index.html, got %q", w.Body.String())
}
}