Repository navigation
fix(accounts): least-privilege accounts list for standard-user filter + plan prefill (closes #949, closes #951) - #987
Conversation
… + plan prefill (closes #949, closes #951) Standard / Read-Only user groups lack view:accounts, so GET /api/accounts 403s for them. This broke two flows: the global filter Account dropdown showed only "All Accounts" (#951, row 551), and the create-plan-from- commitment Target Account could not be pre-filled (the per-id account fetch 403'd), so Save Plan silently no-opped behind the empty-target guard with no error (#949, rows 547/548). Add a minimal-disclosure source these users CAN call, without exposing sensitive account config: - New GET /api/accounts/list returns [{id, name, external_id, provider}] gated on view:recommendations (held by both Standard and Read-Only groups), scoped by allowed_accounts. The full CloudAccount object (role ARNs, subscription IDs, client emails, auth modes) stays behind view:accounts on GET /api/accounts. - Wire the topbar filter dropdown, the plan-account search, and the commitment-target prefill to listAccountsMinimal. Row 550 banner: correct the nav name ("Settings" -> "Admin", renamed in #340) and scope the message to execute-purchases only, since standard users CAN create and manage plans. Same fix applied to the identical history banner. Tests: - backend: authz contract for /api/accounts/list (standard user allowed, view:accounts user still 403s on the full list, no view:recommendations -> 403, allowed_accounts scoping, no sensitive fields in the projection, router dispatch precedence over the generic prefix route). - frontend: standard-user dropdown populates from the minimal endpoint; plan modal prefills target via the minimal list; save-failure shows an error toast AND keeps the modal open; banner copy assertions for row 550.
|
Warning Review limit reached
More reviews will be available in 33 minutes and 30 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (15)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
1 similar comment
|
@coderabbitai review |
✅ Action performedReview finished.
|
✅ Action performedReview finished.
|
|
@coderabbitai review |
Summary
Fixes the Standard / Read-Only user account-access cluster (QA rows 547, 548, 550, 551). closes #949, closes #951.
Unified root cause: Standard / Read-Only groups lack
view:accounts, soGET /api/accounts403s for them, which broke two things:Approach (option a, least-privilege)
Add a minimal-disclosure accounts source these users CAN call, without exposing sensitive account config (no role ARNs, subscription IDs, client emails, auth modes, or the self-account marker).
Backend
GET /api/accounts/listreturning the minimal projection[{id, name, external_id, provider}], gated in-handler onview:recommendations(held by both Standard Users and Read-Only Users groups) rather than the admin-gradeview:accounts. Scoped byallowed_accountsexactly like the full list. The fullCloudAccountobject (role ARNs, subscription IDs, client emails) stays behindview:accountsonGET /api/accounts./api/accounts/GET prefix so "list" is not mistaken for an account:id.Frontend
api.listAccountsMinimal(). The prefill resolves the target client-side from the minimal list (no per-id endpoint needed).savePlanshows an error toast and keeps the modal open on failure); added a regression test asserting both halves of the bug(plans): create-plan reported no success/error feedback (QA standard user) — verify vs deploy lag #949 symptom.Row 550 banner
Endpoint authz
GET /api/accounts/list(new)view:recommendations{id, name, external_id, provider}, scopedGET /api/accounts(unchanged)view:accountsTests
internal/api/handler_accounts_test.go,..._router_test.go): standard user allowed; full-listview:accountsuser still 403s; noview:recommendations-> 403;allowed_accountsscoping; the JSON projection contains no sensitive fields; router dispatches/api/accounts/listto the minimal handler (notgetAccount).Verification
gofmt -lclean,go vet ./internal/...clean,go build ./...OK.go test ./internal/api/-> 1464 passed.npx tsc --noEmitclean;npx jest-> 2350 passed, 0 failed.SKIP=terraform_validate pre-commit run --all-files-> all passed (incl. the Go-defaults frontend-permissions regen, which made no changes).