class-wc-admin-api-keys.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <?php
  2. /**
  3. * WooCommerce Admin API Keys Class
  4. *
  5. * @package WooCommerce\Admin
  6. * @version 2.4.0
  7. */
  8. defined( 'ABSPATH' ) || exit;
  9. /**
  10. * WC_Admin_API_Keys.
  11. */
  12. class WC_Admin_API_Keys {
  13. /**
  14. * Initialize the API Keys admin actions.
  15. */
  16. public function __construct() {
  17. add_action( 'admin_init', array( $this, 'actions' ) );
  18. add_action( 'woocommerce_settings_page_init', array( $this, 'screen_option' ) );
  19. add_filter( 'woocommerce_save_settings_advanced_keys', array( $this, 'allow_save_settings' ) );
  20. }
  21. /**
  22. * Check if should allow save settings.
  23. * This prevents "Your settings have been saved." notices on the table list.
  24. *
  25. * @param bool $allow If allow save settings.
  26. * @return bool
  27. */
  28. public function allow_save_settings( $allow ) {
  29. if ( ! isset( $_GET['create-key'], $_GET['edit-key'] ) ) { // WPCS: input var okay, CSRF ok.
  30. return false;
  31. }
  32. return $allow;
  33. }
  34. /**
  35. * Check if is API Keys settings page.
  36. *
  37. * @return bool
  38. */
  39. private function is_api_keys_settings_page() {
  40. return isset( $_GET['page'], $_GET['tab'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'advanced' === $_GET['tab'] && 'keys' === $_GET['section']; // WPCS: input var okay, CSRF ok.
  41. }
  42. /**
  43. * Page output.
  44. */
  45. public static function page_output() {
  46. // Hide the save button.
  47. $GLOBALS['hide_save_button'] = true;
  48. if ( isset( $_GET['create-key'] ) || isset( $_GET['edit-key'] ) ) {
  49. $key_id = isset( $_GET['edit-key'] ) ? absint( $_GET['edit-key'] ) : 0; // WPCS: input var okay, CSRF ok.
  50. $key_data = self::get_key_data( $key_id );
  51. include 'settings/views/html-keys-edit.php';
  52. } else {
  53. self::table_list_output();
  54. }
  55. }
  56. /**
  57. * Add screen option.
  58. */
  59. public function screen_option() {
  60. global $keys_table_list;
  61. if ( ! isset( $_GET['create-key'] ) && ! isset( $_GET['edit-key'] ) && $this->is_api_keys_settings_page() ) { // WPCS: input var okay, CSRF ok.
  62. $keys_table_list = new WC_Admin_API_Keys_Table_List();
  63. // Add screen option.
  64. add_screen_option(
  65. 'per_page', array(
  66. 'default' => 10,
  67. 'option' => 'woocommerce_keys_per_page',
  68. )
  69. );
  70. }
  71. }
  72. /**
  73. * Table list output.
  74. */
  75. private static function table_list_output() {
  76. global $wpdb, $keys_table_list;
  77. echo '<h2>' . esc_html__( 'REST API', 'woocommerce' ) . ' <a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys&create-key=1' ) ) . '" class="add-new-h2">' . esc_html__( 'Add key', 'woocommerce' ) . '</a></h2>';
  78. // Get the API keys count.
  79. $count = $wpdb->get_var( "SELECT COUNT(key_id) FROM {$wpdb->prefix}woocommerce_api_keys WHERE 1 = 1;" );
  80. if ( absint( $count ) && $count > 0 ) {
  81. $keys_table_list->prepare_items();
  82. echo '<input type="hidden" name="page" value="wc-settings" />';
  83. echo '<input type="hidden" name="tab" value="advanced" />';
  84. echo '<input type="hidden" name="section" value="keys" />';
  85. $keys_table_list->views();
  86. $keys_table_list->search_box( __( 'Search key', 'woocommerce' ), 'key' );
  87. $keys_table_list->display();
  88. } else {
  89. echo '<div class="woocommerce-BlankState woocommerce-BlankState--api">';
  90. ?>
  91. <h2 class="woocommerce-BlankState-message"><?php esc_html_e( 'The WooCommerce REST API allows external apps to view and manage store data. Access is granted only to those with valid API keys.', 'woocommerce' ); ?></h2>
  92. <a class="woocommerce-BlankState-cta button-primary button" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys&create-key=1' ) ); ?>"><?php esc_html_e( 'Create an API key', 'woocommerce' ); ?></a>
  93. <style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions { display: none; }</style>
  94. <?php
  95. }
  96. }
  97. /**
  98. * Get key data.
  99. *
  100. * @param int $key_id API Key ID.
  101. * @return array
  102. */
  103. private static function get_key_data( $key_id ) {
  104. global $wpdb;
  105. $empty = array(
  106. 'key_id' => 0,
  107. 'user_id' => '',
  108. 'description' => '',
  109. 'permissions' => '',
  110. 'truncated_key' => '',
  111. 'last_access' => '',
  112. );
  113. if ( 0 === $key_id ) {
  114. return $empty;
  115. }
  116. $key = $wpdb->get_row(
  117. $wpdb->prepare(
  118. "SELECT key_id, user_id, description, permissions, truncated_key, last_access
  119. FROM {$wpdb->prefix}woocommerce_api_keys
  120. WHERE key_id = %d",
  121. $key_id
  122. ), ARRAY_A
  123. );
  124. if ( is_null( $key ) ) {
  125. return $empty;
  126. }
  127. return $key;
  128. }
  129. /**
  130. * API Keys admin actions.
  131. */
  132. public function actions() {
  133. if ( $this->is_api_keys_settings_page() ) {
  134. // Revoke key.
  135. if ( isset( $_REQUEST['revoke-key'] ) ) { // WPCS: input var okay, CSRF ok.
  136. $this->revoke_key();
  137. }
  138. // Bulk actions.
  139. if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['key'] ) ) { // WPCS: input var okay, CSRF ok.
  140. $this->bulk_actions();
  141. }
  142. }
  143. }
  144. /**
  145. * Notices.
  146. */
  147. public static function notices() {
  148. if ( isset( $_GET['revoked'] ) ) { // WPCS: input var okay, CSRF ok.
  149. $revoked = absint( $_GET['revoked'] ); // WPCS: input var okay, CSRF ok.
  150. /* translators: %d: count */
  151. WC_Admin_Settings::add_message( sprintf( _n( '%d API key permanently revoked.', '%d API keys permanently revoked.', $revoked, 'woocommerce' ), $revoked ) );
  152. }
  153. }
  154. /**
  155. * Revoke key.
  156. */
  157. private function revoke_key() {
  158. check_admin_referer( 'revoke' );
  159. if ( isset( $_REQUEST['revoke-key'] ) ) { // WPCS: input var okay, CSRF ok.
  160. $key_id = absint( $_REQUEST['revoke-key'] ); // WPCS: input var okay, CSRF ok.
  161. if ( $key_id ) {
  162. $this->remove_key( $key_id );
  163. }
  164. }
  165. wp_safe_redirect( esc_url_raw( add_query_arg( array( 'revoked' => 1 ), admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys' ) ) ) );
  166. exit();
  167. }
  168. /**
  169. * Bulk actions.
  170. */
  171. private function bulk_actions() {
  172. check_admin_referer( 'woocommerce-settings' );
  173. if ( ! current_user_can( 'manage_woocommerce' ) ) {
  174. wp_die( esc_html__( 'You do not have permission to edit API Keys', 'woocommerce' ) );
  175. }
  176. if ( isset( $_REQUEST['action'] ) ) { // WPCS: input var okay, CSRF ok.
  177. $action = sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ); // WPCS: input var okay, CSRF ok.
  178. $keys = isset( $_REQUEST['key'] ) ? array_map( 'absint', (array) $_REQUEST['key'] ) : array(); // WPCS: input var okay, CSRF ok.
  179. if ( 'revoke' === $action ) {
  180. $this->bulk_revoke_key( $keys );
  181. }
  182. }
  183. }
  184. /**
  185. * Bulk revoke key.
  186. *
  187. * @param array $keys API Keys.
  188. */
  189. private function bulk_revoke_key( $keys ) {
  190. $qty = 0;
  191. foreach ( $keys as $key_id ) {
  192. $result = $this->remove_key( $key_id );
  193. if ( $result ) {
  194. $qty++;
  195. }
  196. }
  197. // Redirect to webhooks page.
  198. wp_safe_redirect( esc_url_raw( add_query_arg( array( 'revoked' => $qty ), admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys' ) ) ) );
  199. exit();
  200. }
  201. /**
  202. * Remove key.
  203. *
  204. * @param int $key_id API Key ID.
  205. * @return bool
  206. */
  207. private function remove_key( $key_id ) {
  208. global $wpdb;
  209. $delete = $wpdb->delete( $wpdb->prefix . 'woocommerce_api_keys', array( 'key_id' => $key_id ), array( '%d' ) );
  210. return $delete;
  211. }
  212. }
  213. new WC_Admin_API_Keys();