This function is not extensible, so other modules don't have a chance to say whether or not a user should be able to access the checkout page for the order they've specified. This problem manifests itself in the function baking in logic to do with the Cart order state even though Checkout does not have a dependency on Cart.

I think what needs to happen at the same time this function is made extensible is order statuses need to get an additional property similar to $order_status->cart that dictates whether or not orders in said status should be able to access the checkout completion page. This would be checked instead of disallowing at the end of the function orders in the Cart and Canceled states from viewing the checkout page... we simply can't know up front what other states this might apply to.

  elseif ($checkout_page->page_id == 'complete') {
    // Don't allow completion page access for orders in the cart or canceled states.
    if (in_array($order_status->state, array('canceled', 'cart'))) {
      return FALSE;
    }
  }

Comments

rszrama’s picture

StatusFileSize
new2.75 KB

Work in progress patch attached... this is tricky.

das-peter’s picture

Subscribe

alexiswatson’s picture

Been working on this for a client while attempting to sort out #1362412: commerce_checkout_access() blocks anonymous checkout. Above patch doesn't seem to apply to the latest dev cleanly, but the approach used in node_access seems to make the most sense here:

  // We grant access to the node if both of the following conditions are met:
  // - No modules say to deny access.
  // - At least one module says to grant access.
  // If no module specified either allow or deny, we fall back to the
  // node_access table.
  $access = module_invoke_all('node_access', $node, $op, $account);
  if (in_array(NODE_ACCESS_DENY, $access, TRUE)) {
    $rights[$account->uid][$cid][$op] = FALSE;
    return FALSE;
  }
  elseif (in_array(NODE_ACCESS_ALLOW, $access, TRUE)) {
    $rights[$account->uid][$cid][$op] = TRUE;
    return TRUE;
  }
  
  // (If no one else says yea or nay, more node_access() $stuff...)

This means we'll probably want constants for COMMERCE_CHECKOUT_ACCESS_ALLOW/DENY to distinguish between a hook implementation explicitly allowing/denying access and the absence of a response (in which case the default logic should take hold, with any DENY taking precedence in the event of conflicting implementations).

Time permitting I'll whip up another patch, but does this sound like a reasonable approach?

alexiswatson’s picture

Status: Active » Needs review
StatusFileSize
new2.19 KB

Patch operates much in the spirit of #1, though unless I'm mistaken it seems like we really want two hooks here: hook_commerce_checkout_access() to extend order-level access and hook_commerce_checkout_page_access() to extend page-level access. Both require implementors to use the same ALLOW/DENY constants. Review and feedback welcome.

tommy kaneko’s picture

I have made a patch for PayPal WPS using the above patch (comment #4).

See: #1350264: Completion message problem with anonymous users only

bripatand’s picture

Thanks for creating that patch. I needed it desperately for a custom module I developed which allows a user to impersonate another user during the checkout process . Commerce does not allow it by default.

BassistJimmyJam’s picture

I think #4 is headed in the right direction but I made a few changes and rolled a new patch. The changes include:

  • Remove the ALLOW/DENY constants and rely on TRUE/FALSE like the patch in #1. This is consistent with other access hooks including hook_commerce_entity_access.
  • Add the new hooks to commerce_checkout_hook_info() in order to allow lazy loading.
  • Took a stab at adding hook documentation in commerce_checkout.api.php.
alexiswatson’s picture

Thanks for the improvements! I actually used the constants to maintain consistency with hook_node_access and similar mechanisms in core after a bit of research, but I'm not hellbent on keeping them. It's just a matter of what we want to be consistent with.

EDIT: Looking back, do we want to handle IGNORE in a similar way?

BassistJimmyJam’s picture

In the current patch, ignore would be handled by returning NULL (or nothing). This is how it is handled in hook_commerce_entity_access() as well as several other access hooks outside of hook_node_access().

alexiswatson’s picture

Ah, I see. So long as we're being consistent. :]

One more for RTBC?

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

The patch from #7 makes a lot of sense to me, let's do this :)

rszrama’s picture

I'll give it another look, but I think we still need to move the Cart session variable checking into an implementation of this hook in commerce_cart.module. Might need to spin up a child issue to deal with the other aspect of the OP talking about what order statuses should have access to the checkout completion page.

alexbarrett’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Needs review
StatusFileSize
new5.89 KB

Here's a new patch based on #7 that includes moving the cart session variable checking into commerce_cart.module.

alexiswatson’s picture

Calls to the same method looking in the same place for only slightly different things smells a bit, but that's not an issue for this patch.

Approach looks sane, though.

alexbarrett’s picture

The double call to commerce_cart_order_session_exists() definitely smells a bit to me as well, but it's a far more pleasant smell than the one the session variable checks at the end of commerce_checkout_access() are giving off now. I think removing the double call would require changing the way the commerce_cart_order_session_* functions are implemented, which I agree is not an issue for this patch.

alexiswatson’s picture

Totally agree, on all counts.

More eyes for RTBC?

torgospizza’s picture

I'll see if I can test this soon. On our site it would be preferable to allow anonymous checkout, but prevent users coming through anonymously with PayPal EC from having an access denied, etc.

rlmumford’s picture

Status: Needs review » Reviewed & tested by the community

Tested against the latest dev and it all looks good!

Many +1's for getting this committed. We have several sites at the moment that are overriding the whole of 'commerce_checkout_router' just to get around this problem.