PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.22
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.22
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/Services/Settings/Access_Section.php +48 -2 1.10.5 → 1.10.22 View file →
@@ -8,8 +8,9 @@
8 8 namespace WCPOS\WooCommercePOS\Services\Settings;
9 9
10 10 use WCPOS\WooCommercePOS\Interfaces\Settings_Section_Interface;
11 11 use WP_Error;
12 +use WP_User;
12 13
13 14 /**
14 15 * The Access Settings Section.
15 16 *
@@ -47,8 +48,49 @@
47 48 return array_merge( $caps['wcpos'], $caps['wc'], $caps['wp'] );
48 49 }
49 50
50 51 /**
52 + * Capabilities the user can actually exercise, in the Access-settings vocabulary.
53 + *
54 + * The user_can() check is what every REST permission callback asks, so it is the
55 + * answer the client must be given; it also runs the `user_has_cap` filter that
56 + * role editors such as Members use to make a Deny on one role override a grant
57 + * on another. The two singular meta caps (edit_product, delete_product) cannot
58 + * go through user_can() without a post, so they are read from allcaps after the
59 + * same filter has run.
60 + *
61 + * @param WP_User $user User to report on.
62 + *
63 + * @return string[] Capability names, in capability_names() order.
64 + */
65 + public static function effective_capabilities( WP_User $user ): array {
66 + $names = self::capability_names();
67 + // A multisite super admin holds every capability before the filter runs
68 + // (WP_User::has_cap), so mirror that bypass for the two filtered names.
69 + $super_admin = is_multisite() && is_super_admin( $user->ID );
70 +
71 + return array_values(
72 + array_filter(
73 + $names,
74 + function ( $cap ) use ( $user, $super_admin ) {
75 + if ( ! in_array( $cap, array( 'edit_product', 'delete_product' ), true ) ) {
76 + return user_can( $user, $cap );
77 + }
78 + if ( $super_admin ) {
79 + return true;
80 + }
81 + // Same argument shape as WP_User::has_cap(): the caps being
82 + // checked, then the requested cap and user id.
83 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Core capability filter, run so role-editor denies apply.
84 + $filtered = apply_filters( 'user_has_cap', $user->allcaps, array( $cap ), array( $cap, $user->ID ), $user );
85 +
86 + return ! empty( $filtered[ $cap ] );
87 + }
88 + )
89 + );
90 + }
91 +
92 + /**
51 93 * Get capabilities grouped by type.
52 94 *
53 95 * WooCommerce 9.9 replaced promote_users with create_customers for
54 96 * customer creation via the REST API. We show the correct capability
@@ -166,9 +208,9 @@
166 208 * capability names to boolean grants. Only one role is mutated per call —
167 209 * this mirrors the single-role update semantics of the original REST
168 210 * controller.
169 211 *
170 - * The administrator/read capability is never removed as a sanity guard.
212 + * The administrator read and manage_woocommerce_pos capabilities are never removed.
171 213 *
172 214 * @param array $settings Incoming payload keyed by role slug.
173 215 *
174 216 * @return array|WP_Error The fresh read() view on success.
@@ -176,9 +218,9 @@
176 218 public function write( array $settings ) {
177 219 // Defense-in-depth: capability mutation is a privileged service-layer
178 220 // operation; do not rely solely on the REST route's permission
179 221 // callback (matches the Settings::delete_settings() precedent).
180 - if ( ! current_user_can( 'edit_users' ) || ! current_user_can( 'promote_users' ) ) {
222 + if ( ! current_user_can( 'manage_woocommerce_pos' ) || ! current_user_can( 'edit_users' ) || ! current_user_can( 'promote_users' ) ) {
181 223 return new WP_Error(
182 224 'woocommerce_pos_settings_error',
183 225 __( 'You do not have permission to update access settings.', 'woocommerce-pos' ),
184 226 array( 'status' => 403 )
@@ -225,8 +267,12 @@
225 267 // Apply each allowed capability grant/revoke.
226 268 foreach ( $flattened_caps as $cap => $grant ) {
227 269 // Sanity check: administrator role must always keep the `read` capability.
228 270 if ( 'administrator' === $slug && 'read' === $cap ) {
271 + continue;
272 + }
273 + // Administrators must retain access to capability management.
274 + if ( 'administrator' === $slug && 'manage_woocommerce_pos' === $cap && ! $grant ) {
229 275 continue;
230 276 }
231 277 if ( $grant ) {
232 278 $role->add_cap( $cap );