PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.17
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.17
1.10.25 1.10.24 1.10.23 1.10.22 1.10.21 1.10.20 1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 All 169 releases
← All changes | includes/API/V2/Write_Controller.php +48 -1 1.10.4 → 1.10.17 View file →
@@ -7,8 +7,9 @@
7 7
8 8 namespace WCPOS\WooCommercePOS\API\V2;
9 9
10 10 use WCPOS\WooCommercePOS\API\V2\Writers\Collection_Writer_Resolver;
11 +use WCPOS\WooCommercePOS\Services\Customer_Account_Guard;
11 12 use WCPOS\WooCommercePOS\Services\Tax_Id_Types;
12 13 use WCPOS\WooCommercePOS\Sync\Api;
13 14 use WCPOS\WooCommercePOS\Sync\Collections;
14 15 use WCPOS\WooCommercePOS\Sync\Endpoint_Permissions;
@@ -43,8 +44,15 @@
43 44 * live in an injected mutation store, so the apply logic is unit-testable with a
44 45 * fake store + a stubbed `rest_do_request`.
45 46 */
46 47 class Write_Controller extends WP_REST_Controller {
48 + /**
49 + * True while wc_rest_check_user_permissions() is re-run for a cleared target.
50 + *
51 + * @var bool
52 + */
53 + private $rejudging_user_target = false;
54 +
47 55 // Our gate (capability + F13 health); forwarded writes scope the client-tier grant below.
48 56 use Endpoint_Permissions;
49 57
50 58
@@ -759,10 +767,43 @@
759 767 }
760 768 }
761 769
762 770 /**
763 - * Authorize proxied catalog mutations for POS users.
771 + * Judge a customer edit or delete the way V1\Customers_Controller does.
764 772 *
773 + * The staff guard runs first and is final. A target it has cleared is then
774 + * re-judged by WooCommerce with the target's own roles allowed through the
775 + * shop_manager role-name restriction, so a shop manager can edit a subscriber
776 + * from a current app exactly as from the legacy route. WooCommerce's
777 + * credential fence is untouched: it runs in the controller, not here.
778 + *
779 + * @param bool $permission WooCommerce's verdict so far.
780 + * @param string $context 'edit' or 'delete'.
781 + * @param int $target_id Target user ID.
782 + */
783 + private function check_user_permission( bool $permission, string $context, int $target_id ): bool {
784 + if ( $this->rejudging_user_target ) {
785 + return $permission;
786 + }
787 + if ( ! Customer_Account_Guard::can_modify( get_current_user_id(), $target_id ) ) {
788 + return false;
789 + }
790 + if ( $permission ) {
791 + return true;
792 + }
793 + $this->rejudging_user_target = true;
794 + $restore = Customer_Account_Guard::allow_target_roles( $target_id );
795 + try {
796 + return (bool) wc_rest_check_user_permissions( $context, $target_id );
797 + } finally {
798 + $restore();
799 + $this->rejudging_user_target = false;
800 + }
801 + }
802 +
803 + /**
804 + * Authorize proxied mutations for POS users while protecting staff accounts.
805 + *
765 806 * This filter is attached only while a sync push is forwarded to wc/v3, so
766 807 * direct WooCommerce requests keep their normal permission checks.
767 808 *
768 809 * @param bool $permission The current permission.
@@ -772,8 +813,14 @@
772 813 *
773 814 * @return bool
774 815 */
775 816 public function wcpos_check_permissions( $permission, $context, $object_id, $post_type ) {
817 + // Customer edits/deletes: the staff guard is final, then a cleared target
818 + // is judged by WooCommerce the same way the v1 controller judges it.
819 + if ( 'user' === $post_type && (int) $object_id > 0 && \in_array( $context, array( 'edit', 'delete' ), true ) ) {
820 + return $this->check_user_permission( (bool) $permission, $context, (int) $object_id );
821 + }
822 +
776 823 // Catalog and coupon WRITES require the user's real WooCommerce
777 824 // capabilities — no POS-tier widening. The cashier role is deliberately
778 825 // read-only on catalog (Activator), and a blanket grant here handed
779 826 // every POS user product deletion and coupon minting. Product decision