Skip to content

fix(store): close AvailableStores cross-store leak in Customer controller - #821

Merged
KrzysztofPajak merged 1 commit into
developfrom
fix/customer-availablestores-store-leak
Sep 13, 2026
Merged

KrzysztofPajak merged 1 commit into
developfrom
fix/customer-availablestores-store-leak

Conversation

@KrzysztofPajak

Copy link
Copy Markdown
Member

Issue

Follow-up to ARCH-001 Phase 20 (Customer consolidation, #819). Code review of Phase 21 (EmailAccount, #820) caught the same class of bug there and, while auditing the rest of Grand.Web.AdminShared for the same pattern, found it also applies to Customer — already merged to develop.

BaseCustomerController.Create() / Edit(string id) always populate model.AvailableStores with every store's id/name via the shared PrepareCustomerModel call. Store's own CreateOrUpdate.TabInfo view gates the StaffStoreId/StoreId <select>s on Scope.DefaultStoreId is null and never renders either for Store — but the model still reaches Store's store_customer_details_* widget zones via additional-data="Model" (confirmed: WidgetZone.InfoTop.cshtml, WidgetZone.InfoBottom.cshtml, WidgetZone.DetailsTabs.cshtml, etc. all pass Model). A Store widget reading Model.AvailableStores could leak other stores' names/ids from a store-scoped screen.

Solution

Same fix pattern as BaseEmailAccountController in #820: clear AvailableStores under Store scope (scope.DefaultStoreId is not null) right after PrepareCustomerModel, on all four call sites (Create GET, Create POST redisplay, Edit GET, Edit POST redisplay) via a small private helper. No-op for Admin.

Testing

  • dotnet build src/Web/Grand.Web.AdminShared — 0 errors.
  • dotnet test src/Tests/Grand.Web.Admin.Tests --filter BaseCustomerControllerTests — 35/35 passing (31 existing + 4 new regression tests: Create/Edit GET keep AvailableStores under Admin scope, clear it under Store scope).
  • dotnet test src/Tests/Grand.Web.Store.Tests --filter Customer — 13/13 passing.

Breaking changes

None.

🤖 Generated with Claude Code

…ller

Follow-up to ARCH-001 Phase 20 (Customer consolidation, #819), same
class of issue caught during Phase 21 (EmailAccount, #820) code
review.

BaseCustomerController.Create()/Edit(string) always populate
model.AvailableStores with every store's id/name via the shared
PrepareCustomerModel call. Store's own CreateOrUpdate.TabInfo view
gates the StaffStoreId/StoreId <select>s on Scope.DefaultStoreId is
null and never renders them for Store - but the model still reaches
Store's store_customer_details_* widget zones via
additional-data="Model", so a future Store widget reading
Model.AvailableStores could leak other stores' names/ids from a
store-scoped screen.

Fix in the controller: clear AvailableStores under Store scope
(scope.DefaultStoreId is not null) right after PrepareCustomerModel,
on all four call sites (Create GET, Create POST redisplay, Edit GET,
Edit POST redisplay). No-op for Admin.

Adds regression coverage: Create/Edit GET keep AvailableStores under
Admin scope, clear it under Store scope.
Copilot AI lite review requested due to automatic review settings September 9, 2026 18:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KrzysztofPajak
KrzysztofPajak merged commit e28d2c5 into develop Sep 13, 2026
6 checks passed
@KrzysztofPajak
KrzysztofPajak deleted the fix/customer-availablestores-store-leak branch September 13, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants