| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | /** |
| 3 | - * Staff account protection for customer writes. | |
| 3 | + * Backward-compatible staff guard API. | |
| 4 | 4 | * |
| 5 | 5 | * @package WCPOS\WooCommercePOS |
| 6 | 6 | */ |
| 7 | 7 | |
| @@ -7,127 +7,52 @@ | ||
| 7 | 7 | |
| 8 | 8 | namespace WCPOS\WooCommercePOS\Services; |
| 9 | 9 | |
| 10 | 10 | /** |
| 11 | - * Decides which accounts a POS user may edit or delete. | |
| 11 | + * Backward-compatible staff guard. | |
| 12 | 12 | * |
| 13 | - * WooCommerce refuses credential changes on non-customer roles, but the old | |
| 14 | - * WCPOS edit_users fallback bypassed that refusal, and WooCommerce's own test | |
| 15 | - * reads only the target's FIRST role, so an administrator who also holds the | |
| 16 | - * customer role passes it. This guard tests capabilities instead: a POS user | |
| 17 | - * who is not an administrator may not edit or delete an account holding staff | |
| 18 | - * capabilities, whatever its roles say. "Staff" covers site and store | |
| 19 | - * administration, user management and an author seat in wp-admin, so editors | |
| 20 | - * and authors are fenced as well as administrators, shop managers and other | |
| 21 | - * cashiers. Reads are deliberately untouched — the POS customer space is every | |
| 22 | - * user on the site (#1379). | |
| 13 | + * @deprecated Use Permission_Rules::verdict() for complete permission decisions. | |
| 23 | 14 | */ |
| 24 | 15 | class Customer_Account_Guard { |
| 25 | 16 | /** |
| 26 | - * Get the capabilities that identify protected staff accounts. | |
| 17 | + * Get protected staff capabilities. | |
| 27 | 18 | * |
| 19 | + * @deprecated Use Permission_Rules::protected_capabilities(). | |
| 28 | 20 | * @return array |
| 29 | 21 | */ |
| 30 | 22 | public static function protected_capabilities(): array { |
| 31 | - /* | |
| 32 | - * Filters the capabilities that mark an account as staff. | |
| 33 | - * | |
| 34 | - * A POS user who cannot manage_options may not edit or delete an account | |
| 35 | - * holding any of these. The default marks site and store administration | |
| 36 | - * (manage_options, manage_woocommerce), user management (edit_users, which | |
| 37 | - * the Cashier role holds) and an author seat in wp-admin (edit_posts: | |
| 38 | - * editors, authors and contributors). Narrowing the list moves a target into | |
| 39 | - * the cleared path. Cleared targets bypass WooCommerce's | |
| 40 | - * woocommerce_shop_manager_editable_roles role-name restriction before | |
| 41 | - * WooCommerce re-judges them. | |
| 42 | - * | |
| 43 | - * @param {array} $capabilities | |
| 44 | - * @returns {array} $capabilities | |
| 45 | - * @since 1.10.10 | |
| 46 | - * @hook woocommerce_pos_protected_account_capabilities | |
| 47 | - */ | |
| 48 | - $caps = apply_filters( 'woocommerce_pos_protected_account_capabilities', array( 'manage_options', 'manage_woocommerce', 'edit_users', 'edit_posts' ) ); | |
| 49 | - | |
| 50 | - return array_values( array_unique( array_filter( array_map( 'strval', (array) $caps ) ) ) ); | |
| 23 | + return Permission_Rules::protected_capabilities(); | |
| 51 | 24 | } |
| 52 | 25 | |
| 53 | 26 | /** |
| 54 | - * Check staff protection before WooCommerce's own permission checks. | |
| 27 | + * Check whether an actor may modify a target. | |
| 55 | 28 | * |
| 56 | - * Deny is the default for anything this method cannot resolve: it only ever | |
| 57 | - * removes permission, so a caller that reaches it with a bad id is refused | |
| 58 | - * rather than waved through. | |
| 59 | - * | |
| 29 | + * @deprecated Use Permission_Rules::can_modify(). | |
| 60 | 30 | * @param int $actor_id Acting user ID. |
| 61 | 31 | * @param int $target_id Target user ID. |
| 62 | - * | |
| 63 | 32 | * @return bool |
| 64 | 33 | */ |
| 65 | 34 | public static function can_modify( int $actor_id, int $target_id ): bool { |
| 66 | - if ( $actor_id < 1 || $target_id < 1 ) { | |
| 67 | - return false; | |
| 68 | - } | |
| 69 | - if ( user_can( $actor_id, 'manage_options' ) || $actor_id === $target_id ) { | |
| 70 | - return true; | |
| 71 | - } | |
| 72 | - $target = get_user_by( 'id', $target_id ); | |
| 73 | - if ( ! $target ) { | |
| 74 | - return false; | |
| 75 | - } | |
| 76 | - foreach ( self::protected_capabilities() as $cap ) { | |
| 77 | - if ( user_can( $target, $cap ) ) { | |
| 78 | - return false; | |
| 79 | - } | |
| 80 | - } | |
| 81 | - | |
| 82 | - return true; | |
| 35 | + return Permission_Rules::can_modify( $actor_id, $target_id ); | |
| 83 | 36 | } |
| 84 | 37 | |
| 85 | 38 | /** |
| 86 | - * Let WooCommerce judge a cleared target by capability rather than role name. | |
| 39 | + * Temporarily allow a cleared target role. | |
| 87 | 40 | * |
| 88 | - * WooCommerce restricts a shop_manager to editing users whose role is in | |
| 89 | - * `woocommerce_shop_manager_editable_roles` (default: customer only), so a | |
| 90 | - * subscriber or a membership plugin's own customer role is refused outright | |
| 91 | - * even though the POS lists it. Once can_modify() has cleared the target of | |
| 92 | - * every staff capability, that role-name test adds nothing, so allow the | |
| 93 | - * target's own roles for the duration of the check. | |
| 94 | - * | |
| 95 | - * Call only after can_modify() returned true, and always invoke the returned | |
| 96 | - * closure to remove the filter. | |
| 97 | - * | |
| 98 | - * @param int $target_id Target user ID, already cleared by can_modify(). | |
| 99 | - * | |
| 100 | - * @return callable Restores the unfiltered behaviour. | |
| 41 | + * @deprecated Use Permission_Rules::allow_target_roles(). | |
| 42 | + * @param int $target_id Cleared target user ID. | |
| 43 | + * @return callable | |
| 101 | 44 | */ |
| 102 | 45 | public static function allow_target_roles( int $target_id ): callable { |
| 103 | - $target = get_user_by( 'id', $target_id ); | |
| 104 | - $roles = $target ? array_values( (array) $target->roles ) : array(); | |
| 105 | - | |
| 106 | - if ( empty( $roles ) ) { | |
| 107 | - return static function (): void {}; | |
| 108 | - } | |
| 109 | - | |
| 110 | - $filter = static function ( $allowed ) use ( $roles ) { | |
| 111 | - return array_values( array_unique( array_merge( (array) $allowed, $roles ) ) ); | |
| 112 | - }; | |
| 113 | - | |
| 114 | - add_filter( 'woocommerce_shop_manager_editable_roles', $filter ); | |
| 115 | - | |
| 116 | - return static function () use ( $filter ): void { | |
| 117 | - remove_filter( 'woocommerce_shop_manager_editable_roles', $filter ); | |
| 118 | - }; | |
| 46 | + return Permission_Rules::allow_target_roles( $target_id ); | |
| 119 | 47 | } |
| 120 | 48 | |
| 121 | 49 | /** |
| 122 | 50 | * Build the staff account permission error. |
| 123 | 51 | * |
| 52 | + * @deprecated Use Permission_Rules::denial(). | |
| 124 | 53 | * @return \WP_Error |
| 125 | 54 | */ |
| 126 | 55 | public static function denial(): \WP_Error { |
| 127 | - return new \WP_Error( | |
| 128 | - 'woocommerce_pos_rest_cannot_edit_staff_account', | |
| 129 | - __( 'Only an administrator can edit or delete a staff account from the POS.', 'woocommerce-pos' ), | |
| 130 | - array( 'status' => rest_authorization_required_code() ) | |
| 131 | - ); | |
| 56 | + return Permission_Rules::denial(); | |
| 132 | 57 | } |
| 133 | 58 | } |