291 lines
8.2 KiB
PHP
291 lines
8.2 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* Opalestate Admin API Keys Class
|
||
|
*
|
||
|
* @package Opalestate\API
|
||
|
*/
|
||
|
|
||
|
defined( 'ABSPATH' ) || exit;
|
||
|
|
||
|
/**
|
||
|
* Opalestate_Admin_API_Keys.
|
||
|
*/
|
||
|
class Opalestate_Admin_API_Keys {
|
||
|
|
||
|
/**
|
||
|
* Initialize the API Keys admin actions.
|
||
|
*/
|
||
|
public function __construct() {
|
||
|
add_action( 'admin_init', [ $this, 'actions' ] );
|
||
|
add_action( 'load-opalestate_property_page_opalestate-settings', [ $this, 'screen_option' ] );
|
||
|
add_action( 'cmb2_render_api_keys', [ $this, 'page_output' ] );
|
||
|
add_filter( 'opalestate_save_settings_advanced_keys', [ $this, 'allow_save_settings' ] );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if should allow save settings.
|
||
|
* This prevents "Your settings have been saved." notices on the table list.
|
||
|
*
|
||
|
* @param bool $allow If allow save settings.
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function allow_save_settings( $allow ) {
|
||
|
if ( ! isset( $_GET['create-key'], $_GET['edit-key'] ) ) { // WPCS: input var okay, CSRF ok.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return $allow;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if is API Keys settings page.
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
private function is_api_keys_settings_page() {
|
||
|
return isset( $_GET['page'], $_GET['tab'] ) && 'opalestate-settings' === $_GET['page'] && 'api_keys' === $_GET['tab']; // WPCS: input var okay, CSRF ok.
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Page output.
|
||
|
*/
|
||
|
public static function page_output() {
|
||
|
if ( isset( $_GET['create-key'] ) || isset( $_GET['edit-key'] ) ) {
|
||
|
$key_id = isset( $_GET['edit-key'] ) ? absint( $_GET['edit-key'] ) : 0; // WPCS: input var okay, CSRF ok.
|
||
|
$key_data = static::get_key_data( $key_id );
|
||
|
$user_id = absint( $key_data['user_id'] );
|
||
|
|
||
|
if ( $key_id && $user_id && ! current_user_can( 'edit_user', $user_id ) ) {
|
||
|
if ( get_current_user_id() !== $user_id ) {
|
||
|
wp_die( esc_html__( 'You do not have permission to edit this API Key', 'opalestate-pro' ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
include dirname( __FILE__ ) . '/html-keys-edit.php';
|
||
|
} else {
|
||
|
static::table_list_output();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add screen option.
|
||
|
*/
|
||
|
public function screen_option() {
|
||
|
global $keys_table_list;
|
||
|
|
||
|
if ( ! isset( $_GET['create-key'] ) && ! isset( $_GET['edit-key'] ) && $this->is_api_keys_settings_page() ) { // WPCS: input var okay, CSRF ok.
|
||
|
$keys_table_list = new Opalestate_Admin_API_Keys_Table_List();
|
||
|
|
||
|
// Add screen option.
|
||
|
add_screen_option(
|
||
|
'per_page', [
|
||
|
'default' => 10,
|
||
|
'option' => 'opalestate_keys_per_page',
|
||
|
]
|
||
|
);
|
||
|
}
|
||
|
?>
|
||
|
<style>
|
||
|
input[name="submit-cmb"] {
|
||
|
display: none !important;
|
||
|
}
|
||
|
</style>
|
||
|
<?php
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Table list output.
|
||
|
*/
|
||
|
private static function table_list_output() {
|
||
|
global $wpdb, $keys_table_list;
|
||
|
|
||
|
echo '<h2>' . esc_html__( 'REST API',
|
||
|
'opalestate-pro' ) . ' <a href="' . esc_url( admin_url( 'edit.php?post_type=opalestate_property&page=opalestate-settings&tab=api_keys&create-key=1' ) ) . '" class="add-new-h2">' .
|
||
|
esc_html__( 'Add key', 'opalestate-pro' ) . '</a></h2>';
|
||
|
|
||
|
// Get the API keys count.
|
||
|
$count = $wpdb->get_var( "SELECT COUNT(key_id) FROM {$wpdb->prefix}opalestate_api_keys WHERE 1 = 1;" );
|
||
|
|
||
|
if ( absint( $count ) && $count > 0 ) {
|
||
|
$keys_table_list->prepare_items();
|
||
|
|
||
|
echo '<input type="hidden" name="page" value="wc-settings" />';
|
||
|
echo '<input type="hidden" name="tab" value="advanced" />';
|
||
|
echo '<input type="hidden" name="section" value="keys" />';
|
||
|
|
||
|
$keys_table_list->views();
|
||
|
$keys_table_list->search_box( __( 'Search key', 'opalestate-pro' ), 'key' );
|
||
|
$keys_table_list->display();
|
||
|
} else {
|
||
|
echo '<div class="opalestate-admin-api">';
|
||
|
?>
|
||
|
<h2 class="opalestate-admin-api-message">
|
||
|
<?php printf(
|
||
|
__( 'API keys allow users to use the <a href="%s">Opalestate REST API</a> to retrieve donation data in JSON or XML for external applications or devices, such as <a href="%s">Zapi_keyser</a>.',
|
||
|
'opalestate-pro' ),
|
||
|
'https://wpopal.com/opalestate/documentation/opalestate-api_keys-reference/',
|
||
|
'https://wpopal.com/addons/opalestate/'
|
||
|
); ?>
|
||
|
</h2>
|
||
|
|
||
|
<a class="button-primary button" href="<?php echo esc_url( admin_url( 'edit.php?post_type=opalestate_property&page=opalestate-settings&tab=api_keys&create-key=1' ) ); ?>">
|
||
|
<?php esc_html_e( 'Create an API key', 'opalestate-pro' ); ?>
|
||
|
</a>
|
||
|
<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions {
|
||
|
display: none;
|
||
|
}</style>
|
||
|
<?php
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get key data.
|
||
|
*
|
||
|
* @param int $key_id API Key ID.
|
||
|
* @return array
|
||
|
*/
|
||
|
private static function get_key_data( $key_id ) {
|
||
|
global $wpdb;
|
||
|
|
||
|
$empty = [
|
||
|
'key_id' => 0,
|
||
|
'user_id' => '',
|
||
|
'description' => '',
|
||
|
'permissions' => '',
|
||
|
'truncated_key' => '',
|
||
|
'last_access' => '',
|
||
|
];
|
||
|
|
||
|
if ( 0 === $key_id ) {
|
||
|
return $empty;
|
||
|
}
|
||
|
|
||
|
$key = $wpdb->get_row(
|
||
|
$wpdb->prepare(
|
||
|
"SELECT key_id, user_id, description, permissions, truncated_key, last_access
|
||
|
FROM {$wpdb->prefix}opalestate_api_keys
|
||
|
WHERE key_id = %d",
|
||
|
$key_id
|
||
|
), ARRAY_A
|
||
|
);
|
||
|
|
||
|
if ( is_null( $key ) ) {
|
||
|
return $empty;
|
||
|
}
|
||
|
|
||
|
return $key;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* API Keys admin actions.
|
||
|
*/
|
||
|
public function actions() {
|
||
|
if ( $this->is_api_keys_settings_page() ) {
|
||
|
// Revoke key.
|
||
|
if ( isset( $_REQUEST['revoke-key'] ) ) { // WPCS: input var okay, CSRF ok.
|
||
|
$this->revoke_key();
|
||
|
}
|
||
|
|
||
|
// Bulk actions.
|
||
|
if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['key'] ) ) { // WPCS: input var okay, CSRF ok.
|
||
|
$this->bulk_actions();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Notices.
|
||
|
*/
|
||
|
public static function notices() {
|
||
|
if ( isset( $_GET['revoked'] ) ) { // WPCS: input var okay, CSRF ok.
|
||
|
$revoked = absint( $_GET['revoked'] ); // WPCS: input var okay, CSRF ok.
|
||
|
|
||
|
/* translators: %d: count */
|
||
|
Opalestate_Admin_Settings::add_message( sprintf( _n( '%d API key permanently revoked.', '%d API keys permanently revoked.', $revoked, 'opalestate-pro' ), $revoked ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Revoke key.
|
||
|
*/
|
||
|
private function revoke_key() {
|
||
|
global $wpdb;
|
||
|
|
||
|
check_admin_referer( 'revoke' );
|
||
|
|
||
|
if ( isset( $_REQUEST['revoke-key'] ) ) { // WPCS: input var okay, CSRF ok.
|
||
|
$key_id = absint( $_REQUEST['revoke-key'] ); // WPCS: input var okay, CSRF ok.
|
||
|
$user_id = (int) $wpdb->get_var( $wpdb->prepare( "SELECT user_id FROM {$wpdb->prefix}opalestate_api_keys WHERE key_id = %d", $key_id ) );
|
||
|
|
||
|
if ( $key_id && $user_id && ( current_user_can( 'edit_user', $user_id ) || get_current_user_id() === $user_id ) ) {
|
||
|
$this->remove_key( $key_id );
|
||
|
} else {
|
||
|
wp_die( esc_html__( 'You do not have permission to revoke this API Key', 'opalestate-pro' ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
wp_safe_redirect( esc_url_raw( add_query_arg( [ 'revoked' => 1 ], admin_url( 'edit.php?post_type=opalestate_property&page=opalestate-settings&tab=api_keys' ) ) ) );
|
||
|
exit();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Bulk actions.
|
||
|
*/
|
||
|
private function bulk_actions() {
|
||
|
check_admin_referer( 'opalestate-settings' );
|
||
|
|
||
|
if ( ! current_user_can( 'manage_opalestate' ) ) {
|
||
|
wp_die( esc_html__( 'You do not have permission to edit API Keys', 'opalestate-pro' ) );
|
||
|
}
|
||
|
|
||
|
if ( isset( $_REQUEST['action'] ) ) { // WPCS: input var okay, CSRF ok.
|
||
|
$action = sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ); // WPCS: input var okay, CSRF ok.
|
||
|
$keys = isset( $_REQUEST['key'] ) ? array_map( 'absint', (array) $_REQUEST['key'] ) : []; // WPCS: input var okay, CSRF ok.
|
||
|
|
||
|
if ( 'revoke' === $action ) {
|
||
|
$this->bulk_revoke_key( $keys );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Bulk revoke key.
|
||
|
*
|
||
|
* @param array $keys API Keys.
|
||
|
*/
|
||
|
private function bulk_revoke_key( $keys ) {
|
||
|
if ( ! current_user_can( 'remove_users' ) ) {
|
||
|
wp_die( esc_html__( 'You do not have permission to revoke API Keys', 'opalestate-pro' ) );
|
||
|
}
|
||
|
|
||
|
$qty = 0;
|
||
|
foreach ( $keys as $key_id ) {
|
||
|
$result = $this->remove_key( $key_id );
|
||
|
|
||
|
if ( $result ) {
|
||
|
$qty++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Redirect to webhooks page.
|
||
|
wp_safe_redirect( esc_url_raw( add_query_arg( [ 'revoked' => $qty ], admin_url( 'edit.php?post_type=opalestate_property&page=opalestate-settings&tab=api_keys' ) ) ) );
|
||
|
exit();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Remove key.
|
||
|
*
|
||
|
* @param int $key_id API Key ID.
|
||
|
* @return bool
|
||
|
*/
|
||
|
private function remove_key( $key_id ) {
|
||
|
global $wpdb;
|
||
|
|
||
|
$delete = $wpdb->delete( $wpdb->prefix . 'opalestate_api_keys', [ 'key_id' => $key_id ], [ '%d' ] );
|
||
|
|
||
|
return $delete;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
new Opalestate_Admin_API_Keys();
|