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/V1/Customers_Controller.php +69 -7 1.10.9 → 1.10.17 View file →
@@ -16,13 +16,15 @@
16 16 use Exception;
17 17 use WC_Customer;
18 18 use WC_REST_Customers_Controller;
19 19 use WCPOS\WooCommercePOS\Logger;
20 +use WCPOS\WooCommercePOS\Services\Customer_Account_Guard;
20 21 use WCPOS\WooCommercePOS\Services\Settings as SettingsService;
21 22 use WCPOS\WooCommercePOS\Services\Tax_Id_Reader;
22 23 use WCPOS\WooCommercePOS\Services\Tax_Id_Types;
23 24 use WCPOS\WooCommercePOS\Services\Tax_Id_Writer;
24 25 use WCPOS\WooCommercePOS\Sync\Collection_Rules;
26 +use WCPOS\WooCommercePOS\Sync\Meta_Normalizer;
25 27 use WP_Error;
26 28 use WP_REST_Request;
27 29 use WP_REST_Response;
28 30 use WP_User;
@@ -157,10 +159,12 @@
157 159
158 160 /**
159 161 * Check if a given request has access to update a customer.
160 162 *
161 - * WC checks edit_users. The POS fallback also checks edit_users so the
162 - * Access settings page toggle controls this behaviour.
163 + * WCPOS never widens WooCommerce's credential fence, which refuses
164 + * email/password changes on non-customer roles. The guard additionally
165 + * keeps non-admins off staff accounts, testing capabilities rather than
166 + * WooCommerce's first-role-only test.
163 167 *
164 168 * @param WP_REST_Request $request Full details about the request.
165 169 *
166 170 * @return WP_Error|bool
@@ -165,15 +169,62 @@
165 169 *
166 170 * @return WP_Error|bool
167 171 */
168 172 public function update_item_permissions_check( $request ) {
169 - $permission = parent::update_item_permissions_check( $request );
173 + return $this->wcpos_guarded_permissions_check(
174 + (int) $request['id'],
175 + function () use ( $request ) {
176 + return parent::update_item_permissions_check( $request );
177 + }
178 + );
179 + }
170 180
171 - if ( is_wp_error( $permission ) && current_user_can( 'edit_users' ) ) {
172 - return true;
181 + /**
182 + * Check if a given request has access to delete a customer.
183 + *
184 + * WooCommerce refuses deleting a user whose role is outside its allowed
185 + * list, but it reads only the FIRST role, so an administrator who also
186 + * holds the customer role is deleted by any POS user with delete_users.
187 + * The guard closes that by capability.
188 + *
189 + * @param WP_REST_Request $request Full details about the request.
190 + *
191 + * @return WP_Error|bool
192 + */
193 + public function delete_item_permissions_check( $request ) {
194 + return $this->wcpos_guarded_permissions_check(
195 + (int) $request['id'],
196 + function () use ( $request ) {
197 + return parent::delete_item_permissions_check( $request );
198 + }
199 + );
200 + }
201 +
202 + /**
203 + * Run WooCommerce's own check behind the staff account guard.
204 + *
205 + * The guard runs first and can only refuse. When it clears the target,
206 + * that target's roles are allowed through WooCommerce's shop_manager
207 + * role-name restriction for the duration of the check, so a cleared
208 + * subscriber or membership-plugin role is judged by capability.
209 + *
210 + * @param int $target_id Target user ID.
211 + * @param callable $check Returns WooCommerce's verdict.
212 + *
213 + * @return WP_Error|bool
214 + */
215 + private function wcpos_guarded_permissions_check( int $target_id, callable $check ) {
216 + if ( ! Customer_Account_Guard::can_modify( get_current_user_id(), $target_id ) ) {
217 + return Customer_Account_Guard::denial();
173 218 }
174 219
175 - return $permission;
220 + $restore = Customer_Account_Guard::allow_target_roles( $target_id );
221 +
222 + try {
223 + return $check();
224 + } finally {
225 + $restore();
226 + }
176 227 }
177 228
178 229 /**
179 230 * Add extra fields to WP_REST_Controller::get_collection_params().
@@ -390,9 +441,20 @@
390 441
391 442 $filtered_meta_data = array_filter(
392 443 $raw_meta_data,
393 444 function ( $meta ) {
394 - return ! is_protected_meta( $meta->key, 'user' );
445 + if ( is_protected_meta( $meta->key, 'user' ) ) {
446 + return false;
447 + }
448 + // A single enormous value fatals the response encoder no matter how few
449 + // entries the customer has; same budget as the v2 sync lane.
450 + if ( Meta_Normalizer::exceeds_value_budget( $meta->value ) ) {
451 + Meta_Normalizer::note_oversized_meta( (string) $meta->key, (int) $meta->id );
452 +
453 + return false;
454 + }
455 +
456 + return true;
395 457 }
396 458 );
397 459
398 460 // Convert to WC REST API expected format.