perf(server): scope /.profile/access?path= to the requested location only
enumerateAccess always computed the global summary — every project (EnumerateProjects) and every admin subtree (enumerateAdminSubtrees tree walk) — and merely appended the path-scoped fields when ?path= was given. The browse hovercard calls this per folder hovered, so each distinct folder paid a full global enumeration for data it never reads. Split the two: a ?path= query now returns ONLY identity + path_verbs/ path_is_admin/path_can_elevate_grant/path_roles and skips the tree walks; the no-path call still returns the full global view for the profile page. Verified all path-scoped consumers (browse hovercard, form, tables) read only path_* fields; the global consumers (elevation, stage, plan-review, accept-transmittal) all call without ?path=. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
91e6d1ec82
commit
1cf3f3a9b3
2 changed files with 21 additions and 6 deletions
|
|
@ -197,10 +197,22 @@ type AccessView struct {
|
|||
// silently ignored (the global fields still return).
|
||||
func enumerateAccess(ctx context.Context, decider policy.Decider, cfg config.Config, p zddc.Principal, pathQuery string) AccessView {
|
||||
view := AccessView{
|
||||
Email: p.Email,
|
||||
EmailHeader: cfg.EmailHeader,
|
||||
IsSuperAdmin: zddc.IsAdmin(cfg.Root, p),
|
||||
Email: p.Email,
|
||||
EmailHeader: cfg.EmailHeader,
|
||||
}
|
||||
|
||||
// Path-scoped query: return ONLY the access for THIS location. The
|
||||
// global summary (every project, every admin subtree) requires tree
|
||||
// walks that are irrelevant to "what can I do here?" — and the
|
||||
// hovercard calls this per folder, so paying that cost per hover
|
||||
// would be wasteful. Callers that want the global view omit ?path=.
|
||||
if pathQuery != "" {
|
||||
populatePathScopedAccess(ctx, decider, cfg, p, pathQuery, &view)
|
||||
return view
|
||||
}
|
||||
|
||||
// Global summary (the profile page).
|
||||
view.IsSuperAdmin = zddc.IsAdmin(cfg.Root, p)
|
||||
view.Projects, _ = EnumerateProjects(ctx, decider, cfg, p)
|
||||
view.AdminSubtrees = enumerateAdminSubtrees(cfg, p)
|
||||
view.HasAnyAdminScope = view.IsSuperAdmin || len(view.AdminSubtrees) > 0
|
||||
|
|
@ -216,9 +228,6 @@ func enumerateAccess(ctx context.Context, decider policy.Decider, cfg config.Con
|
|||
allowed, _ := policy.AllowActionFromChainP(ctx, decider, rootChain, p, "/", policy.ActionCreate)
|
||||
view.CanCreateProject = allowed
|
||||
}
|
||||
if pathQuery != "" {
|
||||
populatePathScopedAccess(ctx, decider, cfg, p, pathQuery, &view)
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -540,6 +540,12 @@ acl:
|
|||
if alice.PathVerbs != "rw" {
|
||||
t.Errorf("alice PathVerbs = %q, want rw", alice.PathVerbs)
|
||||
}
|
||||
// A path-scoped query returns ONLY the access for this location — the
|
||||
// global summary (projects + admin-subtree walks) is omitted.
|
||||
if len(alice.Projects) != 0 || len(alice.AdminSubtrees) != 0 || alice.CanCreateProject {
|
||||
t.Errorf("path-scoped response leaked global fields: Projects=%d AdminSubtrees=%d CanCreateProject=%v",
|
||||
len(alice.Projects), len(alice.AdminSubtrees), alice.CanCreateProject)
|
||||
}
|
||||
if alice.PathIsAdmin {
|
||||
t.Errorf("alice PathIsAdmin = true, want false")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue