Skip to content

Follow-ups to the explicit checkout context (#932 review items 7-10) - #933

Merged
KrzysztofPajak merged 8 commits into
developfrom
refactor/business-explicit-context-checkout-followups
Oct 17, 2026
Merged

KrzysztofPajak merged 8 commits into
developfrom
refactor/business-explicit-context-checkout-followups

Conversation

@KrzysztofPajak

Copy link
Copy Markdown
Member

Resolves review items 7-10 of #932
Type: feature

Issue

The #932 review left four items for a separate PR:

  1. ExternalAuthenticationService still read IContextAccessor for the request customer and store: in Authenticate, in the login path (CustomerLoggedInEvent), in registration (RegistrationRequest, CustomerRegisteredEvent) and in the provider availability checks. LoadActiveAuthenticationProviders(customer, store) took both values but ignored them.
  2. Cache keys join the customer group ids in stored order, so the same set of groups in another order made a separate cache entry (checkout attributes, and the Catalog keys too).
  3. GetShoppingCartHandler took everything from the request except the host, which it read from IContextAccessor.
  4. About 40 call sites repeated GetShoppingCart(contextAccessor.WorkContext.CurrentCustomer, contextAccessor.StoreContext.CurrentStore.Id, ...).

Solution

One commit per item:

  • External authentication: Authenticate, LoadActiveAuthenticationProviders and AuthenticationProviderIsAvailable take the customer and store. The service no longer injects IContextAccessor. Facebook, Google, OpenID Connect (controller and sign-out provider), the panel login page and GetInfoHandler pass the request values.
  • Group ids: GetCustomerGroupIds() returns the ids sorted (ordinal). Every key built from it is fixed in one place; the ACL filters only test membership.
  • Host: GetShoppingCart.Host, set by the nine senders in ShoppingCartController. The handler no longer injects IContextAccessor.
  • Helper: shoppingCartService.GetCurrentCart(contextAccessor, params ShoppingCartType[]) in Grand.Web.Common.Extensions, next to CalculationContext(), used at all 40 call sites (controllers, view components, UpdateQuantityValidator, ShoppingCartLinks.cshtml, BrainTree).

Breaking changes

  • IExternalAuthenticationService.Authenticate(parameters, customer, store, returnUrl), LoadActiveAuthenticationProviders(customer, store) (no defaults) and AuthenticationProviderIsAvailable(systemName, customer, store). External-auth plugins outside this repository must pass the request customer and store.
  • ExternalAuthenticationService, GetShoppingCartHandler and OidcSignOutProvider constructors changed.
  • GetCustomerGroupIds() now returns the ids sorted; Customer.Groups itself is not reordered.

Testing

Automated: the solution builds; Authentication, Catalog, Checkout, Domain, Web.Common, Web, Web.Admin and Modules test projects pass. New tests cover the login event and registration using the passed customer and store, the same cache key for groups in another order (checkout attributes, categories), the sort itself, and GetCurrentCart.

Manual:

  1. With Google or Facebook sign-in configured, add a product to the cart as a guest, sign in with the provider: the cart is merged into the account.
  2. Sign in with a provider for an identity not seen before: the account is registered in the current store and signed in.
  3. Admin login page: provider sign-in buttons still appear when a panel provider is active.
  4. Add a checkout attribute of type file upload, upload a file on the cart page: the download link in the attribute summary points to the current store host.
  5. Cart, wishlist, mini cart counters, checkout steps and the estimate shipping box work as before.

support added 4 commits October 16, 2026 23:12
ExternalAuthenticationService read the request customer and store from
IContextAccessor in Authenticate, in the registration and login paths
(CustomerLoggedInEvent, RegistrationRequest) and in the provider
availability checks. LoadActiveAuthenticationProviders took a customer and
a store but ignored both. The callers (Facebook, Google and OpenID Connect
controllers, the sign-out provider, the panel login page and the customer
info handler) now pass them, and the service no longer depends on the
ambient context.
GetCustomerGroupIds returned the groups in the order they are stored, and
about 30 cache keys (checkout attributes, categories, product mappings,
menus, search, home page blocks) join that list. The same set of groups
in another order therefore made a separate cache entry. Sorting once in
GetCustomerGroupIds fixes every key; the ACL filters only test membership.
GetShoppingCartHandler took the customer, store, language and currency
from the request, but read the host for checkout attribute download links
from IContextAccessor. The host is now a property of GetShoppingCart, set
by every sender, and the handler no longer depends on the ambient context.
About 40 call sites in controllers, view components, a validator, a
Razor partial and the BrainTree plugin repeated
GetShoppingCart(contextAccessor.WorkContext.CurrentCustomer,
contextAccessor.StoreContext.CurrentStore.Id, ...). The Grand.Web.Common
extension GetCurrentCart(contextAccessor, ...) reads both from the request,
next to CalculationContext(). Behavior is unchanged.
Copilot AI balanced review requested due to automatic review settings October 16, 2026 21:13

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.

support added 4 commits October 17, 2026 06:30
LoadActiveAuthenticationProviders and AuthenticationProviderIsAvailable
treated a null customer or store as allowed by every group and store
limit. GetShoppingCartHandler formatted checkout attribute download links
with a host nothing required. All three now throw on null, as Authenticate
already does.
The nine senders in ShoppingCartController repeated the customer,
currency, language, tax display, store and host lines; ShoppingCartRequest
fills them once.
SidebarWishlist and Index filtered the wishlist by hand, keeping items of
deleted products that every other wishlist read drops. The header partial
loaded the cart twice to count cart and wishlist items; it loads both types
once and sums them in memory.
UpdateQuantityValidator picked the permission from the cart type in the
request, not from the item it found. It now checks the wishlist or shopping
cart permission of the item itself.
@KrzysztofPajak
KrzysztofPajak merged commit fc5cf0b into develop Oct 17, 2026
9 checks passed
@KrzysztofPajak
KrzysztofPajak deleted the refactor/business-explicit-context-checkout-followups branch October 17, 2026 04:46
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