| 1 |
<?php |
| 2 |
/** |
| 3 |
* MainWP REST API page |
| 4 |
* |
| 5 |
* This Class handles building/Managing the |
| 6 |
* REST API MainWP DashboardPage & all SubPages. |
| 7 |
* |
| 8 |
* @package MainWP/Dashboard |
| 9 |
*/ |
| 10 |
|
| 11 |
namespace MainWP\Dashboard; |
| 12 |
|
| 13 |
// Exit if accessed directly. |
| 14 |
if ( ! defined( 'ABSPATH' ) ) { |
| 15 |
exit; |
| 16 |
} |
| 17 |
|
| 18 |
/** |
| 19 |
* Class MainWP_Rest_Api_Page |
| 20 |
* |
| 21 |
* @package MainWP\Dashboard |
| 22 |
*/ |
| 23 |
class MainWP_Rest_Api_Page { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.nore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.nore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.nore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR. |
| 24 |
|
| 25 |
/** |
| 26 |
* Protected static variable to hold the single instance of the class. |
| 27 |
* |
| 28 |
* @var mixed Default null |
| 29 |
*/ |
| 30 |
protected static $instance = null; |
| 31 |
|
| 32 |
/** |
| 33 |
* Public static varable to hold Subpages information. |
| 34 |
* |
| 35 |
* @var array $subPages |
| 36 |
*/ |
| 37 |
public static $subPages; |
| 38 |
|
| 39 |
/** |
| 40 |
* Private variable to hold the application passwords instance. |
| 41 |
* |
| 42 |
* @var MainWP_Application_Passwords |
| 43 |
*/ |
| 44 |
protected static $application_passwords; |
| 45 |
|
| 46 |
/** |
| 47 |
* Get Class Name |
| 48 |
* |
| 49 |
* @return __CLASS__ |
| 50 |
*/ |
| 51 |
public static function get_class_name() { |
| 52 |
return __CLASS__; |
| 53 |
} |
| 54 |
|
| 55 |
/** |
| 56 |
* Return the single instance of the class. |
| 57 |
* |
| 58 |
* @return mixed $instance The single instance of the class. |
| 59 |
*/ |
| 60 |
public static function get_instance() { |
| 61 |
if ( is_null( static::$instance ) ) { |
| 62 |
static::$instance = new self(); |
| 63 |
} |
| 64 |
return static::$instance; |
| 65 |
} |
| 66 |
|
| 67 |
/** |
| 68 |
* Constructor |
| 69 |
* |
| 70 |
* Sets up the application passwords instance. |
| 71 |
*/ |
| 72 |
public function __construct() { |
| 73 |
static::$application_passwords = MainWP_Application_Passwords::instance(); |
| 74 |
} |
| 75 |
|
| 76 |
/** Instantiate Hooks for the REST API Page. */ |
| 77 |
public static function init() { |
| 78 |
/** |
| 79 |
* Renders the REST API page header via the 'mainwp_pageheader_restapi' action. |
| 80 |
* |
| 81 |
* This hook is normally used in the same context of 'mainwp_getsubpages_restapi' |
| 82 |
*/ |
| 83 |
add_action( 'mainwp-pageheader-restapi', array( static::get_class_name(), 'render_header' ) ); |
| 84 |
|
| 85 |
/** |
| 86 |
* Renders the REST API page footer via the 'mainwp-pagefooter-restapi' action. |
| 87 |
* |
| 88 |
* This hook is normally used in the same context of 'mainwp-getsubpages-restapi' |
| 89 |
*/ |
| 90 |
add_action( 'mainwp-pagefooter-restapi', array( static::get_class_name(), 'render_footer' ) ); |
| 91 |
|
| 92 |
add_action( 'mainwp_help_sidebar_content', array( static::get_class_name(), 'mainwp_help_content' ) ); |
| 93 |
|
| 94 |
add_action( 'admin_init', array( static::get_instance(), 'admin_init' ) ); |
| 95 |
} |
| 96 |
|
| 97 |
/** Run the export_sites method that exports the Child Sites .csv file */ |
| 98 |
public function admin_init() { |
| 99 |
MainWP_Post_Handler::instance()->add_action( 'mainwp_rest_api_remove_keys', array( $this, 'ajax_rest_api_remove_keys' ) ); |
| 100 |
|
| 101 |
// Page: Application Passwords. |
| 102 |
MainWP_Post_Handler::instance()->add_action( 'mainwp_application_password_create', array( &$this, 'ajax_application_password_create' ) ); |
| 103 |
MainWP_Post_Handler::instance()->add_action( 'mainwp_application_password_delete', array( &$this, 'ajax_application_password_delete' ) ); |
| 104 |
MainWP_Post_Handler::instance()->add_action( 'mainwp_application_password_delete_multiple', array( &$this, 'ajax_application_password_delete_multiple' ) ); |
| 105 |
MainWP_Post_Handler::instance()->add_action( 'mainwp_application_password_delete_all', array( &$this, 'ajax_application_password_delete_all' ) ); |
| 106 |
// Add update handler for editing application password name. |
| 107 |
MainWP_Post_Handler::instance()->add_action( 'mainwp_application_password_update', array( &$this, 'ajax_application_password_update' ) ); |
| 108 |
|
| 109 |
// phpcs:disable WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 110 |
// Redirect to Application Passwords page if user tries to access REST API page and doesn't have permission. |
| 111 |
if ( isset( $_GET['page'] ) && 'RESTAPI' === $_GET['page'] && ! static::can_access_rest_api() ) { |
| 112 |
// If cannot view REST API, try redirecting to Application Passwords if allowed, otherwise to dashboard. |
| 113 |
$redirect = static::$application_passwords->can_access_application_passwords() ? 'admin.php?page=ApplicationPasswords' : 'admin.php?page=mainwp_tab'; // NOSONAR. |
| 114 |
wp_safe_redirect( admin_url( $redirect ) ); // NOSONAR. |
| 115 |
exit; |
| 116 |
} |
| 117 |
|
| 118 |
// Redirect to Application Passwords page if user tries to access Add API Keys page and doesn't have permission. |
| 119 |
// Allow access to Add/Edit API Keys if user has manage/create/edit REST API keys. |
| 120 |
if ( |
| 121 |
isset( $_GET['page'] ) && |
| 122 |
'AddApiKeys' === $_GET['page'] && |
| 123 |
! ( static::can_create_rest_api_keys() || static::can_edit_rest_api_keys() ) |
| 124 |
) { |
| 125 |
$redirect = static::$application_passwords->can_access_application_passwords() ? 'admin.php?page=ApplicationPasswords' : 'admin.php?page=mainwp_tab'; |
| 126 |
wp_safe_redirect( admin_url( $redirect ) ); |
| 127 |
exit; |
| 128 |
} |
| 129 |
// phpcs:enable |
| 130 |
|
| 131 |
$this->handle_rest_api_add_new(); |
| 132 |
$this->handle_rest_api_edit(); |
| 133 |
} |
| 134 |
|
| 135 |
|
| 136 |
/** |
| 137 |
* Instantiate the REST API Menu. |
| 138 |
* |
| 139 |
* @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item() |
| 140 |
*/ |
| 141 |
public static function init_menu() { |
| 142 |
$add_api_keys_title = esc_html__( 'Add API Keys', 'mainwp' ); // NOSONAR. |
| 143 |
$api_access_title = esc_html__( 'API Access', 'mainwp' ); // NOSONAR. |
| 144 |
$application_passwords_title = esc_html__( 'Application Passwords', 'mainwp' ); // NOSONAR. |
| 145 |
|
| 146 |
add_submenu_page( |
| 147 |
'mainwp_tab', |
| 148 |
$api_access_title, |
| 149 |
' <span id="mainwp-rest-api">' . $api_access_title . '</span>', |
| 150 |
'read', |
| 151 |
'RESTAPI', |
| 152 |
array( |
| 153 |
static::get_class_name(), |
| 154 |
'render_all_api_keys', |
| 155 |
) |
| 156 |
); |
| 157 |
|
| 158 |
if ( ! MainWP_Menu::is_disable_menu_item( 3, 'AddApiKeys' ) ) { |
| 159 |
add_submenu_page( |
| 160 |
'mainwp_tab', |
| 161 |
$add_api_keys_title, |
| 162 |
' <div class="mainwp-hidden">' . $add_api_keys_title . '</div>', |
| 163 |
'read', |
| 164 |
'AddApiKeys', |
| 165 |
array( |
| 166 |
static::get_class_name(), |
| 167 |
'render_rest_api_setings', |
| 168 |
) |
| 169 |
); |
| 170 |
} |
| 171 |
if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ApplicationPasswords' ) ) { |
| 172 |
add_submenu_page( |
| 173 |
'mainwp_tab', |
| 174 |
$application_passwords_title, |
| 175 |
' <div class="mainwp-hidden">' . $application_passwords_title . '</div>', |
| 176 |
'read', |
| 177 |
'ApplicationPasswords', |
| 178 |
array( |
| 179 |
static::get_class_name(), |
| 180 |
'render_application_passwords', |
| 181 |
) |
| 182 |
); |
| 183 |
} |
| 184 |
|
| 185 |
/** |
| 186 |
* REST API Subpages |
| 187 |
* |
| 188 |
* Filters subpages for the REST API page. |
| 189 |
* |
| 190 |
* @since Unknown |
| 191 |
*/ |
| 192 |
static::$subPages = apply_filters( 'mainwp_getsubpages_restapi', array() ); |
| 193 |
|
| 194 |
if ( isset( static::$subPages ) && is_array( static::$subPages ) ) { |
| 195 |
foreach ( static::$subPages as $subPage ) { |
| 196 |
if ( MainWP_Menu::is_disable_menu_item( 3, 'RESTAPI' . $subPage['slug'] ) ) { |
| 197 |
continue; |
| 198 |
} |
| 199 |
add_submenu_page( 'mainwp_tab', $subPage['title'], '<div class="mainwp-hidden">' . $subPage['title'] . '</div>', 'read', 'RESTAPI' . $subPage['slug'], $subPage['callback'] ); |
| 200 |
} |
| 201 |
} |
| 202 |
|
| 203 |
static::init_left_menu( static::$subPages ); |
| 204 |
} |
| 205 |
|
| 206 |
/** |
| 207 |
* Instantiate REST API SubPages Menu. |
| 208 |
* |
| 209 |
* @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item() |
| 210 |
*/ |
| 211 |
public static function init_subpages_menu() { |
| 212 |
?> |
| 213 |
<div id="menu-mainwp-RESTAPI" class="mainwp-submenu-wrapper"> |
| 214 |
<div class="wp-submenu sub-open"> |
| 215 |
<div class="mainwp_boxout"> |
| 216 |
<div class="mainwp_boxoutin"></div> |
| 217 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=RESTAPI' ) ); // NOSONAR. ?>" class="mainwp-submenu"><?php esc_html_e( 'API Access', 'mainwp' ); ?></a> |
| 218 |
<?php |
| 219 |
if ( isset( static::$subPages ) && is_array( static::$subPages ) && ! empty( static::$subPages ) ) { |
| 220 |
foreach ( static::$subPages as $subPage ) { |
| 221 |
if ( MainWP_Menu::is_disable_menu_item( 3, 'RESTAPI' . $subPage['slug'] ) ) { |
| 222 |
continue; |
| 223 |
} |
| 224 |
?> |
| 225 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=RESTAPI' . $subPage['slug'] ) ); ?>" class="mainwp-submenu"><?php echo esc_html( $subPage['title'] ); ?></a> |
| 226 |
<?php |
| 227 |
} |
| 228 |
} |
| 229 |
?> |
| 230 |
</div> |
| 231 |
</div> |
| 232 |
</div> |
| 233 |
<?php |
| 234 |
} |
| 235 |
|
| 236 |
/** |
| 237 |
* Instantiate left menu |
| 238 |
* |
| 239 |
* REST API Page & SubPage link data. |
| 240 |
* |
| 241 |
* @param array $subPages SubPages Array. |
| 242 |
*/ |
| 243 |
public static function init_left_menu( $subPages = array() ) { |
| 244 |
// Determine if the user has permission to view either REST API or Application Passwords. |
| 245 |
$is_can_view_rest_api = static::can_access_rest_api(); |
| 246 |
$is_can_view_application_passwords = static::$application_passwords->can_access_application_passwords(); |
| 247 |
if ( ! $is_can_view_rest_api && ! $is_can_view_application_passwords ) { |
| 248 |
return; |
| 249 |
} |
| 250 |
|
| 251 |
$api_keys_title = esc_html__( 'API Keys', 'mainwp' ); // NOSONAR. |
| 252 |
$application_passwords_title = esc_html__( 'Application Passwords', 'mainwp' ); |
| 253 |
$application_passwords_url = 'admin.php?page=ApplicationPasswords'; |
| 254 |
|
| 255 |
// Determine the landing href for the top-level API Access item based on permissions. |
| 256 |
$root_href = 'admin.php?page=RESTAPI'; |
| 257 |
if ( ! $is_can_view_rest_api && $is_can_view_application_passwords ) { |
| 258 |
$root_href = $application_passwords_url; |
| 259 |
} |
| 260 |
|
| 261 |
MainWP_Menu::add_left_menu( |
| 262 |
array( |
| 263 |
'title' => esc_html__( 'Access', 'mainwp' ), |
| 264 |
'parent_key' => 'mainwp_tab', |
| 265 |
'slug' => 'RESTAPI', |
| 266 |
'href' => $root_href, |
| 267 |
'id' => 'mainwp-restapi-active-item', |
| 268 |
'icon' => '<div class="mainwp-api-icon">API</div>', |
| 269 |
), |
| 270 |
0 |
| 271 |
); |
| 272 |
|
| 273 |
// API Keys. |
| 274 |
$sub_rest_api = array(); |
| 275 |
if ( $is_can_view_rest_api ) { |
| 276 |
// Second-level groups (dropdowns) under API Access. |
| 277 |
MainWP_Menu::add_left_menu( |
| 278 |
array( |
| 279 |
'title' => $api_keys_title, |
| 280 |
'parent_key' => 'RESTAPI', |
| 281 |
'slug' => 'RESTAPIKeys', |
| 282 |
'href' => 'admin.php?page=RESTAPI', |
| 283 |
), |
| 284 |
1 |
| 285 |
); |
| 286 |
$sub_rest_api[] = array( |
| 287 |
'title' => $api_keys_title, |
| 288 |
'parent_key' => 'RESTAPIKeys', |
| 289 |
'href' => 'admin.php?page=RESTAPI', |
| 290 |
'slug' => 'RESTAPI', |
| 291 |
'right' => '', |
| 292 |
); |
| 293 |
|
| 294 |
if ( static::can_create_rest_api_keys() ) { |
| 295 |
$sub_rest_api[] = array( |
| 296 |
'title' => esc_html__( 'Add API Keys', 'mainwp' ), |
| 297 |
'parent_key' => 'RESTAPIKeys', |
| 298 |
'href' => 'admin.php?page=AddApiKeys', |
| 299 |
'slug' => 'AddApiKeys', |
| 300 |
'right' => '', |
| 301 |
); |
| 302 |
} |
| 303 |
} |
| 304 |
|
| 305 |
// Application Passwords. |
| 306 |
$sub_application_passwords = array(); |
| 307 |
if ( $is_can_view_application_passwords ) { |
| 308 |
MainWP_Menu::add_left_menu( |
| 309 |
array( |
| 310 |
'title' => $application_passwords_title, |
| 311 |
'parent_key' => 'RESTAPI', |
| 312 |
'slug' => 'RESTAPIAppPasswords', |
| 313 |
'href' => $application_passwords_url, |
| 314 |
), |
| 315 |
1 |
| 316 |
); |
| 317 |
$sub_application_passwords[] = array( |
| 318 |
'title' => $application_passwords_title, |
| 319 |
'parent_key' => 'RESTAPIAppPasswords', |
| 320 |
'href' => $application_passwords_url, |
| 321 |
'slug' => 'ApplicationPasswords', |
| 322 |
'right' => '', |
| 323 |
); |
| 324 |
} |
| 325 |
|
| 326 |
// Third-level items (actual links). |
| 327 |
$init_sub_subleftmenu = array_merge( |
| 328 |
$sub_rest_api, |
| 329 |
$sub_application_passwords |
| 330 |
); |
| 331 |
|
| 332 |
// If any dynamic subpages exist, attach them under API Keys group by default. |
| 333 |
MainWP_Menu::init_subpages_left_menu( $subPages, $init_sub_subleftmenu, 'RESTAPIKeys', 'RESTAPI' ); |
| 334 |
foreach ( $init_sub_subleftmenu as $item ) { |
| 335 |
if ( MainWP_Menu::is_disable_menu_item( 3, $item['slug'] ) ) { |
| 336 |
continue; |
| 337 |
} |
| 338 |
|
| 339 |
MainWP_Menu::add_left_menu( $item, 2 ); |
| 340 |
} |
| 341 |
} |
| 342 |
|
| 343 |
/** |
| 344 |
* Method handle_rest_api_add_new() |
| 345 |
* |
| 346 |
* Handle rest api settings |
| 347 |
*/ |
| 348 |
public function handle_rest_api_add_new() { // phpcs:ignore -- NOSONAR - complex. |
| 349 |
// phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 350 |
$submit = false; |
| 351 |
|
| 352 |
if ( isset( $_POST['submit'] ) && isset( $_GET['page'] ) && 'AddApiKeys' === $_GET['page'] ) { |
| 353 |
$submit = true; |
| 354 |
} |
| 355 |
|
| 356 |
if ( $submit && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'RESTAPI' ) ) { |
| 357 |
// Only users with explicit create permission can create new API keys. |
| 358 |
if ( ! static::can_create_rest_api_keys() ) { |
| 359 |
wp_safe_redirect( admin_url( 'admin.php?page=RESTAPI' ) ); |
| 360 |
exit; |
| 361 |
} |
| 362 |
$all_keys = static::check_rest_api_updates(); |
| 363 |
|
| 364 |
if ( ! is_array( $all_keys ) ) { |
| 365 |
$all_keys = array(); |
| 366 |
} |
| 367 |
|
| 368 |
$consumer_key = isset( $_POST['mainwp_consumer_key'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_consumer_key'] ) ) : ''; |
| 369 |
$consumer_secret = isset( $_POST['mainwp_consumer_secret'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_consumer_secret'] ) ) : ''; |
| 370 |
$desc = isset( $_POST['mainwp_rest_add_api_key_desc'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_rest_add_api_key_desc'] ) ) : ''; |
| 371 |
$enabled = ! empty( $_POST['mainwp_enable_rest_api'] ) ? 1 : 0; |
| 372 |
$pers = ! empty( $_POST['mainwp_rest_api_key_edit_pers'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_rest_api_key_edit_pers'] ) ) : ''; |
| 373 |
|
| 374 |
// hash the password. |
| 375 |
$consumer_key_hashed = wp_hash_password( $consumer_key ); |
| 376 |
$consumer_secret_hashed = wp_hash_password( $consumer_secret ); |
| 377 |
|
| 378 |
if ( ! empty( $_POST['mainwp_rest_api_keys_compatible_v1'] ) ) { |
| 379 |
$all_keys[ $consumer_key ] = array( |
| 380 |
'ck_hashed' => $consumer_key_hashed, |
| 381 |
'cs' => $consumer_secret_hashed, |
| 382 |
'desc' => $desc, |
| 383 |
'enabled' => $enabled, |
| 384 |
'perms' => $pers, |
| 385 |
); |
| 386 |
// store the data. |
| 387 |
MainWP_Utility::update_option( 'mainwp_rest_api_keys', $all_keys ); |
| 388 |
} |
| 389 |
|
| 390 |
// compatible with version 2. |
| 391 |
$scope = 'read'; |
| 392 |
if ( ! empty( $pers ) ) { |
| 393 |
$pers_list = explode( ',', $pers ); |
| 394 |
$has_read = in_array( 'r', $pers_list ); |
| 395 |
$has_write = in_array( 'w', $pers_list ) || in_array( 'd', $pers_list ); |
| 396 |
|
| 397 |
if ( $has_read && $has_write ) { |
| 398 |
$scope = 'read_write'; |
| 399 |
} elseif ( $has_write ) { |
| 400 |
$scope = 'write'; |
| 401 |
} elseif ( $has_read ) { |
| 402 |
$scope = 'read'; |
| 403 |
} |
| 404 |
} |
| 405 |
$this->invalidate_warm_cache(); |
| 406 |
$api_key = MainWP_DB::instance()->insert_rest_api_key( $consumer_key, $consumer_secret, $scope, $desc, $enabled ); |
| 407 |
// insert_rest_api_key() returns false when wpdb->insert() fails. |
| 408 |
// Without this guard the redirect would still claim success even |
| 409 |
// though no row was persisted. |
| 410 |
if ( ! is_array( $api_key ) || empty( $api_key['key_id'] ) ) { |
| 411 |
wp_safe_redirect( |
| 412 |
add_query_arg( |
| 413 |
array( |
| 414 |
'page' => 'RESTAPI', |
| 415 |
'message' => 'create_failed', |
| 416 |
), |
| 417 |
admin_url( 'admin.php' ) |
| 418 |
) |
| 419 |
); |
| 420 |
exit(); |
| 421 |
} |
| 422 |
wp_safe_redirect( |
| 423 |
add_query_arg( |
| 424 |
array( |
| 425 |
'page' => 'RESTAPI', |
| 426 |
'message' => 'created', |
| 427 |
), |
| 428 |
admin_url( 'admin.php' ) |
| 429 |
) |
| 430 |
); |
| 431 |
exit(); |
| 432 |
} |
| 433 |
// phpcs:enable |
| 434 |
} |
| 435 |
|
| 436 |
/** |
| 437 |
* Method handle_rest_api_edit() |
| 438 |
* |
| 439 |
* Handle rest api settings |
| 440 |
*/ |
| 441 |
public function handle_rest_api_edit() { // phpcs:ignore -- NOSONAR - complex. |
| 442 |
|
| 443 |
$edit_id = isset( $_POST['editkey_id'] ) ? sanitize_text_field( wp_unslash( $_POST['editkey_id'] ) ) : false; |
| 444 |
|
| 445 |
if ( isset( $_POST['submit'] ) && ! empty( $edit_id ) && isset( $_POST['edit_key_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['edit_key_nonce'] ), 'edit-key-nonce-' . $edit_id ) ) { |
| 446 |
// Only users with explicit edit permission can update API keys. |
| 447 |
if ( ! static::can_edit_rest_api_keys() ) { |
| 448 |
wp_safe_redirect( admin_url( 'admin.php?page=RESTAPI' ) ); |
| 449 |
exit(); |
| 450 |
} |
| 451 |
|
| 452 |
$save = false; |
| 453 |
$updated = false; |
| 454 |
if ( ! empty( $edit_id ) ) { |
| 455 |
if ( ! empty( $_POST['rest_v2_edit'] ) ) { |
| 456 |
$key_id = intval( $edit_id ); |
| 457 |
$desc = isset( $_POST['mainwp_rest_api_key_desc'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_rest_api_key_desc'] ) ) : ''; |
| 458 |
$enabled = ! empty( $_POST['mainwp_enable_rest_api'] ) ? 1 : 0; |
| 459 |
$pers = ! empty( $_POST['mainwp_rest_api_key_edit_pers'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_rest_api_key_edit_pers'] ) ) : ''; |
| 460 |
$scope = 'read'; |
| 461 |
if ( ! empty( $pers ) ) { |
| 462 |
$pers_list = explode( ',', $pers ); |
| 463 |
$has_read = in_array( 'r', $pers_list ); |
| 464 |
$has_write = in_array( 'w', $pers_list ) || in_array( 'd', $pers_list ); |
| 465 |
|
| 466 |
if ( $has_read && $has_write ) { |
| 467 |
$scope = 'read_write'; |
| 468 |
} elseif ( $has_write ) { |
| 469 |
$scope = 'write'; |
| 470 |
} elseif ( $has_read ) { |
| 471 |
$scope = 'read'; |
| 472 |
} |
| 473 |
} |
| 474 |
|
| 475 |
MainWP_DB::instance()->update_rest_api_key( $key_id, $scope, $desc, $enabled ); |
| 476 |
|
| 477 |
$updated = true; |
| 478 |
$save = true; |
| 479 |
} else { |
| 480 |
$edit_id = sanitize_text_field( $edit_id ); |
| 481 |
$all_keys = get_option( 'mainwp_rest_api_keys', false ); |
| 482 |
if ( is_array( $all_keys ) && isset( $all_keys[ $edit_id ] ) ) { |
| 483 |
$item = $all_keys[ $edit_id ]; |
| 484 |
if ( is_array( $item ) && isset( $item['cs'] ) ) { |
| 485 |
$item['desc'] = isset( $_POST['mainwp_rest_api_key_desc'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_rest_api_key_desc'] ) ) : ''; |
| 486 |
$item['enabled'] = ! empty( $_POST['mainwp_enable_rest_api'] ) ? 1 : 0; |
| 487 |
$item['perms'] = ! empty( $_POST['mainwp_rest_api_key_edit_pers'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_rest_api_key_edit_pers'] ) ) : ''; |
| 488 |
|
| 489 |
$all_keys[ $edit_id ] = $item; |
| 490 |
$updated = true; |
| 491 |
$save = true; |
| 492 |
} else { |
| 493 |
unset( $all_keys[ $edit_id ] ); // delete incorrect key. |
| 494 |
$save = true; |
| 495 |
} |
| 496 |
|
| 497 |
if ( $save ) { |
| 498 |
MainWP_Utility::update_option( 'mainwp_rest_api_keys', $all_keys ); |
| 499 |
} |
| 500 |
} |
| 501 |
} |
| 502 |
} |
| 503 |
|
| 504 |
$msg = ''; |
| 505 |
if ( $updated ) { |
| 506 |
$msg = '&message=saved'; |
| 507 |
} |
| 508 |
|
| 509 |
$this->invalidate_warm_cache(); |
| 510 |
|
| 511 |
wp_safe_redirect( admin_url( 'admin.php?page=RESTAPI' . $msg ) ); //phpcs:ignore -- ok. |
| 512 |
exit(); |
| 513 |
} |
| 514 |
} |
| 515 |
|
| 516 |
/** |
| 517 |
* Method invalidate_warm_cache() |
| 518 |
*/ |
| 519 |
public function invalidate_warm_cache() { |
| 520 |
MainWP_Cache_Warm_Helper::invalidate_manage_pages( array( 'RESTAPI' ) ); |
| 521 |
} |
| 522 |
|
| 523 |
/** |
| 524 |
* Method ajax_rest_api_remove_keys() |
| 525 |
* |
| 526 |
* Remove API Key. |
| 527 |
*/ |
| 528 |
public function ajax_rest_api_remove_keys() { //phpcs:ignore -- NOSONAR - complex. |
| 529 |
MainWP_Post_Handler::instance()->check_security( 'mainwp_rest_api_remove_keys' ); |
| 530 |
// Require delete permission to remove API keys. |
| 531 |
if ( ! static::can_delete_rest_api_keys() ) { |
| 532 |
echo wp_json_encode( |
| 533 |
array( |
| 534 |
'success' => false, |
| 535 |
'error' => esc_html__( 'You are not allowed to delete REST API keys.', 'mainwp' ), |
| 536 |
) |
| 537 |
); |
| 538 |
exit(); |
| 539 |
} |
| 540 |
$ret = array( 'success' => false ); |
| 541 |
$cons_key_id = isset( $_POST['keyId'] ) ? urldecode( wp_unslash( $_POST['keyId'] ) ) : false; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 542 |
$is_v2 = isset( $_POST['api_ver'] ) && 'v2' === wp_unslash( $_POST['api_ver'] ) ? true : false; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 543 |
|
| 544 |
if ( ! empty( $cons_key_id ) ) { |
| 545 |
if ( $is_v2 ) { |
| 546 |
MainWP_DB::instance()->remove_rest_api_key( $cons_key_id ); |
| 547 |
} else { |
| 548 |
$save = false; |
| 549 |
$all_keys = get_option( 'mainwp_rest_api_keys', false ); |
| 550 |
if ( is_array( $all_keys ) && isset( $all_keys[ $cons_key_id ] ) ) { |
| 551 |
$item = $all_keys[ $cons_key_id ]; |
| 552 |
if ( is_array( $item ) && isset( $item['cs'] ) ) { |
| 553 |
unset( $all_keys[ $cons_key_id ] ); // delete key. |
| 554 |
$save = true; |
| 555 |
} |
| 556 |
} |
| 557 |
if ( $save ) { |
| 558 |
MainWP_Utility::update_option( 'mainwp_rest_api_keys', $all_keys ); |
| 559 |
} |
| 560 |
} |
| 561 |
$ret['success'] = 'SUCCESS'; |
| 562 |
$ret['result'] = esc_html__( 'REST API Key deleted successfully.', 'mainwp' ); |
| 563 |
$this->invalidate_warm_cache(); |
| 564 |
} else { |
| 565 |
$ret['error'] = esc_html__( 'REST API Key ID empty.', 'mainwp' ); |
| 566 |
} |
| 567 |
echo wp_json_encode( $ret ); |
| 568 |
exit; |
| 569 |
} |
| 570 |
|
| 571 |
|
| 572 |
/** |
| 573 |
* Render Page Header. |
| 574 |
* |
| 575 |
* @param string $shownPage The page slug shown at this moment. |
| 576 |
* |
| 577 |
* @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item() |
| 578 |
* @uses \MainWP\Dashboard\MainWP_UI::render_top_header() |
| 579 |
* @uses \MainWP\Dashboard\MainWP_UI::render_page_navigation() |
| 580 |
*/ |
| 581 |
public static function render_header( $shownPage = '' ) { // phpcs:ignore -- NOSONAR - complex. |
| 582 |
|
| 583 |
$params = array( |
| 584 |
'title' => esc_html__( 'API Access', 'mainwp' ), |
| 585 |
); |
| 586 |
|
| 587 |
MainWP_UI::render_top_header( $params ); |
| 588 |
|
| 589 |
$renderItems = array(); |
| 590 |
|
| 591 |
// Show API Keys tab if user can view REST API section (any of manage/create/edit/delete). |
| 592 |
if ( static::can_access_rest_api() ) { |
| 593 |
$renderItems[] = array( |
| 594 |
'title' => esc_html__( 'API Keys', 'mainwp' ), |
| 595 |
'href' => 'admin.php?page=RESTAPI', |
| 596 |
'active' => ( '' === $shownPage ) ? true : false, |
| 597 |
); |
| 598 |
} |
| 599 |
|
| 600 |
// Show Add API Keys tab if user can create or edit REST API keys or has manage permission. |
| 601 |
if ( ! MainWP_Menu::is_disable_menu_item( 3, 'AddApiKeys' ) && ( static::can_create_rest_api_keys() || static::can_edit_rest_api_keys() ) ) { |
| 602 |
if ( isset( $_GET['editkey'] ) && ! empty( $_GET['editkey'] ) && isset( $_GET['_opennonce'] ) && wp_verify_nonce( sanitize_key( $_GET['_opennonce'] ), 'mainwp-admin-nonce' ) ) { |
| 603 |
// phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 604 |
$ver = isset( $_GET['rest_ver'] ) && ! empty( $_GET['rest_ver'] ) ? '&rest_ver=' . intval( $_GET['rest_ver'] ) : ''; |
| 605 |
$renderItems[] = array( |
| 606 |
'title' => esc_html__( 'Edit API Keys', 'mainwp' ), |
| 607 |
'href' => 'admin.php?page=AddApiKeys&editkey=' . esc_url( wp_unslash( $_GET['editkey'] ) ) . $ver . '&_opennonce=' . esc_html( wp_create_nonce( 'mainwp-admin-nonce' ) ), // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 608 |
'active' => ( 'Edit' === $shownPage ) ? true : false, |
| 609 |
); |
| 610 |
} |
| 611 |
$renderItems[] = array( |
| 612 |
'title' => esc_html__( 'Add API Keys', 'mainwp' ), |
| 613 |
'href' => 'admin.php?page=AddApiKeys', |
| 614 |
'active' => ( 'Settings' === $shownPage ) ? true : false, |
| 615 |
); |
| 616 |
} |
| 617 |
|
| 618 |
if ( ! MainWP_Menu::is_disable_menu_item( 3, 'ApplicationPasswords' ) && ( static::$application_passwords->can_view_manage_application_passwords() || |
| 619 |
static::$application_passwords->can_view_all_application_passwords() || |
| 620 |
static::$application_passwords->can_create_application_passwords() || |
| 621 |
static::$application_passwords->can_delete_application_passwords() ) ) { |
| 622 |
|
| 623 |
$renderItems[] = array( |
| 624 |
'title' => esc_html__( 'Application Passwords', 'mainwp' ), |
| 625 |
'href' => 'admin.php?page=ApplicationPasswords', |
| 626 |
'active' => ( 'Application Passwords' === $shownPage ) ? true : false, |
| 627 |
); |
| 628 |
} |
| 629 |
|
| 630 |
if ( isset( static::$subPages ) && is_array( static::$subPages ) ) { |
| 631 |
foreach ( static::$subPages as $subPage ) { |
| 632 |
if ( MainWP_Menu::is_disable_menu_item( 3, 'RESTAPI' . $subPage['slug'] ) ) { |
| 633 |
continue; |
| 634 |
} |
| 635 |
$item = array(); |
| 636 |
$item['title'] = $subPage['title']; |
| 637 |
$item['href'] = 'admin.php?page=RESTAPI' . $subPage['slug']; |
| 638 |
$item['active'] = ( $subPage['slug'] === $shownPage ) ? true : false; |
| 639 |
$renderItems[] = $item; |
| 640 |
} |
| 641 |
} |
| 642 |
|
| 643 |
MainWP_UI::render_page_navigation( $renderItems ); |
| 644 |
} |
| 645 |
|
| 646 |
/** |
| 647 |
* Close the HTML container. |
| 648 |
*/ |
| 649 |
public static function render_footer() { |
| 650 |
echo '</div>'; |
| 651 |
} |
| 652 |
|
| 653 |
/** |
| 654 |
* Render a friendly permission denied UI inside MainWP layout. |
| 655 |
* |
| 656 |
* @param string $title Page title to show in header. |
| 657 |
* @param string $message Message to show in the body. |
| 658 |
*/ |
| 659 |
protected static function render_permission_denied_ui( $title, $message ) { |
| 660 |
$params = array( 'title' => $title ); |
| 661 |
MainWP_UI::render_top_header( $params ); |
| 662 |
?> |
| 663 |
<div class="ui segment"> |
| 664 |
<div class="ui negative message"> |
| 665 |
<i class="ban icon"></i> |
| 666 |
<div class="content"> |
| 667 |
<div class="header"><?php echo esc_html( $title ); ?></div> |
| 668 |
<p><?php echo esc_html( $message ); ?></p> |
| 669 |
</div> |
| 670 |
</div> |
| 671 |
<div class="ui divider"></div> |
| 672 |
<div class="ui two column stackable grid"> |
| 673 |
<div class="column"> |
| 674 |
<?php if ( current_user_can( 'manage_options' ) ) : ?> |
| 675 |
<a class="ui small basic button" href="<?php echo esc_url( admin_url( 'admin.php?page=RESTAPI' ) ); ?>"> |
| 676 |
<i class="key icon"></i> <?php esc_html_e( 'API Keys', 'mainwp' ); ?> |
| 677 |
</a> |
| 678 |
<?php endif; ?> |
| 679 |
</div> |
| 680 |
<div class="column right aligned"> |
| 681 |
<?php if ( static::$application_passwords->can_access_application_passwords() ) : ?> |
| 682 |
<a class="ui small green button" |
| 683 |
href="<?php echo esc_url( admin_url( 'admin.php?page=ApplicationPasswords' ) ); ?>"> |
| 684 |
<i class="lock icon"></i> <?php esc_html_e( 'Go to Application Passwords', 'mainwp' ); ?> |
| 685 |
</a> |
| 686 |
<?php else : ?> |
| 687 |
<a class="ui small button" href="<?php echo esc_url( admin_url( 'admin.php?page=mainwp_tab' ) ); ?>"> |
| 688 |
<i class="home icon"></i> <?php esc_html_e( 'Back to Dashboard', 'mainwp' ); ?> |
| 689 |
</a> |
| 690 |
<?php endif; ?> |
| 691 |
</div> |
| 692 |
</div> |
| 693 |
</div> |
| 694 |
<?php |
| 695 |
static::render_footer(); |
| 696 |
} |
| 697 |
|
| 698 |
/** |
| 699 |
* Method render_api_keys_v1_table. |
| 700 |
* |
| 701 |
* @return void |
| 702 |
*/ |
| 703 |
public static function render_api_keys_v1_table() { //phpcs:ignore -- NOSONAR - complex. |
| 704 |
$all_keys = static::check_rest_api_updates(); |
| 705 |
$can_edit_keys = static::can_edit_rest_api_keys(); |
| 706 |
$can_delete_keys = static::can_delete_rest_api_keys(); |
| 707 |
|
| 708 |
if ( ! is_array( $all_keys ) ) { |
| 709 |
$all_keys = array(); |
| 710 |
} |
| 711 |
|
| 712 |
if ( ! empty( $all_keys ) ) { |
| 713 |
$write_delete = esc_html__( 'Write & Delete', 'mainwp' ); // NOSONAR - ok. |
| 714 |
?> |
| 715 |
|
| 716 |
<table id="mainwp-rest-api-keys-table" class="ui unstackable single linetable"> |
| 717 |
<thead> |
| 718 |
<tr> |
| 719 |
<th scope="col" class="no-sort collapsing check-column"><span class="ui checkbox"><input |
| 720 |
aria-label="<?php esc_attr_e( 'Select all REST API keys', 'mainwp' ); ?>" id="cb-select-all-top" |
| 721 |
type="checkbox" /></span></th> |
| 722 |
<th scope="col" class="collapsing"><?php esc_html_e( 'Status', 'mainwp' ); ?></th> |
| 723 |
<th scope="col"><?php esc_html_e( 'API Key', 'mainwp' ); ?></th> |
| 724 |
<th scope="col" class="collapsing"><?php esc_html_e( 'Permissions', 'mainwp' ); ?></th> |
| 725 |
<th scope="col" class="no-sort collapsing"><?php esc_html_e( 'Consumer key ending in', 'mainwp' ); ?></th> |
| 726 |
<?php if ( $can_edit_keys || $can_delete_keys ) : ?> |
| 727 |
<th scope="col" class="no-sort collapsing"></th> |
| 728 |
<?php endif; ?> |
| 729 |
</tr> |
| 730 |
</thead> |
| 731 |
<tbody id="mainwp-rest-api-body-table" class="mainwp-rest-api-body-table-manage"> |
| 732 |
<?php |
| 733 |
foreach ( $all_keys as $ck => $item ) { |
| 734 |
if ( ! is_array( $item ) ) { |
| 735 |
continue; |
| 736 |
} |
| 737 |
$ending = substr( $ck, -8 ); |
| 738 |
$desc = isset( $item['desc'] ) && ! empty( $item['desc'] ) ? $item['desc'] : 'N/A'; |
| 739 |
$enabled = isset( $item['enabled'] ) && ! empty( $item['enabled'] ) ? true : false; |
| 740 |
$endcoded_ck = rawurlencode( $ck ); |
| 741 |
|
| 742 |
$pers_codes = ''; |
| 743 |
if ( ! isset( $item['perms'] ) ) { |
| 744 |
$pers_codes = 'r,w,d'; // to compatible. |
| 745 |
} elseif ( ! empty( $item['perms'] ) ) { |
| 746 |
$pers_codes = $item['perms']; |
| 747 |
} |
| 748 |
|
| 749 |
$pers_names = array(); |
| 750 |
if ( ! empty( $pers_codes ) && is_string( $pers_codes ) ) { |
| 751 |
$pers_codes = explode( ',', $pers_codes ); |
| 752 |
if ( is_array( $pers_codes ) ) { |
| 753 |
if ( in_array( 'r', $pers_codes ) ) { |
| 754 |
$pers_names[] = esc_html__( 'Read', 'mainwp' ); |
| 755 |
} |
| 756 |
if ( in_array( 'w', $pers_codes ) ) { |
| 757 |
$pers_names[] = esc_html__( 'Write', 'mainwp' ); |
| 758 |
} |
| 759 |
if ( in_array( 'd', $pers_codes ) ) { |
| 760 |
$pers_names[] = esc_html__( 'Delete', 'mainwp' ); |
| 761 |
} |
| 762 |
} |
| 763 |
} |
| 764 |
|
| 765 |
?> |
| 766 |
<tr key-ck-id="<?php echo esc_attr( $endcoded_ck ); ?>"> |
| 767 |
<td class="check-column"> |
| 768 |
<div class="ui checkbox"> |
| 769 |
<input type="checkbox" |
| 770 |
aria-label="<?php echo esc_attr__( 'Select API key described as: ', 'mainwp' ) . esc_html( $desc ); ?>" |
| 771 |
value="<?php echo esc_html( $endcoded_ck ); ?>" name="" /> |
| 772 |
</div> |
| 773 |
</td> |
| 774 |
<td><?php echo $enabled ? '<span class="ui green fluid label">' . esc_html__( 'Enabled', 'mainwp' ) . '</span>' : '<span class="ui gray fluid label">' . esc_html__( 'Disabled', 'mainwp' ) . '</span>'; ?> |
| 775 |
</td> |
| 776 |
<td> |
| 777 |
<?php if ( $can_edit_keys ) : ?> |
| 778 |
<?php |
| 779 |
$url = add_query_arg( |
| 780 |
array( |
| 781 |
'page' => 'AddApiKeys', |
| 782 |
'editkey' => $endcoded_ck, |
| 783 |
'_opennonce' => wp_create_nonce( 'mainwp-admin-nonce' ), |
| 784 |
), |
| 785 |
admin_url( 'admin.php' ) |
| 786 |
); |
| 787 |
?> |
| 788 |
<a href="<?php echo esc_url( $url ); ?>"><?php echo esc_html( $desc ); ?></a> |
| 789 |
<?php else : ?> |
| 790 |
<?php echo esc_html( $desc ); ?> |
| 791 |
<?php endif; ?> |
| 792 |
</td> |
| 793 |
<td><?php echo ! empty( $pers_names ) ? implode( ', ', $pers_names ) : 'N/A'; // phpcs:ignore WordPress.Security.EscapeOutput ?> |
| 794 |
</td> |
| 795 |
<td><code><?php echo esc_html( '...' . $ending ); // phpcs:ignore WordPress.Security.EscapeOutput ?></code> |
| 796 |
</td> |
| 797 |
<?php if ( $can_edit_keys || $can_delete_keys ) : ?> |
| 798 |
<td class="right aligned"> |
| 799 |
<div class="ui right pointing dropdown" style="z-index:999"> |
| 800 |
<i class="ellipsis vertical icon"></i> |
| 801 |
<div class="menu"> |
| 802 |
<?php if ( $can_edit_keys ) : ?> |
| 803 |
<?php |
| 804 |
$url = add_query_arg( |
| 805 |
array( |
| 806 |
'page' => 'AddApiKeys', |
| 807 |
'editkey' => $endcoded_ck, |
| 808 |
'_opennonce' => wp_create_nonce( 'mainwp-admin-nonce' ), |
| 809 |
), |
| 810 |
admin_url( 'admin.php' ) |
| 811 |
); |
| 812 |
?> |
| 813 |
<a class="item" |
| 814 |
href="<?php echo esc_url( $url ); ?>"><?php esc_html_e( 'Edit', 'mainwp' ); ?></a> |
| 815 |
<?php endif; ?> |
| 816 |
<?php if ( $can_delete_keys ) : ?> |
| 817 |
<a class="item" href="javascript:void(0)" |
| 818 |
onclick="mainwp_restapi_remove_key_confirm(jQuery(this).closest('tr').find('.check-column INPUT:checkbox'));"><?php esc_html_e( 'Delete', 'mainwp' ); ?></a> |
| 819 |
<?php endif; ?> |
| 820 |
</div> |
| 821 |
</div> |
| 822 |
</td> |
| 823 |
<?php endif; ?> |
| 824 |
</tr> |
| 825 |
<?php } ?> |
| 826 |
</tbody> |
| 827 |
</table> |
| 828 |
<script type="text/javascript"> |
| 829 |
var responsive = true; |
| 830 |
if (jQuery(window).width() > 1140) { |
| 831 |
responsive = false; |
| 832 |
} |
| 833 |
jQuery(document).ready(function ($) { |
| 834 |
try { |
| 835 |
jQuery('#mainwp-rest-api-keys-table').DataTable({ |
| 836 |
"lengthMenu": [[5, 10, 25, 50, 100, -1], [5, 10, 25, 50, 100, "All"]], |
| 837 |
"stateSave": true, |
| 838 |
"order": [[1, 'asc']], |
| 839 |
"columnDefs": [{ |
| 840 |
"targets": 'no-sort', |
| 841 |
"orderable": false |
| 842 |
}], |
| 843 |
"responsive": responsive, |
| 844 |
"preDrawCallback": function () { |
| 845 |
jQuery('#mainwp-rest-api-keys-table .ui.dropdown').dropdown(); |
| 846 |
jQuery('#mainwp-rest-api-keys-table .ui.checkbox').checkbox(); |
| 847 |
mainwp_datatable_fix_menu_overflow('#mainwp-rest-api-keys-table', -70, 0); |
| 848 |
mainwp_table_check_columns_init(); // ajax: to fix checkbox all. |
| 849 |
} |
| 850 |
}); |
| 851 |
mainwp_datatable_fix_menu_overflow('#mainwp-rest-api-keys-table', -70, 0); |
| 852 |
} catch { |
| 853 |
// to fix js error. |
| 854 |
} |
| 855 |
}); |
| 856 |
</script> |
| 857 |
<?php |
| 858 |
} |
| 859 |
} |
| 860 |
|
| 861 |
/** Render REST API SubPage */ |
| 862 |
public static function render_api_keys_v2_table() { // phpcs:ignore -- NOSONAR - complex. |
| 863 |
$all_keys_v2 = MainWP_DB::instance()->get_rest_api_keys(); |
| 864 |
$can_edit_keys = static::can_edit_rest_api_keys(); |
| 865 |
$can_delete_keys = static::can_delete_rest_api_keys(); |
| 866 |
$el_id_cb_1 = 'cb-select-all-top'; |
| 867 |
?> |
| 868 |
<table id="mainwp-rest-api-keys-v2-table" class="ui unstackable single line table"> |
| 869 |
<thead> |
| 870 |
<tr> |
| 871 |
<th scope="col" class="no-sort collapsing check-column"> |
| 872 |
<span class="ui checkbox"> |
| 873 |
<input |
| 874 |
aria-label="<?php esc_attr_e( 'Select all REST API keys', 'mainwp' ); ?>" |
| 875 |
id="<?php echo esc_attr( $el_id_cb_1 ); ?>" type="checkbox" /> |
| 876 |
</span> |
| 877 |
</th> |
| 878 |
<th scope="col" class="collapsing"><?php esc_html_e( 'Status', 'mainwp' ); ?></th> |
| 879 |
<th scope="col"><?php esc_html_e( 'API Key (v2)', 'mainwp' ); ?></th> |
| 880 |
<th scope="col" class="collapsing"><?php esc_html_e( 'Permissions', 'mainwp' ); ?></th> |
| 881 |
<th scope="col" class="no-sort collapsing"><?php esc_html_e( 'API key ending in', 'mainwp' ); ?></th> |
| 882 |
<th scope="col" class="collapsing"><?php esc_html_e( 'Last access', 'mainwp' ); ?></th> |
| 883 |
<?php if ( $can_edit_keys || $can_delete_keys ) : ?> |
| 884 |
<th scope="col" class="no-sort collapsing"></th> |
| 885 |
<?php endif; ?> |
| 886 |
</tr> |
| 887 |
</thead> |
| 888 |
<tbody id="mainwp-rest-api-v2-body-table" class="mainwp-rest-api-body-table-manage"> |
| 889 |
<?php |
| 890 |
if ( is_array( $all_keys_v2 ) ) : |
| 891 |
foreach ( $all_keys_v2 as $item ) : |
| 892 |
$ending = $item->truncated_key; |
| 893 |
$desc = ! empty( $item->description ) ? esc_html( $item->description ) : 'N/A'; |
| 894 |
$enabled = $item->enabled ? true : false; |
| 895 |
$key_id = $item->key_id; |
| 896 |
|
| 897 |
$pers_title = array(); |
| 898 |
$per = $item->permissions; |
| 899 |
if ( 'read' === $per ) { |
| 900 |
$pers_title[] = esc_html__( 'Read', 'mainwp' ); |
| 901 |
} |
| 902 |
if ( 'write' === $per || 'delete' === $per ) { |
| 903 |
$pers_title[] = esc_html__( 'Write & Delete', 'mainwp' ); |
| 904 |
} |
| 905 |
if ( 'read_write' === $per ) { |
| 906 |
$pers_title[] = esc_html__( 'Read', 'mainwp' ); |
| 907 |
$pers_title[] = esc_html__( 'Write & Delete', 'mainwp' ); |
| 908 |
} |
| 909 |
$url = ''; |
| 910 |
if ( $can_edit_keys ) { |
| 911 |
$url = add_query_arg( |
| 912 |
array( |
| 913 |
'page' => 'AddApiKeys', |
| 914 |
'editkey' => intval( $key_id ), |
| 915 |
'rest_ver' => 2, |
| 916 |
'_opennonce' => wp_create_nonce( 'mainwp-admin-nonce' ), |
| 917 |
), |
| 918 |
admin_url( 'admin.php' ) |
| 919 |
); |
| 920 |
} |
| 921 |
?> |
| 922 |
<tr key-ck-id="<?php echo intval( $key_id ); ?>"> |
| 923 |
<td class="check-column"> |
| 924 |
<div class="ui checkbox"> |
| 925 |
<input type="checkbox" |
| 926 |
aria-label="<?php echo esc_attr__( 'Select API key described as: ', 'mainwp' ) . esc_html( $desc ); ?>" |
| 927 |
value="<?php echo intval( $key_id ); ?>" name="" /> |
| 928 |
</div> |
| 929 |
</td> |
| 930 |
<td><?php echo $enabled ? '<span class="ui green fluid label">' . esc_html__( 'Enabled', 'mainwp' ) . '</span>' : '<span class="ui gray fluid label">' . esc_html__( 'Disabled', 'mainwp' ) . '</span>'; ?> |
| 931 |
</td> |
| 932 |
<td> |
| 933 |
<?php if ( $can_edit_keys ) : ?> |
| 934 |
<a href="<?php echo esc_url( $url ); ?>"><?php echo esc_html( $desc ); ?></a> |
| 935 |
<?php else : ?> |
| 936 |
<?php echo esc_html( $desc ); ?> |
| 937 |
<?php endif; ?> |
| 938 |
</td> |
| 939 |
<td><?php echo ! empty( $pers_title ) ? implode( ', ', $pers_title ) : 'N/A'; // phpcs:ignore WordPress.Security.EscapeOutput ?> |
| 940 |
</td> |
| 941 |
<td><code><?php echo esc_html( '...' . $ending ); // phpcs:ignore WordPress.Security.EscapeOutput ?></code> |
| 942 |
</td> |
| 943 |
<td data-order="<?php echo ! empty( $item->last_access ) ? esc_attr( strtotime( $item->last_access ) ) : 0; ?>"> |
| 944 |
<?php echo ! empty( $item->last_access ) ? '<span data-tooltip="' . esc_attr( MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( strtotime( $item->last_access ) ) ) ) . '" data-position="left center" data-inverted="">' . esc_html( MainWP_Utility::time_elapsed_string( strtotime( $item->last_access ) ) ) . '</span>' : 'N/A'; // phpcs:ignore WordPress.Security.EscapeOutput ?> |
| 945 |
</td> |
| 946 |
<?php if ( $can_edit_keys || $can_delete_keys ) : ?> |
| 947 |
<td class="right aligned"> |
| 948 |
<div class="ui right pointing dropdown" style="z-index:999"> |
| 949 |
<i class="ellipsis vertical icon"></i> |
| 950 |
<div class="menu"> |
| 951 |
<?php if ( $can_edit_keys ) : ?> |
| 952 |
<a class="item" |
| 953 |
href="<?php echo esc_url( $url ); ?>"><?php esc_html_e( 'Edit', 'mainwp' ); ?></a> |
| 954 |
<?php endif; ?> |
| 955 |
<?php if ( $can_delete_keys ) : ?> |
| 956 |
<a class="item" href="javascript:void(0)" |
| 957 |
onclick="mainwp_restapi_remove_key_confirm(jQuery(this).closest('tr').find('.check-column INPUT:checkbox'));"><?php esc_html_e( 'Delete', 'mainwp' ); ?></a> |
| 958 |
<?php endif; ?> |
| 959 |
</div> |
| 960 |
</div> |
| 961 |
</td> |
| 962 |
<?php endif; ?> |
| 963 |
</tr> |
| 964 |
<?php |
| 965 |
endforeach; |
| 966 |
endif; |
| 967 |
?> |
| 968 |
</tbody> |
| 969 |
</table> |
| 970 |
<script type="text/javascript"> |
| 971 |
var responsive = true; |
| 972 |
if (jQuery(window).width() > 1140) { |
| 973 |
responsive = false; |
| 974 |
} |
| 975 |
jQuery(document).ready(function ($) { |
| 976 |
try { |
| 977 |
jQuery('#mainwp-rest-api-keys-v2-table').DataTable({ |
| 978 |
"lengthMenu": [[5, 10, 25, 50, 100, -1], [5, 10, 25, 50, 100, "All"]], |
| 979 |
"stateSave": true, |
| 980 |
"order": [[1, 'asc']], |
| 981 |
"columnDefs": [{ |
| 982 |
"targets": 'no-sort', |
| 983 |
"orderable": false |
| 984 |
}], |
| 985 |
"responsive": responsive, |
| 986 |
"preDrawCallback": function () { |
| 987 |
jQuery('#mainwp-rest-api-keys-v2-table .ui.dropdown').dropdown(); |
| 988 |
jQuery('#mainwp-rest-api-keys-v2-table .ui.checkbox').checkbox(); |
| 989 |
mainwp_datatable_fix_menu_overflow('#mainwp-rest-api-keys-v2-table', -70, 0); |
| 990 |
mainwp_table_check_columns_init(); // ajax: to fix checkbox all. |
| 991 |
} |
| 992 |
}); |
| 993 |
mainwp_datatable_fix_menu_overflow('#mainwp-rest-api-keys-v2-table', -70, 0); |
| 994 |
} catch { |
| 995 |
// to fix js error. |
| 996 |
} |
| 997 |
}); |
| 998 |
</script> |
| 999 |
|
| 1000 |
<?php |
| 1001 |
} |
| 1002 |
|
| 1003 |
/** |
| 1004 |
* Render All API Keys |
| 1005 |
*/ |
| 1006 |
public static function render_all_api_keys() { // phpcs:ignore -- NOSONAR - complex. |
| 1007 |
// Allow page if user can view REST API (any of manage/create/edit/delete). |
| 1008 |
if ( ! static::can_access_rest_api() ) { |
| 1009 |
static::render_permission_denied_ui( |
| 1010 |
esc_html__( 'API Access', 'mainwp' ), |
| 1011 |
esc_html__( 'You do not have permission to view the REST API. If you need access to this page please contact the dashboard administrator.', 'mainwp' ) |
| 1012 |
); |
| 1013 |
return; |
| 1014 |
} |
| 1015 |
$all_keys = static::check_rest_api_updates(); |
| 1016 |
if ( ! is_array( $all_keys ) ) { |
| 1017 |
$all_keys = array(); |
| 1018 |
} |
| 1019 |
$all_keys_v2 = MainWP_DB::instance()->get_rest_api_keys(); |
| 1020 |
$has_no_api_keys = empty( $all_keys ) && empty( $all_keys_v2 ); |
| 1021 |
static::render_header(); |
| 1022 |
static::render_table_top( $has_no_api_keys ); |
| 1023 |
if ( ! static::check_rest_api_enabled() ) { |
| 1024 |
?> |
| 1025 |
<div class="ui message yellow"> |
| 1026 |
<?php |
| 1027 |
// translators: 1: Opening anchor tag. 2: Closing anchor tag. |
| 1028 |
printf( esc_html__( 'It seems the WordPress REST API is currently disabled on your site. MainWP REST API requires the WordPress REST API to function properly. Please enable it to ensure smooth operation. Need help? %1$sClick here for a guide%2$s.', 'mainwp' ), '<a href="https://docs.mainwp.com/troubleshooting/wordpress-rest-api-does-not-respond" target="_blank">', '</a> <i class="external alternate icon"></i>' ); |
| 1029 |
?> |
| 1030 |
</div> |
| 1031 |
<?php |
| 1032 |
} |
| 1033 |
?> |
| 1034 |
<div id="mainwp-rest-api-keys" class="ui padded segment"> |
| 1035 |
<?php if ( $has_no_api_keys ) : ?> |
| 1036 |
<?php |
| 1037 |
MainWP_UI::render_empty_page_placeholder( |
| 1038 |
esc_html__( 'No API Keys yet', 'mainwp' ), |
| 1039 |
esc_html__( 'Create an API key to integrate MainWP with your custom tools, automations, and external platforms through the REST API.', 'mainwp' ), |
| 1040 |
'<em data-emoji=":key:" class="big"></em>' |
| 1041 |
); |
| 1042 |
?> |
| 1043 |
<?php if ( static::can_create_rest_api_keys() ) : ?> |
| 1044 |
<div class="ui center aligned basic segment"> |
| 1045 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=AddApiKeys' ) ); ?>" |
| 1046 |
class="ui green button"><?php esc_html_e( 'Create New API Key', 'mainwp' ); ?></a> |
| 1047 |
</div> |
| 1048 |
<?php endif; ?> |
| 1049 |
<?php endif; ?> |
| 1050 |
|
| 1051 |
|
| 1052 |
<div class="ui message" id="mainwp-message-zone-apikeys" style="display:none;"></div> |
| 1053 |
<?php static::show_messages(); ?> |
| 1054 |
<?php if ( ! $has_no_api_keys ) : ?> |
| 1055 |
<div class="ui basic accordion mainwp-blank-accordion" id="mainwp-rest-api-keys-accordion"> |
| 1056 |
<h2 class="ui dividing header active title"> |
| 1057 |
<i class="right dropdown icon"></i> |
| 1058 |
<?php esc_html_e( 'MainWP REST API v2 API Keys', 'mainwp' ); ?> |
| 1059 |
<div class="sub header"> |
| 1060 |
<?php esc_html_e( 'Generate secure API Keys to connect your MainWP Dashboard with trusted tools and automations.', 'mainwp' ); ?> |
| 1061 |
</div> |
| 1062 |
</h2> |
| 1063 |
<div class="content active"> |
| 1064 |
<?php static::render_api_keys_v2_table(); ?> |
| 1065 |
</div> |
| 1066 |
<?php if ( ! empty( $all_keys ) ) : ?> |
| 1067 |
<h2 class="ui dividing header title"> |
| 1068 |
<i class="right dropdown icon"></i> |
| 1069 |
<?php esc_html_e( 'MainWP REST API v1 API Keys (Legacy)', 'mainwp' ); ?> |
| 1070 |
<div class="sub header"> |
| 1071 |
<?php esc_html_e( 'Legacy API keys for older integrations. We recommend switching to v2 for better security and performance.', 'mainwp' ); ?> |
| 1072 |
</div> |
| 1073 |
</h2> |
| 1074 |
<div class="content"> |
| 1075 |
<?php static::render_api_keys_v1_table(); ?> |
| 1076 |
</div> |
| 1077 |
<?php endif; ?> |
| 1078 |
</div> |
| 1079 |
<script> |
| 1080 |
jQuery(document).ready(function () { |
| 1081 |
jQuery('#mainwp-rest-api-keys-accordion').accordion({ |
| 1082 |
exclusive: false, |
| 1083 |
}); |
| 1084 |
}); |
| 1085 |
</script> |
| 1086 |
<?php endif; ?> |
| 1087 |
</div> |
| 1088 |
<?php |
| 1089 |
static::render_footer(); |
| 1090 |
} |
| 1091 |
|
| 1092 |
/** |
| 1093 |
* Render table top. |
| 1094 |
* |
| 1095 |
* @param bool $has_no_api_keys Whether there are no API keys. |
| 1096 |
*/ |
| 1097 |
public static function render_table_top( $has_no_api_keys = false ) { |
| 1098 |
if ( $has_no_api_keys ) { |
| 1099 |
return; |
| 1100 |
} |
| 1101 |
?> |
| 1102 |
<div class="mainwp-sub-header"> |
| 1103 |
<div class="ui grid"> |
| 1104 |
<div class="equal width row ui mini form"> |
| 1105 |
<div class="middle aligned column"> |
| 1106 |
<?php if ( ! $has_no_api_keys && static::can_delete_rest_api_keys() ) : ?> |
| 1107 |
<div id="mainwp-rest-api-bulk-actions-menu" class="ui selection dropdown disabled"> |
| 1108 |
<div class="default text"><?php esc_html_e( 'Bulk actions', 'mainwp' ); ?></div> |
| 1109 |
<i class="dropdown icon"></i> |
| 1110 |
<div class="menu"> |
| 1111 |
<div class="item" data-value="delete"><?php esc_html_e( 'Delete', 'mainwp' ); ?></div> |
| 1112 |
</div> |
| 1113 |
</div> |
| 1114 |
<button class="ui mini basic button disabled" |
| 1115 |
id="mainwp-do-rest-api-bulk-actions"><?php esc_html_e( 'Apply', 'mainwp' ); ?></button> |
| 1116 |
<?php endif; ?> |
| 1117 |
</div> |
| 1118 |
<div class="right aligned middle aligned column"> |
| 1119 |
<?php if ( static::can_create_rest_api_keys() ) : ?> |
| 1120 |
<a href="admin.php?page=AddApiKeys" |
| 1121 |
class="ui mini green button"><?php esc_html_e( 'Create New API Key', 'mainwp' ); ?></a> |
| 1122 |
<?php endif; ?> |
| 1123 |
</div> |
| 1124 |
</div> |
| 1125 |
</div> |
| 1126 |
</div> |
| 1127 |
<?php |
| 1128 |
} |
| 1129 |
|
| 1130 |
/** |
| 1131 |
* Method check_rest_api_updates(). |
| 1132 |
* |
| 1133 |
* To Checks for updating REST API keys. |
| 1134 |
*/ |
| 1135 |
public static function check_rest_api_updates() { |
| 1136 |
$all_keys = get_option( 'mainwp_rest_api_keys', false ); |
| 1137 |
$cs = get_option( 'mainwp_rest_api_consumer_key', false ); |
| 1138 |
|
| 1139 |
// to compatible. |
| 1140 |
if ( false === $all_keys || false !== $cs ) { |
| 1141 |
if ( ! is_array( $all_keys ) ) { |
| 1142 |
$all_keys = array(); |
| 1143 |
} |
| 1144 |
if ( ! empty( $cs ) ) { |
| 1145 |
$all_keys[ $cs ] = array( |
| 1146 |
'ck' => get_option( 'mainwp_rest_api_consumer_key', '' ), |
| 1147 |
'cs' => get_option( 'mainwp_rest_api_consumer_secret', '' ), |
| 1148 |
'desc' => '', |
| 1149 |
); |
| 1150 |
} |
| 1151 |
MainWP_Utility::update_option( 'mainwp_rest_api_keys', $all_keys ); |
| 1152 |
|
| 1153 |
if ( false !== $cs ) { |
| 1154 |
delete_option( 'mainwp_rest_api_consumer_key' ); |
| 1155 |
delete_option( 'mainwp_rest_api_consumer_secret' ); |
| 1156 |
delete_option( 'mainwp_enable_rest_api' ); |
| 1157 |
} |
| 1158 |
} |
| 1159 |
// end. |
| 1160 |
return $all_keys; |
| 1161 |
} |
| 1162 |
|
| 1163 |
|
| 1164 |
/** |
| 1165 |
* Method show_messages(). |
| 1166 |
*/ |
| 1167 |
public static function show_messages() { |
| 1168 |
$msg = ''; |
| 1169 |
$tone = 'green'; |
| 1170 |
if ( isset( $_GET['message'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification |
| 1171 |
$message = sanitize_key( wp_unslash( $_GET['message'] ) ); // phpcs:ignore WordPress.Security.NonceVerification |
| 1172 |
if ( 'saved' === $message || 'created' === $message ) { |
| 1173 |
$msg = esc_html__( 'API Key have been saved successfully!', 'mainwp' ); |
| 1174 |
} elseif ( 'create_failed' === $message ) { |
| 1175 |
$msg = esc_html__( 'Could not save the API key. The credential was generated but the database did not accept the insert, so no key was stored. Please try again or contact MainWP support if the problem persists.', 'mainwp' ); |
| 1176 |
$tone = 'red'; |
| 1177 |
} |
| 1178 |
} |
| 1179 |
if ( ! empty( $msg ) ) { |
| 1180 |
?> |
| 1181 |
<div class="ui <?php echo esc_attr( $tone ); ?> message"><i class="close icon"></i><?php echo esc_html( $msg ); ?></div> |
| 1182 |
<?php |
| 1183 |
} |
| 1184 |
} |
| 1185 |
|
| 1186 |
/** |
| 1187 |
* Render REST API SubPage |
| 1188 |
*/ |
| 1189 |
public static function render_rest_api_setings() { //phpcs:ignore -- NOSONAR - complex. |
| 1190 |
// Allow access if user can create or edit REST API keys (manage alone cannot create/edit). |
| 1191 |
if ( ! ( static::can_create_rest_api_keys() || static::can_edit_rest_api_keys() ) ) { |
| 1192 |
static::render_permission_denied_ui( |
| 1193 |
esc_html__( 'API Access', 'mainwp' ), |
| 1194 |
esc_html__( 'You do not have permission to manage REST API keys. If you need access to this page please contact the dashboard administrator.', 'mainwp' ) |
| 1195 |
); |
| 1196 |
return; |
| 1197 |
} |
| 1198 |
|
| 1199 |
$edit_key = false; |
| 1200 |
if ( isset( $_GET['editkey'] ) && ! empty( $_GET['editkey'] ) && isset( $_GET['_opennonce'] ) && wp_verify_nonce( sanitize_key( $_GET['_opennonce'] ), 'mainwp-admin-nonce' ) ) { |
| 1201 |
$edit_key = wp_unslash( $_GET['editkey'] ); // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 1202 |
} |
| 1203 |
|
| 1204 |
$edit_item = array(); |
| 1205 |
if ( false !== $edit_key ) { |
| 1206 |
if ( empty( $_GET['rest_ver'] ) ) { |
| 1207 |
$edit_key = urldecode( $edit_key ); |
| 1208 |
$all_keys = get_option( 'mainwp_rest_api_keys', false ); |
| 1209 |
if ( ! is_array( $all_keys ) || ! isset( $all_keys[ $edit_key ] ) ) { |
| 1210 |
$edit_key = false; |
| 1211 |
} else { |
| 1212 |
$edit_item = $all_keys[ $edit_key ]; |
| 1213 |
} |
| 1214 |
|
| 1215 |
if ( ! empty( $edit_item ) ) { |
| 1216 |
static::render_rest_api_edit( $edit_key, $edit_item ); |
| 1217 |
return; |
| 1218 |
} |
| 1219 |
} else { |
| 1220 |
$key_id = intval( $edit_key ); |
| 1221 |
$edit_item = MainWP_DB::instance()->get_rest_api_key_by( $key_id ); |
| 1222 |
if ( ! empty( $edit_item ) ) { |
| 1223 |
static::render_rest_api_v2_edit( $edit_item ); |
| 1224 |
return; |
| 1225 |
} |
| 1226 |
} |
| 1227 |
} |
| 1228 |
|
| 1229 |
// we need to generate a consumer key and secret and return the result and save it into the database. |
| 1230 |
$_consumer_key = static::mainwp_generate_rand_hash(); |
| 1231 |
$_consumer_secret = static::mainwp_generate_rand_hash(); |
| 1232 |
|
| 1233 |
$consumer_key = 'ck_' . $_consumer_key; |
| 1234 |
$consumer_secret = 'cs_' . $_consumer_secret; |
| 1235 |
|
| 1236 |
static::render_header( 'Settings' ); |
| 1237 |
|
| 1238 |
?> |
| 1239 |
<div id="rest-api-settings" class="ui padded segment"> |
| 1240 |
<h2 class="ui dividing header"> |
| 1241 |
<?php esc_html_e( 'MainWP REST API Credentials', 'mainwp' ); ?> |
| 1242 |
<div class="sub header"> |
| 1243 |
<?php esc_html_e( 'Generate, manage, and revoke API keys to securely connect with the MainWP REST API. Ensure you\'re using the correct version for your integrations.', 'mainwp' ); ?> |
| 1244 |
</div> |
| 1245 |
</h2> |
| 1246 |
<div id="api-credentials-created" class="ui green message"> |
| 1247 |
<strong><?php esc_html_e( 'API Key Created Successfully!', 'mainwp' ); ?></strong><br /> |
| 1248 |
<?php esc_html_e( 'Copy your key and store it securely. It will not be visible again!', 'mainwp' ); ?> |
| 1249 |
</div> |
| 1250 |
|
| 1251 |
<?php static::show_messages(); ?> |
| 1252 |
|
| 1253 |
<div class="ui info message"> |
| 1254 |
<?php esc_html_e( 'The API Key (Bearer) authentication is only compatible with the MainWP REST API v2', 'mainwp' ); ?> |
| 1255 |
<?php esc_html_e( 'If you are working with the MainWP REST API v1 (Legacy), click on the "Show Legacy API Credentials" button to obtain your Consumer Key and Consumer Secret.', 'mainwp' ); ?> |
| 1256 |
</div> |
| 1257 |
|
| 1258 |
<div class="ui form"> |
| 1259 |
<form method="POST" action=""> |
| 1260 |
<?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?> |
| 1261 |
<input type="hidden" name="wp_nonce" value="<?php echo esc_attr( wp_create_nonce( 'RESTAPI' ) ); ?>" /> |
| 1262 |
<?php |
| 1263 |
/** |
| 1264 |
* Action: rest_api_form_top |
| 1265 |
* |
| 1266 |
* Fires at the top of REST API form. |
| 1267 |
* |
| 1268 |
* @since 4.1 |
| 1269 |
*/ |
| 1270 |
do_action( 'rest_api_form_top' ); |
| 1271 |
?> |
| 1272 |
<div class="ui grid field"> |
| 1273 |
<label class="six wide column middle aligned" for="mainwp_enable_rest_api"><?php esc_html_e( 'Enable API key', 'mainwp' ); ?></label> |
| 1274 |
<div class="ten wide column ui toggle checkbox"> |
| 1275 |
<input type="checkbox" name="mainwp_enable_rest_api" id="mainwp_enable_rest_api" checked="true" |
| 1276 |
aria-label="<?php esc_attr_e( 'Enable REST API key', 'mainwp' ); // NOSONAR. ?>" /> |
| 1277 |
</div> |
| 1278 |
</div> |
| 1279 |
<div class="ui grid field"> |
| 1280 |
<label class="six wide column middle aligned" for="mainwp_rest_add_api_key_desc"><?php esc_html_e( 'API key name', 'mainwp' ); ?></label> |
| 1281 |
<div class="five wide column"> |
| 1282 |
<input type="text" name="mainwp_rest_add_api_key_desc" id="mainwp_rest_add_api_key_desc" value="" |
| 1283 |
aria-label="<?php esc_attr_e( 'API key name.', 'mainwp' ); ?>" /> |
| 1284 |
</div> |
| 1285 |
</div> |
| 1286 |
|
| 1287 |
<div class="ui grid field"> |
| 1288 |
<label |
| 1289 |
class="six wide column middle aligned" for="mainwp_rest_api_keys_compatible_v1"><?php esc_html_e( 'Enable MainWP REST API v1 Compatibility', 'mainwp' ); ?></label> |
| 1290 |
<div class="ten wide column ui toggle checkbox" |
| 1291 |
data-tooltip="<?php esc_attr_e( 'If enabled, the credentials will be compatible with REST API v1.', 'mainwp' ); ?>" |
| 1292 |
data-inverted="" data-position="bottom left"> |
| 1293 |
<input type="checkbox" name="mainwp_rest_api_keys_compatible_v1" |
| 1294 |
id="mainwp_rest_api_keys_compatible_v1" |
| 1295 |
aria-label="<?php esc_attr_e( 'If enabled, the credentials will be compatible with REST API v1.', 'mainwp' ); ?>" /> |
| 1296 |
</div> |
| 1297 |
</div> |
| 1298 |
|
| 1299 |
<?php $init_pers = 'r,w,d'; ?> |
| 1300 |
|
| 1301 |
<div class="ui grid field"> |
| 1302 |
<label class="six wide column middle aligned"><?php esc_html_e( 'Permissions', 'mainwp' ); ?></label> |
| 1303 |
<div class="ten wide column"> |
| 1304 |
<div class="mainwp-rest-api-permission-chips" data-init-value="<?php echo esc_attr( $init_pers ); ?>" data-api-version="v2"> |
| 1305 |
<input type="hidden" name="mainwp_rest_api_key_edit_pers" value="" /> |
| 1306 |
<button type="button" class="ui basic label mainwp-permission-chip" data-permission="r"> |
| 1307 |
<i class="book icon"></i> |
| 1308 |
<?php esc_html_e( 'Read', 'mainwp' ); ?> |
| 1309 |
</button> |
| 1310 |
<button type="button" class="ui basic label mainwp-permission-chip mainwp-v2-chip" data-permission="w,d"> |
| 1311 |
<i class="pencil icon"></i> |
| 1312 |
<?php esc_html_e( 'Write & Delete', 'mainwp' ); ?> |
| 1313 |
</button> |
| 1314 |
<button type="button" class="ui basic label mainwp-permission-chip mainwp-v1-chip" data-permission="w" style="display:none;"> |
| 1315 |
<i class="pencil icon"></i> |
| 1316 |
<?php esc_html_e( 'Write', 'mainwp' ); ?> |
| 1317 |
</button> |
| 1318 |
<button type="button" class="ui basic label mainwp-permission-chip mainwp-v1-chip" data-permission="d" style="display:none;"> |
| 1319 |
<i class="trash icon"></i> |
| 1320 |
<?php esc_html_e( 'Delete', 'mainwp' ); ?> |
| 1321 |
</button> |
| 1322 |
</div> |
| 1323 |
<div class="mainwp-permission-chips-help"> |
| 1324 |
<span class="ui small grey text"><?php esc_html_e( 'Choose what actions this key can perform on your Dashboard data.', 'mainwp' ); ?></span> |
| 1325 |
</div> |
| 1326 |
</div> |
| 1327 |
</div> |
| 1328 |
|
| 1329 |
<?php |
| 1330 |
$token = $_consumer_secret . '==' . $_consumer_key; |
| 1331 |
?> |
| 1332 |
<div class="ui grid field"> |
| 1333 |
<label |
| 1334 |
class="six wide column middle aligned" for="mainwp_rest_token"><?php esc_html_e( 'API key (Bearer token)', 'mainwp' ); ?></label> |
| 1335 |
<div class="five wide column"> |
| 1336 |
<input type="text" name="mainwp_rest_token" id="mainwp_rest_token" |
| 1337 |
value="<?php echo esc_html( $token ); ?>" readonly |
| 1338 |
aria-label="<?php esc_attr_e( 'API Token', 'mainwp' ); ?>" /> |
| 1339 |
</div> |
| 1340 |
<div class="five wide column"> |
| 1341 |
<input id="mainwp_rest_token_clipboard_button" style="display:nonce;" type="button" name="" |
| 1342 |
class="ui green basic button copy-to-clipboard" |
| 1343 |
value="<?php esc_attr_e( 'Copy to Clipboard', 'mainwp' ); // NOSONAR. ?>"> |
| 1344 |
</div> |
| 1345 |
</div> |
| 1346 |
|
| 1347 |
<div id="mainwp-legacy-api-credentials" class="ui segment" style="display:none"> |
| 1348 |
<h3 class="ui dividing header"> |
| 1349 |
<?php esc_html_e( 'Legacy API Credentials', 'mainwp' ); ?> |
| 1350 |
<div class="sub header"> |
| 1351 |
<?php esc_html_e( 'Authentication compatible only with the MainWP REST API version 1!', 'mainwp' ); ?> |
| 1352 |
</div> |
| 1353 |
</h3> |
| 1354 |
|
| 1355 |
<div class="ui grid field"> |
| 1356 |
<label |
| 1357 |
class="six wide column middle aligned" for="mainwp_consumer_key"><?php esc_html_e( 'Consumer key', 'mainwp' ); ?></label> |
| 1358 |
<div class="five wide column"> |
| 1359 |
<input type="text" name="mainwp_consumer_key" id="mainwp_consumer_key" |
| 1360 |
value="<?php echo esc_html( $consumer_key ); ?>" readonly |
| 1361 |
aria-label="<?php esc_attr_e( 'Consumer key', 'mainwp' ); ?>" /> |
| 1362 |
</div> |
| 1363 |
<div class="five wide column"> |
| 1364 |
<input id="mainwp_consumer_key_clipboard_button" style="display:nonce;" type="button" name="" |
| 1365 |
class="ui green basic button copy-to-clipboard" |
| 1366 |
value="<?php esc_attr_e( 'Copy to Clipboard', 'mainwp' ); ?>"> |
| 1367 |
</div> |
| 1368 |
</div> |
| 1369 |
|
| 1370 |
<div class="ui grid field"> |
| 1371 |
<label |
| 1372 |
class="six wide column middle aligned" for="mainwp_consumer_secret"><?php esc_html_e( 'Consumer secret', 'mainwp' ); ?></label> |
| 1373 |
<div class="five wide column"> |
| 1374 |
<input type="text" name="mainwp_consumer_secret" id="mainwp_consumer_secret" |
| 1375 |
value="<?php echo esc_html( $consumer_secret ); ?>" readonly |
| 1376 |
aria-label="<?php esc_attr_e( 'Consumer secret', 'mainwp' ); ?>" /> |
| 1377 |
</div> |
| 1378 |
<div class="five wide column"> |
| 1379 |
<input id="mainwp_consumer_secret_clipboard_button" style="display:nonce;" type="button" name="" |
| 1380 |
class="ui green basic button copy-to-clipboard" |
| 1381 |
value="<?php esc_attr_e( 'Copy to Clipboard', 'mainwp' ); ?>"> |
| 1382 |
</div> |
| 1383 |
</div> |
| 1384 |
</div> |
| 1385 |
<?php |
| 1386 |
/** |
| 1387 |
* Action: rest_api_form_bottom |
| 1388 |
* |
| 1389 |
* Fires at the bottom of REST API form. |
| 1390 |
* |
| 1391 |
* @since 4.1 |
| 1392 |
*/ |
| 1393 |
do_action( 'rest_api_form_bottom' ); |
| 1394 |
?> |
| 1395 |
<div class="ui divider"></div> |
| 1396 |
<input type="submit" name="submit" id="submit-save-settings-button" class="ui green big button" |
| 1397 |
value="<?php esc_attr_e( 'Save Key', 'mainwp' ); ?>" /> |
| 1398 |
<div style="clear:both"></div> |
| 1399 |
</form> |
| 1400 |
</div> |
| 1401 |
</div> |
| 1402 |
<div id="mainwp-api-key-copied-confirm-modal" class="ui mini modal"> |
| 1403 |
<i class="close icon"></i> |
| 1404 |
<div class="header"> |
| 1405 |
<?php esc_html_e( 'API Key Copied', 'mainwp' ); ?> |
| 1406 |
</div> |
| 1407 |
<div class="content"> |
| 1408 |
<p><?php esc_html_e( 'Your API key has been copied to your clipboard.', 'mainwp' ); ?></p> |
| 1409 |
</div> |
| 1410 |
</div> |
| 1411 |
<script type="text/javascript"> |
| 1412 |
jQuery(function ($) { |
| 1413 |
//we are going to inject the values into the copy buttons to make things easier for people |
| 1414 |
$('#mainwp_consumer_key_clipboard_button').attr('data-clipboard-text', '<?php echo esc_html( $consumer_key ); ?>'); |
| 1415 |
$('#mainwp_consumer_secret_clipboard_button').attr('data-clipboard-text', '<?php echo esc_html( $consumer_secret ); ?>'); |
| 1416 |
$('#mainwp_rest_token_clipboard_button').attr('data-clipboard-text', '<?php echo esc_html( $token ); ?>'); //phpcs:ignore -- NOSONAR - token value ok. |
| 1417 |
//initiate clipboard |
| 1418 |
new ClipboardJS('.copy-to-clipboard'); |
| 1419 |
//show copy to clipboard buttons |
| 1420 |
$('.copy-to-clipboard').show(); |
| 1421 |
|
| 1422 |
$('#mainwp_rest_api_keys_compatible_v1').on('change', function () { |
| 1423 |
$('#mainwp-legacy-api-credentials').toggle(); |
| 1424 |
}); |
| 1425 |
}); |
| 1426 |
</script> |
| 1427 |
<?php |
| 1428 |
|
| 1429 |
static::render_footer(); |
| 1430 |
} |
| 1431 |
|
| 1432 |
/** |
| 1433 |
* Method mainwp_generate_rand_hash() |
| 1434 |
* |
| 1435 |
* Generates a random hash to be used when generating the consumer key and secret. |
| 1436 |
* |
| 1437 |
* @return string Returns random string. |
| 1438 |
*/ |
| 1439 |
public static function mainwp_generate_rand_hash() { |
| 1440 |
if ( ! function_exists( 'openssl_random_pseudo_bytes' ) ) { |
| 1441 |
return sha1( wp_rand() ); // NOSONAR - safe for keys. |
| 1442 |
} |
| 1443 |
|
| 1444 |
return bin2hex( openssl_random_pseudo_bytes( 20 ) ); // @codingStandardsIgnoreLine |
| 1445 |
} |
| 1446 |
|
| 1447 |
/** |
| 1448 |
* Method render_rest_api_v2_edit(). |
| 1449 |
* |
| 1450 |
* Render REST API edit screen. |
| 1451 |
* |
| 1452 |
* @param mixed $item The Key edit. |
| 1453 |
*/ |
| 1454 |
public static function render_rest_api_v2_edit( $item ) { //phpcs:ignore -- NOSONAR - complex. |
| 1455 |
$keyid = $item->key_id; |
| 1456 |
$edit_desc = $item->description; |
| 1457 |
$enabled = $item->enabled ? true : false; |
| 1458 |
$ending = $item->truncated_key; |
| 1459 |
$perms = $item->permissions; |
| 1460 |
|
| 1461 |
$init_pers = ''; |
| 1462 |
if ( 'read' === $perms ) { |
| 1463 |
$init_pers = 'r'; |
| 1464 |
} elseif ( 'write' === $perms || 'delete' === $perms ) { |
| 1465 |
$init_pers = 'w,d'; |
| 1466 |
} elseif ( 'read_write' === $perms ) { |
| 1467 |
$init_pers = 'r,w,d'; |
| 1468 |
} |
| 1469 |
static::render_header( 'Edit' ); |
| 1470 |
$el_id_res_api_1 = 'rest-api-settings'; |
| 1471 |
?> |
| 1472 |
<div id="<?php echo esc_attr( $el_id_res_api_1 ); ?>" class="ui segment"> |
| 1473 |
<div class="ui form"> |
| 1474 |
<form method="POST" action=""> |
| 1475 |
<?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?> |
| 1476 |
<input type="hidden" name="edit_key_nonce" |
| 1477 |
value="<?php echo esc_attr( wp_create_nonce( 'edit-key-nonce-' . $keyid ) ); ?>" /> |
| 1478 |
<input type="hidden" name="editkey_id" value="<?php echo esc_html( $keyid ); ?>" /> |
| 1479 |
<input type="hidden" name="rest_v2_edit" value="1" /> |
| 1480 |
<div |
| 1481 |
class="ui grid field settings-field-indicator-wrapper <?php echo $item ? 'settings-field-indicator-edit-api-keys' : ''; ?>"> |
| 1482 |
<label class="six wide column middle aligned" for="mainwp_enable_rest_api"> |
| 1483 |
<?php |
| 1484 |
if ( $item ) { |
| 1485 |
MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $enabled ); |
| 1486 |
} |
| 1487 |
$el_id_en_res_api_1 = 'mainwp_enable_rest_api'; |
| 1488 |
?> |
| 1489 |
<?php esc_html_e( 'Enable REST API Key', 'mainwp' ); ?></label> |
| 1490 |
<div class="ten wide column ui toggle checkbox" |
| 1491 |
data-tooltip="<?php esc_attr_e( 'If enabled, the REST API will be activated.', 'mainwp' ); ?>" |
| 1492 |
data-inverted="" data-position="bottom left"> |
| 1493 |
<input type="checkbox" class="settings-field-value-change-handler" name="mainwp_enable_rest_api" |
| 1494 |
id="<?php echo esc_attr( $el_id_en_res_api_1 ); ?>" value="1" <?php echo $enabled ? 'checked="true"' : ''; ?> |
| 1495 |
aria-label="<?php esc_attr_e( 'Enable REST API key', 'mainwp' ); ?>" /> |
| 1496 |
</div> |
| 1497 |
</div> |
| 1498 |
<div |
| 1499 |
class="ui grid field settings-field-indicator-wrapper <?php echo $item ? 'settings-field-indicator-edit-api-keys' : ''; ?>"> |
| 1500 |
<label class="six wide column middle aligned" for="mainwp_rest_api_key_desc"> |
| 1501 |
<?php |
| 1502 |
if ( $item ) { |
| 1503 |
MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $edit_desc ); |
| 1504 |
} |
| 1505 |
?> |
| 1506 |
<?php esc_html_e( 'Description', 'mainwp' ); ?></label> |
| 1507 |
<div class="five wide column"> |
| 1508 |
<input type="text" class="settings-field-value-change-handler" name="mainwp_rest_api_key_desc" |
| 1509 |
id="mainwp_rest_api_key_desc" value="<?php echo esc_html( $edit_desc ); ?>" |
| 1510 |
aria-label="<?php esc_attr_e( 'Key description', 'mainwp' ); ?>" /> |
| 1511 |
</div> |
| 1512 |
</div> |
| 1513 |
<div |
| 1514 |
class="ui grid field settings-field-indicator-wrapper <?php echo $item ? 'settings-field-indicator-edit-api-keys' : ''; ?>"> |
| 1515 |
<label class="six wide column middle aligned" for="none_preset_value"> |
| 1516 |
<?php |
| 1517 |
if ( $item ) { |
| 1518 |
MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $ending ); |
| 1519 |
} |
| 1520 |
?> |
| 1521 |
<?php esc_html_e( 'Consumer key ending in', 'mainwp' ); ?></label> |
| 1522 |
<div class="five wide column"> |
| 1523 |
<div class="ui disabled input"> |
| 1524 |
<input type="text" class="settings-field-value-change-handler" |
| 1525 |
value="<?php echo esc_attr( '...' . $ending ); ?>" |
| 1526 |
aria-label="<?php esc_attr_e( 'Consumer key ending in...', 'mainwp' ); ?>" /> |
| 1527 |
</div> |
| 1528 |
</div> |
| 1529 |
</div> |
| 1530 |
<div class="ui grid field settings-field-indicator-wrapper <?php echo $item ? 'settings-field-indicator-edit-api-keys' : ''; ?>" |
| 1531 |
default-indi-value="3"> |
| 1532 |
<label class="six wide column middle aligned"> |
| 1533 |
<?php |
| 1534 |
if ( $item ) { |
| 1535 |
$tmp = explode( ',', $init_pers ); |
| 1536 |
$visible = 2 !== count( $tmp ); |
| 1537 |
MainWP_Settings_Indicator::render_indicator( '', '', $visible ); |
| 1538 |
} |
| 1539 |
?> |
| 1540 |
<?php esc_html_e( 'Permissions', 'mainwp' ); ?></label> |
| 1541 |
<div class="ten wide column"> |
| 1542 |
<div class="mainwp-rest-api-permission-chips" data-init-value="<?php echo esc_attr( $init_pers ); ?>" data-api-version="v2"> |
| 1543 |
<input type="hidden" name="mainwp_rest_api_key_edit_pers" class="settings-field-value-change-handler" value="" /> |
| 1544 |
<button type="button" class="ui button chip mainwp-permission-chip" data-permission="r"> |
| 1545 |
<i class="book icon"></i> |
| 1546 |
<?php esc_html_e( 'Read', 'mainwp' ); ?> |
| 1547 |
</button> |
| 1548 |
<button type="button" class="ui button chip mainwp-permission-chip" data-permission="w,d"> |
| 1549 |
<i class="pencil icon"></i> |
| 1550 |
<?php esc_html_e( 'Write & Delete', 'mainwp' ); ?> |
| 1551 |
</button> |
| 1552 |
</div> |
| 1553 |
<div class="mainwp-permission-chips-help" style="margin-top: 8px; font-size: 12px; color: #666;"> |
| 1554 |
<?php esc_html_e( 'Choose what actions this key can perform on your Dashboard data.', 'mainwp' ); ?> |
| 1555 |
</div> |
| 1556 |
</div> |
| 1557 |
</div> |
| 1558 |
<div class="ui divider"></div> |
| 1559 |
<input type="submit" name="submit" id="submit" class="ui green big button" |
| 1560 |
value="<?php esc_attr_e( 'Save API Key', 'mainwp' ); ?>" /> |
| 1561 |
<div style="clear:both"></div> |
| 1562 |
</form> |
| 1563 |
</div> |
| 1564 |
|
| 1565 |
</div> |
| 1566 |
<?php |
| 1567 |
static::render_footer(); |
| 1568 |
} |
| 1569 |
|
| 1570 |
/** |
| 1571 |
* Method render_rest_api_edit(). |
| 1572 |
* |
| 1573 |
* Render REST API edit screen. |
| 1574 |
* |
| 1575 |
* @param string $keyid Key ID edit. |
| 1576 |
* @param array $item The Key edit. |
| 1577 |
*/ |
| 1578 |
public static function render_rest_api_edit( $keyid, $item ) { //phpcs:ignore -- NOSONAR - complex. |
| 1579 |
|
| 1580 |
$edit_desc = is_array( $item ) && isset( $item['desc'] ) ? $item['desc'] : ''; |
| 1581 |
$enabled = is_array( $item ) && isset( $item['enabled'] ) && ! empty( $item['enabled'] ) ? true : false; |
| 1582 |
$ending = substr( $keyid, -8 ); |
| 1583 |
|
| 1584 |
$init_pers = ''; |
| 1585 |
if ( isset( $item['perms'] ) ) { |
| 1586 |
$init_pers = $item['perms']; |
| 1587 |
} else { |
| 1588 |
$init_pers = 'r,w,d'; // to compatible. |
| 1589 |
} |
| 1590 |
|
| 1591 |
static::render_header( 'Edit' ); |
| 1592 |
$el_id_res_api_2 = 'rest-api-settings'; |
| 1593 |
?> |
| 1594 |
<div id="<?php echo esc_attr( $el_id_res_api_2 ); ?>" class="ui segment"> |
| 1595 |
<div class="ui form"> |
| 1596 |
<form method="POST" action=""> |
| 1597 |
<?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?> |
| 1598 |
<input type="hidden" name="edit_key_nonce" |
| 1599 |
value="<?php echo esc_attr( wp_create_nonce( 'edit-key-nonce-' . $keyid ) ); ?>" /> |
| 1600 |
<input type="hidden" name="editkey_id" value="<?php echo esc_html( $keyid ); ?>" /> |
| 1601 |
<div |
| 1602 |
class="ui grid field settings-field-indicator-wrapper <?php echo $item ? 'settings-field-indicator-edit-api-keys' : ''; ?>"> |
| 1603 |
<label class="six wide column middle aligned" for="mainwp_enable_rest_api"> |
| 1604 |
<?php |
| 1605 |
if ( $item ) { |
| 1606 |
MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $enabled ); |
| 1607 |
} |
| 1608 |
$el_id_en_res_api_2 = 'mainwp_enable_rest_api'; |
| 1609 |
?> |
| 1610 |
<?php esc_html_e( 'Enable API key', 'mainwp' ); ?></label> |
| 1611 |
<div class="ten wide column ui toggle checkbox" |
| 1612 |
data-tooltip="<?php esc_attr_e( 'If enabled, the REST API will be activated.', 'mainwp' ); ?>" |
| 1613 |
data-inverted="" data-position="bottom left"> |
| 1614 |
<input type="checkbox" class="settings-field-value-change-handler" name="mainwp_enable_rest_api" |
| 1615 |
id="<?php echo esc_attr( $el_id_en_res_api_2 ); ?>" value="1" <?php echo $enabled ? 'checked="true"' : ''; ?> |
| 1616 |
aria-label="<?php esc_attr_e( 'Enable REST API key', 'mainwp' ); ?>" /> |
| 1617 |
</div> |
| 1618 |
</div> |
| 1619 |
<div |
| 1620 |
class="ui grid field settings-field-indicator-wrapper <?php echo $item ? 'settings-field-indicator-edit-api-keys' : ''; ?>"> |
| 1621 |
<label class="six wide column middle aligned" for="none_preset_value"> |
| 1622 |
<?php |
| 1623 |
if ( $item ) { |
| 1624 |
MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $edit_desc ); |
| 1625 |
} |
| 1626 |
?> |
| 1627 |
<?php esc_html_e( 'Description', 'mainwp' ); ?></label> |
| 1628 |
<div class="five wide column"> |
| 1629 |
<input type="text" class="settings-field-value-change-handler" name="mainwp_rest_api_key_desc" |
| 1630 |
id="mainwp_rest_api_key_desc" value="<?php echo esc_html( $edit_desc ); ?>" |
| 1631 |
aria-label="<?php esc_attr_e( 'Key description', 'mainwp' ); ?>" /> |
| 1632 |
</div> |
| 1633 |
</div> |
| 1634 |
<div |
| 1635 |
class="ui grid field settings-field-indicator-wrapper <?php echo $item ? 'settings-field-indicator-edit-api-keys' : ''; ?>"> |
| 1636 |
<label class="six wide column middle aligned" for="none_preset_value"> |
| 1637 |
<?php |
| 1638 |
if ( $item ) { |
| 1639 |
MainWP_Settings_Indicator::render_not_default_indicator( 'none_preset_value', $ending ); |
| 1640 |
} |
| 1641 |
?> |
| 1642 |
<?php esc_html_e( 'Consumer key ending in', 'mainwp' ); ?></label> |
| 1643 |
<div class="five wide column"> |
| 1644 |
<div class="ui disabled input"> |
| 1645 |
<input type="text" class="settings-field-value-change-handler" |
| 1646 |
value="<?php echo esc_attr( '...' . $ending ); ?>" |
| 1647 |
aria-label="<?php esc_attr_e( 'Consumer key ending in...', 'mainwp' ); ?>" /> |
| 1648 |
</div> |
| 1649 |
</div> |
| 1650 |
</div> |
| 1651 |
<div class="ui grid field settings-field-indicator-wrapper <?php echo $item ? 'settings-field-indicator-edit-api-keys' : ''; ?>" |
| 1652 |
default-indi-value="3"> |
| 1653 |
<label class="six wide column middle aligned"> |
| 1654 |
<?php |
| 1655 |
if ( $item ) { |
| 1656 |
$tmp = explode( ',', $init_pers ); |
| 1657 |
$visible = 3 !== count( $tmp ); |
| 1658 |
MainWP_Settings_Indicator::render_indicator( '', '', $visible ); |
| 1659 |
} |
| 1660 |
?> |
| 1661 |
<?php esc_html_e( 'Permissions', 'mainwp' ); ?></label> |
| 1662 |
<div class="ten wide column"> |
| 1663 |
<div class="mainwp-rest-api-permission-chips" data-init-value="<?php echo esc_attr( $init_pers ); ?>" data-api-version="v1"> |
| 1664 |
<input type="hidden" name="mainwp_rest_api_key_edit_pers" class="settings-field-value-change-handler" value="" /> |
| 1665 |
<button type="button" class="ui button chip mainwp-permission-chip" data-permission="r"> |
| 1666 |
<i class="book icon"></i> |
| 1667 |
<?php esc_html_e( 'Read', 'mainwp' ); ?> |
| 1668 |
</button> |
| 1669 |
<button type="button" class="ui button chip mainwp-permission-chip" data-permission="w"> |
| 1670 |
<i class="pencil icon"></i> |
| 1671 |
<?php esc_html_e( 'Write', 'mainwp' ); ?> |
| 1672 |
</button> |
| 1673 |
<button type="button" class="ui button chip mainwp-permission-chip" data-permission="d"> |
| 1674 |
<i class="trash icon"></i> |
| 1675 |
<?php esc_html_e( 'Delete', 'mainwp' ); ?> |
| 1676 |
</button> |
| 1677 |
</div> |
| 1678 |
<div class="mainwp-permission-chips-help" style="margin-top: 8px; font-size: 12px; color: #666;"> |
| 1679 |
<?php esc_html_e( 'Choose what actions this key can perform on your Dashboard data.', 'mainwp' ); ?> |
| 1680 |
</div> |
| 1681 |
</div> |
| 1682 |
</div> |
| 1683 |
<div class="ui divider"></div> |
| 1684 |
<?php $el_id_sbm_btn_2 = 'submit'; ?> |
| 1685 |
<input type="submit" name="submit" id="<?php echo esc_attr( $el_id_sbm_btn_2 ); ?>" |
| 1686 |
class="ui green big button" value="<?php esc_attr_e( 'Save API Key', 'mainwp' ); ?>" /> |
| 1687 |
<div style="clear:both"></div> |
| 1688 |
</form> |
| 1689 |
</div> |
| 1690 |
|
| 1691 |
</div> |
| 1692 |
<?php |
| 1693 |
static::render_footer(); |
| 1694 |
} |
| 1695 |
|
| 1696 |
/** |
| 1697 |
* Method check_rest_api_enabled(). |
| 1698 |
* |
| 1699 |
* @param bool $check_logged_in check for logged in user or not. |
| 1700 |
* |
| 1701 |
* @return bool check result. |
| 1702 |
*/ |
| 1703 |
public static function check_rest_api_enabled( $check_logged_in = false ) { // phpcs:ignore -- NOSONAR - complex. |
| 1704 |
$cookies = array(); |
| 1705 |
if ( $check_logged_in && is_user_logged_in() && defined( 'LOGGED_IN_COOKIE' ) ) { |
| 1706 |
$cookies = array(); |
| 1707 |
$auth_cookies = wp_parse_auth_cookie( $_COOKIE[ LOGGED_IN_COOKIE ], 'logged_in' ); // phpcs:ignore -- ok. |
| 1708 |
if ( is_array( $auth_cookies ) ) { |
| 1709 |
foreach ( $auth_cookies as $name => $value ) { |
| 1710 |
$cookies[] = new \WP_Http_Cookie( |
| 1711 |
array( |
| 1712 |
'name' => $name, |
| 1713 |
'value' => $value, |
| 1714 |
) |
| 1715 |
); |
| 1716 |
} |
| 1717 |
} |
| 1718 |
} |
| 1719 |
|
| 1720 |
$args = array( |
| 1721 |
'method' => 'GET', |
| 1722 |
'timeout' => 45, |
| 1723 |
'headers' => array( |
| 1724 |
'content-type' => 'application/json', |
| 1725 |
), |
| 1726 |
'sslverify' => (bool) get_option( 'mainwp_sslVerifyCertificate', true ), |
| 1727 |
); |
| 1728 |
|
| 1729 |
if ( $check_logged_in && ! empty( $cookies ) ) { |
| 1730 |
$args['cookies'] = $cookies; |
| 1731 |
} |
| 1732 |
|
| 1733 |
$site_url = get_option( 'home' ); |
| 1734 |
$response = wp_remote_post( $site_url . '/wp-json', $args ); |
| 1735 |
$body = wp_remote_retrieve_body( $response ); |
| 1736 |
$data = is_string( $body ) ? json_decode( $body, true ) : false; |
| 1737 |
|
| 1738 |
if ( is_array( $data ) & isset( $data['routes'] ) && ! empty( $data['routes'] ) ) { |
| 1739 |
return true; |
| 1740 |
} elseif ( ! $check_logged_in ) { |
| 1741 |
return static::check_rest_api_enabled( true ); |
| 1742 |
} |
| 1743 |
return false; |
| 1744 |
} |
| 1745 |
|
| 1746 |
/** |
| 1747 |
* Method mainwp_help_content() |
| 1748 |
* |
| 1749 |
* Creates the MainWP Help Documentation List for the help component in the sidebar. |
| 1750 |
*/ |
| 1751 |
public static function mainwp_help_content() { |
| 1752 |
$allow_pages = array( 'RESTAPI', 'AddApiKeys' ); |
| 1753 |
if ( isset( $_GET['page'] ) && in_array( $_GET['page'], $allow_pages, true ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 1754 |
?> |
| 1755 |
<p><?php esc_html_e( 'If you need help with the MainWP REST API, please review following help documents', 'mainwp' ); ?> |
| 1756 |
</p> |
| 1757 |
<div class="ui list"> |
| 1758 |
<div class="item"><i class="external alternate icon"></i> <a |
| 1759 |
href="https://docs.mainwp.com/dashboard/overview/mainwp-rest-api" target="_blank">REST API</a></div> |
| 1760 |
<?php // NOSONAR -- compatible with help. ?> |
| 1761 |
<div class="item"><i class="external alternate icon"></i> <a |
| 1762 |
href="https://docs.mainwp.com/dashboard/overview/mainwp-rest-api#enable-rest-api" target="_blank">Enable |
| 1763 |
REST API</a></div> <?php // NOSONAR -- compatible with help. ?> |
| 1764 |
<div class="item"><i class="external alternate icon"></i> <a |
| 1765 |
href="https://docs.mainwp.com/dashboard/overview/mainwp-rest-api#rest-api-permissions" target="_blank">REST |
| 1766 |
API Permissions</a></div> <?php // NOSONAR -- compatible with help. ?> |
| 1767 |
<div class="item"><i class="external alternate icon"></i> <a |
| 1768 |
href="https://docs.mainwp.com/dashboard/overview/mainwp-rest-api#disable-rest-api" target="_blank">Disable |
| 1769 |
REST API</a></div> <?php // NOSONAR -- compatible with help. ?> |
| 1770 |
<div class="item"><i class="external alternate icon"></i> <a |
| 1771 |
href="https://docs.mainwp.com/dashboard/overview/mainwp-rest-api#delete-rest-api-keys" |
| 1772 |
target="_blank">Delete REST API Key</a></div> <?php // NOSONAR -- compatible with help. ?> |
| 1773 |
<?php |
| 1774 |
/** |
| 1775 |
* Action: mainwp_rest_api_help_item |
| 1776 |
* |
| 1777 |
* Fires at the bottom of the help articles list in the Help sidebar on the REST API page. |
| 1778 |
* |
| 1779 |
* Suggested HTML markup: |
| 1780 |
* |
| 1781 |
* <div class="item"><a href="Your custom URL">Your custom text</a></div> |
| 1782 |
* |
| 1783 |
* @since 4.0 |
| 1784 |
*/ |
| 1785 |
do_action( 'mainwp_rest_api_help_item' ); |
| 1786 |
?> |
| 1787 |
</div> |
| 1788 |
<?php |
| 1789 |
} |
| 1790 |
} |
| 1791 |
|
| 1792 |
/** |
| 1793 |
* Render application password table top. |
| 1794 |
* |
| 1795 |
* @param bool $has_rows Whether there are rows to display. |
| 1796 |
*/ |
| 1797 |
public static function render_application_passwords_table_top( $has_rows = true ) { |
| 1798 |
// Align with Team Control caps: create_application_passwords, delete_application_passwords. |
| 1799 |
$can_add = static::$application_passwords->can_create_application_passwords(); |
| 1800 |
$can_revoke = static::$application_passwords->can_delete_application_passwords(); |
| 1801 |
|
| 1802 |
if ( ! $can_add && ! $can_revoke ) { |
| 1803 |
return; |
| 1804 |
} |
| 1805 |
|
| 1806 |
if ( ! $has_rows ) { |
| 1807 |
return; |
| 1808 |
} |
| 1809 |
?> |
| 1810 |
<div class="mainwp-sub-header"> |
| 1811 |
<div class="ui grid"> |
| 1812 |
<div class="equal width row ui mini form"> |
| 1813 |
<div class="middle aligned column"> |
| 1814 |
<?php if ( $can_add ) : ?> |
| 1815 |
<button type="button" class="ui mini green button" |
| 1816 |
id="mainwp-create-application-password-button-top"><?php esc_html_e( 'Add Application Password', 'mainwp' ); ?></button> |
| 1817 |
<?php endif; ?> |
| 1818 |
</div> |
| 1819 |
<div class="right aligned middle aligned column"> |
| 1820 |
<?php if ( $can_revoke ) : ?> |
| 1821 |
<button class="ui mini grey basic button disabled" |
| 1822 |
id="mainwp-do-application-passwords-bulk-actions"><?php esc_html_e( 'Revoke Selected Application Passwords', 'mainwp' ); ?></button> |
| 1823 |
<?php endif; ?> |
| 1824 |
</div> |
| 1825 |
</div> |
| 1826 |
</div> |
| 1827 |
</div> |
| 1828 |
<?php |
| 1829 |
} |
| 1830 |
|
| 1831 |
/** |
| 1832 |
* Render Application Passwords page. |
| 1833 |
*/ |
| 1834 |
public static function render_application_passwords() { |
| 1835 |
// Silent check to avoid echoing permission messages on access control. |
| 1836 |
$can_access = static::$application_passwords->can_access_application_passwords(); |
| 1837 |
|
| 1838 |
if ( ! $can_access ) { |
| 1839 |
static::render_permission_denied_ui( |
| 1840 |
esc_html__( 'Application Passwords', 'mainwp' ), |
| 1841 |
esc_html__( 'You do not have permission to view Application Passwords. If you need access to this page please contact the dashboard administrator.', 'mainwp' ) |
| 1842 |
); |
| 1843 |
return; |
| 1844 |
} |
| 1845 |
|
| 1846 |
$page_title = 'Application Passwords'; |
| 1847 |
$context = static::get_app_passwords_context(); |
| 1848 |
$rows = static::get_application_password_rows( $context ); |
| 1849 |
|
| 1850 |
static::render_header( $page_title ); |
| 1851 |
static::render_application_passwords_table_top( ! empty( $rows ) ); |
| 1852 |
|
| 1853 |
$current_user_name = ( $context['current_user'] instanceof \WP_User ) ? (string) $context['user_login'] : ''; |
| 1854 |
$user_id = (int) $context['user_id']; |
| 1855 |
$show_user_col = ! empty( $context['can_view_all'] ); |
| 1856 |
?> |
| 1857 |
<div id="rest-application-passwords-settings" class="ui padded segment" |
| 1858 |
data-current-user-name="<?php echo esc_attr( $current_user_name ); ?>" |
| 1859 |
data-current-user-id="<?php echo esc_attr( $user_id ); ?>"> |
| 1860 |
<?php static::render_application_passwords_messages( $rows ); ?> |
| 1861 |
<?php static::render_application_passwords_table( $rows, (bool) $show_user_col ); ?> |
| 1862 |
<?php static::create_application_password_modal(); ?> |
| 1863 |
<?php static::success_application_password_modal(); ?> |
| 1864 |
<?php static::edit_application_password_modal(); ?> |
| 1865 |
|
| 1866 |
<script type="text/javascript"> |
| 1867 |
jQuery(function ($) { |
| 1868 |
var created_index = <?php echo $show_user_col ? 3 : 2; ?>; |
| 1869 |
|
| 1870 |
window.mainwp_app_passwords_table = $('#mainwp-application-password-table').DataTable({ |
| 1871 |
pageLength: 10, |
| 1872 |
lengthMenu: [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]], |
| 1873 |
stateSave: true, |
| 1874 |
order: [[created_index, 'desc']], |
| 1875 |
columnDefs: [{ |
| 1876 |
targets: 'no-sort', |
| 1877 |
orderable: false |
| 1878 |
}], |
| 1879 |
initComplete: function () { |
| 1880 |
$('#mainwp-application-password-table .ui.checkbox').checkbox(); |
| 1881 |
if (typeof mainwp_table_check_columns_init === 'function') { |
| 1882 |
mainwp_table_check_columns_init(); |
| 1883 |
} |
| 1884 |
}, |
| 1885 |
drawCallback: function () { |
| 1886 |
$('#mainwp-application-password-table .ui.checkbox').checkbox(); |
| 1887 |
if (typeof mainwp_table_check_columns_init === 'function') { |
| 1888 |
mainwp_table_check_columns_init(); |
| 1889 |
} |
| 1890 |
} |
| 1891 |
}); |
| 1892 |
}); |
| 1893 |
</script> |
| 1894 |
</div> |
| 1895 |
<?php |
| 1896 |
static::render_footer(); |
| 1897 |
} |
| 1898 |
|
| 1899 |
/** |
| 1900 |
* Render create application password modal. |
| 1901 |
*/ |
| 1902 |
public static function create_application_password_modal() { |
| 1903 |
?> |
| 1904 |
<div class="ui small modal" id="mainwp-create-application-password-modal"> |
| 1905 |
<i class="ui close icon"></i> |
| 1906 |
<div class="header"><?php esc_html_e( 'Add Application Password', 'mainwp' ); ?></div> |
| 1907 |
<div class="content"> |
| 1908 |
<div class="ui form"> |
| 1909 |
<div class="field"> |
| 1910 |
<label |
| 1911 |
for="mainwp-app-password-name-input"><?php esc_html_e( 'Application Password Name', 'mainwp' ); ?></label> |
| 1912 |
<input type="text" name="app_password_name" id="mainwp-app-password-name-input" |
| 1913 |
placeholder="<?php esc_attr_e( 'e.g. MCP Client', 'mainwp' ); ?>" /> |
| 1914 |
<span |
| 1915 |
class="ui small text"><?php esc_html_e( 'Enter a name to help you identify this application password.', 'mainwp' ); ?></span> |
| 1916 |
</div> |
| 1917 |
</div> |
| 1918 |
</div> |
| 1919 |
<div class="actions"> |
| 1920 |
<button class="ui green ok button" id="mainwp-create-app-password-submit"> |
| 1921 |
<?php esc_html_e( 'Create', 'mainwp' ); ?> |
| 1922 |
</button> |
| 1923 |
|
| 1924 |
</div> |
| 1925 |
</div> |
| 1926 |
<?php |
| 1927 |
} |
| 1928 |
|
| 1929 |
/** |
| 1930 |
* Render success application password modal. |
| 1931 |
*/ |
| 1932 |
public static function success_application_password_modal() { |
| 1933 |
?> |
| 1934 |
<div class="ui small modal" id="mainwp-application-password-success-modal"> |
| 1935 |
<div class="header"> |
| 1936 |
<strong id="app-pass-success-name"></strong> <?php esc_html_e( 'Application Password Created', 'mainwp' ); ?> |
| 1937 |
</div> |
| 1938 |
<div class="content"> |
| 1939 |
<div class="ui message info"> |
| 1940 |
<?php esc_html_e( 'Be sure to save this in a safe location. You will not be able to retrieve it.', 'mainwp' ); ?> |
| 1941 |
</div> |
| 1942 |
<?php esc_html_e( 'Your new password is:', 'mainwp' ); ?> |
| 1943 |
<div class="ui grid"> |
| 1944 |
<div class="thirteen wide middle aligned column"> |
| 1945 |
<div class="ui fluid input"> |
| 1946 |
<input type="text" id="app-pass-success-value" readonly="readonly" |
| 1947 |
style="font-family: monospace; font-size: 16px; letter-spacing: 2px;" /> |
| 1948 |
</div> |
| 1949 |
</div> |
| 1950 |
<div class="three wide middle aligned column"> |
| 1951 |
<button class="ui green basic fluid button copy-app-password" |
| 1952 |
data-tooltip="<?php esc_attr_e( 'Copy to clipboard', 'mainwp' ); ?>" data-position="top center" |
| 1953 |
data-inverted=""> |
| 1954 |
<i class="copy icon"></i> <?php esc_html_e( 'Copy', 'mainwp' ); ?> |
| 1955 |
</button> |
| 1956 |
</div> |
| 1957 |
</div> |
| 1958 |
</div> |
| 1959 |
<div class="actions"> |
| 1960 |
<div class="ui green ok button"><?php esc_html_e( 'Done', 'mainwp' ); ?></div> |
| 1961 |
</div> |
| 1962 |
</div> |
| 1963 |
<?php |
| 1964 |
} |
| 1965 |
|
| 1966 |
/** |
| 1967 |
* Render edit application password modal. |
| 1968 |
*/ |
| 1969 |
public static function edit_application_password_modal() { |
| 1970 |
?> |
| 1971 |
<div class="ui small modal" id="mainwp-edit-application-password-modal"> |
| 1972 |
<div class="header"><?php esc_html_e( 'Edit Application Password', 'mainwp' ); ?></div> |
| 1973 |
<div class="content"> |
| 1974 |
<div class="ui form"> |
| 1975 |
<div class="field"> |
| 1976 |
<label for="mainwp-app-password-edit-name-input"><?php esc_html_e( 'Name', 'mainwp' ); ?></label> |
| 1977 |
<input type="text" name="app_password_name_edit" id="mainwp-app-password-edit-name-input" /> |
| 1978 |
<input type="hidden" id="mainwp-app-password-edit-uuid" /> |
| 1979 |
<input type="hidden" id="mainwp-app-password-edit-user-id" /> |
| 1980 |
</div> |
| 1981 |
</div> |
| 1982 |
</div> |
| 1983 |
<div class="actions"> |
| 1984 |
<button class="ui green ok button" id="mainwp-edit-app-password-submit"> |
| 1985 |
<?php esc_html_e( 'Save', 'mainwp' ); ?> |
| 1986 |
</button> |
| 1987 |
<button class="ui cancel button"><?php esc_html_e( 'Cancel', 'mainwp' ); ?></button> |
| 1988 |
</div> |
| 1989 |
</div> |
| 1990 |
<?php |
| 1991 |
} |
| 1992 |
|
| 1993 |
/** |
| 1994 |
* AJAX handler for creating application password. |
| 1995 |
*/ |
| 1996 |
public function ajax_application_password_create() { |
| 1997 |
MainWP_Post_Handler::instance()->check_security( 'mainwp_application_password_create' ); |
| 1998 |
|
| 1999 |
if ( ! static::$application_passwords->can_create_application_passwords() ) { |
| 2000 |
wp_send_json_error( array( 'message' => __( 'You are not allowed to create application passwords.', 'mainwp' ) ) ); |
| 2001 |
} |
| 2002 |
|
| 2003 |
$name = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : ''; // phpcs:ignore -- ok. |
| 2004 |
|
| 2005 |
if ( '' === $name ) { |
| 2006 |
wp_send_json_error( array( 'message' => __( 'Application name is required.', 'mainwp' ) ) ); |
| 2007 |
} |
| 2008 |
|
| 2009 |
$user_id = get_current_user_id(); |
| 2010 |
$result = static::$application_passwords->create_new_application_password( $user_id, array( 'name' => $name ) ); |
| 2011 |
|
| 2012 |
if ( is_wp_error( $result ) ) { |
| 2013 |
wp_send_json_error( array( 'message' => $result->get_error_message() ) ); |
| 2014 |
} |
| 2015 |
|
| 2016 |
list( $password, $item ) = $result; |
| 2017 |
|
| 2018 |
// Format password with spaces for better readability. |
| 2019 |
$formatted_password = static::$application_passwords->chunk_password( $password ); |
| 2020 |
|
| 2021 |
wp_send_json_success( |
| 2022 |
array( |
| 2023 |
'password' => $formatted_password, |
| 2024 |
'item' => $item, |
| 2025 |
) |
| 2026 |
); |
| 2027 |
} |
| 2028 |
|
| 2029 |
/** |
| 2030 |
* AJAX handler for deleting application password. |
| 2031 |
*/ |
| 2032 |
public function ajax_application_password_delete() { |
| 2033 |
MainWP_Post_Handler::instance()->check_security( 'mainwp_application_password_delete' ); |
| 2034 |
|
| 2035 |
if ( ! static::$application_passwords->can_delete_application_passwords() ) { |
| 2036 |
wp_send_json_error( array( 'message' => __( 'You are not allowed to revoke application passwords.', 'mainwp' ) ) ); // NOSONAR. |
| 2037 |
} |
| 2038 |
|
| 2039 |
$uuid = isset( $_POST['uuid'] ) ? sanitize_text_field( wp_unslash( $_POST['uuid'] ) ) : ''; // phpcs:ignore -- ok. |
| 2040 |
$user_id = isset( $_POST['user_id'] ) ? (int) wp_unslash( $_POST['user_id'] ) : 0; // phpcs:ignore -- ok. |
| 2041 |
|
| 2042 |
if ( '' === $uuid ) { |
| 2043 |
wp_send_json_error( array( 'message' => __( 'UUID is required.', 'mainwp' ) ) ); |
| 2044 |
} |
| 2045 |
|
| 2046 |
$current_id = get_current_user_id(); |
| 2047 |
// Only allow targeting others if can manage or can view all. |
| 2048 |
$can_target_others = static::$application_passwords->can_manage_application_passwords() || static::$application_passwords->can_view_all_application_passwords(); |
| 2049 |
$target_user = ( $user_id > 0 && $can_target_others ) ? $user_id : $current_id; |
| 2050 |
|
| 2051 |
$result = static::$application_passwords->delete_application_password( $target_user, $uuid ); |
| 2052 |
|
| 2053 |
if ( is_wp_error( $result ) ) { |
| 2054 |
wp_send_json_error( array( 'message' => $result->get_error_message() ) ); |
| 2055 |
} |
| 2056 |
|
| 2057 |
wp_send_json_success( array( 'deleted' => true ) ); |
| 2058 |
} |
| 2059 |
|
| 2060 |
/** |
| 2061 |
* AJAX handler for deleting multiple application passwords. |
| 2062 |
*/ |
| 2063 |
public function ajax_application_password_delete_multiple() { // phpcs:ignore -- NOSONAR. |
| 2064 |
MainWP_Post_Handler::instance()->check_security( 'mainwp_application_password_delete_multiple' ); |
| 2065 |
// Must have delete capability to delete own passwords. |
| 2066 |
$can_delete_self = static::$application_passwords->can_delete_application_passwords(); |
| 2067 |
if ( ! $can_delete_self ) { |
| 2068 |
wp_send_json_error( array( 'message' => __( 'You are not allowed to revoke application passwords.', 'mainwp' ) ) ); |
| 2069 |
} |
| 2070 |
|
| 2071 |
// Only allow targeting others if can manage or can view all. |
| 2072 |
$can_target_others = static::$application_passwords->can_manage_application_passwords() || static::$application_passwords->can_view_all_application_passwords(); |
| 2073 |
|
| 2074 |
// phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 2075 |
$items = isset( $_POST['items'] ) && is_array( $_POST['items'] ) ? wp_unslash( $_POST['items'] ) : array(); |
| 2076 |
$uuids = isset( $_POST['uuids'] ) && is_array( $_POST['uuids'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['uuids'] ) ) : array(); |
| 2077 |
// phpcs:enable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 2078 |
|
| 2079 |
$current_id = get_current_user_id(); |
| 2080 |
$deleted = 0; |
| 2081 |
$errors = array(); |
| 2082 |
|
| 2083 |
if ( is_array( $items ) && ! empty( $items ) ) { |
| 2084 |
foreach ( (array) $items as $it ) { |
| 2085 |
$uuid = isset( $it['uuid'] ) ? sanitize_text_field( $it['uuid'] ) : ''; |
| 2086 |
$user_id = isset( $it['user_id'] ) ? (int) $it['user_id'] : 0; |
| 2087 |
|
| 2088 |
if ( '' === $uuid ) { |
| 2089 |
continue; |
| 2090 |
} |
| 2091 |
|
| 2092 |
$target_user = ( $user_id > 0 && $can_target_others ) ? $user_id : $current_id; |
| 2093 |
$result = static::$application_passwords->delete_application_password( $target_user, $uuid ); |
| 2094 |
|
| 2095 |
if ( is_wp_error( $result ) ) { |
| 2096 |
$errors[] = $result->get_error_message(); |
| 2097 |
} else { |
| 2098 |
++$deleted; |
| 2099 |
} |
| 2100 |
} |
| 2101 |
} else { |
| 2102 |
$uuids = is_array( $uuids ) ? array_map( 'sanitize_text_field', $uuids ) : array(); |
| 2103 |
if ( empty( $uuids ) ) { |
| 2104 |
wp_send_json_error( array( 'message' => __( 'No passwords selected.', 'mainwp' ) ) ); |
| 2105 |
} |
| 2106 |
|
| 2107 |
foreach ( $uuids as $uuid ) { |
| 2108 |
$result = static::$application_passwords->delete_application_password( $current_id, $uuid ); |
| 2109 |
|
| 2110 |
if ( is_wp_error( $result ) ) { |
| 2111 |
$errors[] = $result->get_error_message(); |
| 2112 |
} else { |
| 2113 |
++$deleted; |
| 2114 |
} |
| 2115 |
} |
| 2116 |
} |
| 2117 |
|
| 2118 |
if ( ! empty( $errors ) ) { |
| 2119 |
wp_send_json_error( array( 'message' => implode( ', ', $errors ) ) ); |
| 2120 |
} |
| 2121 |
|
| 2122 |
wp_send_json_success( array( 'deleted' => $deleted ) ); |
| 2123 |
} |
| 2124 |
|
| 2125 |
/** |
| 2126 |
* AJAX handler for deleting all application passwords. |
| 2127 |
*/ |
| 2128 |
public function ajax_application_password_delete_all() { |
| 2129 |
MainWP_Post_Handler::instance()->check_security( 'mainwp_application_password_delete_all' ); |
| 2130 |
|
| 2131 |
if ( ! static::$application_passwords->can_delete_application_passwords() ) { |
| 2132 |
wp_send_json_error( array( 'message' => __( 'You are not allowed to revoke application passwords.', 'mainwp' ) ) ); |
| 2133 |
} |
| 2134 |
|
| 2135 |
$user_id = get_current_user_id(); |
| 2136 |
$result = static::$application_passwords->delete_all_application_passwords( $user_id ); |
| 2137 |
|
| 2138 |
if ( is_wp_error( $result ) ) { |
| 2139 |
wp_send_json_error( array( 'message' => $result->get_error_message() ) ); |
| 2140 |
} |
| 2141 |
|
| 2142 |
wp_send_json_success( array( 'deleted' => $result ) ); |
| 2143 |
} |
| 2144 |
|
| 2145 |
/** |
| 2146 |
* AJAX handler for updating (renaming) an application password. |
| 2147 |
*/ |
| 2148 |
public function ajax_application_password_update() { // phpcs:ignore -- NOSONAR. |
| 2149 |
MainWP_Post_Handler::instance()->check_security( 'mainwp_application_password_update' ); |
| 2150 |
// Must have edit capability to edit own passwords. |
| 2151 |
$can_edit_self = static::$application_passwords->can_edit_application_passwords(); |
| 2152 |
if ( ! $can_edit_self ) { |
| 2153 |
wp_send_json_error( array( 'message' => __( 'You are not allowed to edit application passwords.', 'mainwp' ) ) ); |
| 2154 |
} |
| 2155 |
|
| 2156 |
// phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 2157 |
$uuid = isset( $_POST['uuid'] ) ? sanitize_text_field( wp_unslash( $_POST['uuid'] ) ) : ''; |
| 2158 |
$user_id = isset( $_POST['user_id'] ) ? (int) wp_unslash( $_POST['user_id'] ) : 0; // phpcs:ignore -- ok. |
| 2159 |
$name = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : ''; |
| 2160 |
|
| 2161 |
// phpcs:enable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 2162 |
|
| 2163 |
if ( '' === $uuid || '' === $name ) { |
| 2164 |
wp_send_json_error( array( 'message' => __( 'UUID and Name are required.', 'mainwp' ) ) ); |
| 2165 |
} |
| 2166 |
|
| 2167 |
$current_id = get_current_user_id(); |
| 2168 |
// Only allow targeting others if can manage or can view all. |
| 2169 |
$can_edit_others = static::$application_passwords->can_manage_application_passwords() || static::$application_passwords->can_view_all_application_passwords(); |
| 2170 |
$target_user = ( $user_id > 0 && $can_edit_others ) ? $user_id : $current_id; |
| 2171 |
$result = static::$application_passwords->update_application_password( $target_user, $uuid, array( 'name' => $name ) ); |
| 2172 |
|
| 2173 |
if ( is_wp_error( $result ) ) { |
| 2174 |
wp_send_json_error( array( 'message' => $result->get_error_message() ) ); |
| 2175 |
} |
| 2176 |
|
| 2177 |
$updated_item = static::$application_passwords->get_user_application_password( $target_user, $uuid ); |
| 2178 |
wp_send_json_success( |
| 2179 |
array( |
| 2180 |
'updated' => true, |
| 2181 |
'item' => $updated_item, |
| 2182 |
) |
| 2183 |
); |
| 2184 |
} |
| 2185 |
|
| 2186 |
/** |
| 2187 |
* Get the context for application passwords. |
| 2188 |
* |
| 2189 |
* @return array The context. |
| 2190 |
*/ |
| 2191 |
protected static function get_app_passwords_context() { |
| 2192 |
$user_id = get_current_user_id(); |
| 2193 |
$current_user = wp_get_current_user(); |
| 2194 |
$admin_email = get_option( 'admin_email' ); |
| 2195 |
$display_name = ''; |
| 2196 |
$user_login = ''; |
| 2197 |
|
| 2198 |
if ( $current_user instanceof \WP_User ) { |
| 2199 |
$display_name = ! empty( $current_user->display_name ) ? $current_user->display_name : $current_user->user_login; |
| 2200 |
$user_login = $current_user->user_login; |
| 2201 |
} |
| 2202 |
|
| 2203 |
$can_view_all = static::$application_passwords->can_view_all_application_passwords(); |
| 2204 |
|
| 2205 |
return array( |
| 2206 |
'user_id' => (int) $user_id, |
| 2207 |
'current_user' => $current_user, |
| 2208 |
'display_name' => $display_name, |
| 2209 |
'admin_email' => (string) $admin_email, |
| 2210 |
'user_login' => $user_login, |
| 2211 |
'can_view_all' => (bool) $can_view_all, |
| 2212 |
); |
| 2213 |
} |
| 2214 |
|
| 2215 |
/** |
| 2216 |
* Get the application password rows. |
| 2217 |
* |
| 2218 |
* @param array $context The context. |
| 2219 |
* |
| 2220 |
* @return array The application password rows. |
| 2221 |
*/ |
| 2222 |
protected static function get_application_password_rows( $context ) { |
| 2223 |
$can_view_all = static::$application_passwords->can_view_all_application_passwords(); |
| 2224 |
|
| 2225 |
// Only allow viewing all users' passwords when can_view_all is granted. |
| 2226 |
if ( $can_view_all ) { |
| 2227 |
return static::get_all_users_application_password_rows(); |
| 2228 |
} |
| 2229 |
|
| 2230 |
return static::get_single_user_application_password_rows( |
| 2231 |
(int) $context['user_id'], |
| 2232 |
$context['user_login'], |
| 2233 |
$context['current_user'] instanceof \WP_User ? (string) $context['display_name'] : '' |
| 2234 |
); |
| 2235 |
} |
| 2236 |
|
| 2237 |
/** |
| 2238 |
* Get all users application password rows. |
| 2239 |
* |
| 2240 |
* @return array The application password rows. |
| 2241 |
*/ |
| 2242 |
protected static function get_all_users_application_password_rows() { |
| 2243 |
$rows = array(); |
| 2244 |
$users = get_users( |
| 2245 |
array( |
| 2246 |
'fields' => array( 'ID', 'display_name', 'user_email', 'user_login' ), |
| 2247 |
) |
| 2248 |
); |
| 2249 |
|
| 2250 |
foreach ( $users as $u ) { |
| 2251 |
$pwds = static::$application_passwords->get_user_application_passwords( $u->ID ); |
| 2252 |
if ( empty( $pwds ) ) { |
| 2253 |
continue; |
| 2254 |
} |
| 2255 |
|
| 2256 |
$user_name = ! empty( $u->display_name ) ? $u->display_name : $u->user_login; |
| 2257 |
|
| 2258 |
foreach ( $pwds as $pwd_item ) { |
| 2259 |
$rows[] = static::decorate_password_row( |
| 2260 |
$pwd_item, |
| 2261 |
(int) $u->ID, |
| 2262 |
(string) $u->user_login, |
| 2263 |
(string) $user_name, |
| 2264 |
(string) $u->user_email |
| 2265 |
); |
| 2266 |
} |
| 2267 |
} |
| 2268 |
|
| 2269 |
return $rows; |
| 2270 |
} |
| 2271 |
|
| 2272 |
/** |
| 2273 |
* Get a single user application password rows. |
| 2274 |
* |
| 2275 |
* @param int $user_id The user ID. |
| 2276 |
* @param string $user_login The user login. |
| 2277 |
* @param string $display_name The display name. |
| 2278 |
* |
| 2279 |
* @return array The application password rows. |
| 2280 |
*/ |
| 2281 |
protected static function get_single_user_application_password_rows( $user_id, $user_login, $display_name ) { |
| 2282 |
$rows = array(); |
| 2283 |
$passwords = static::$application_passwords->get_user_application_passwords( $user_id ); |
| 2284 |
|
| 2285 |
foreach ( $passwords as $pwd_item ) { |
| 2286 |
$rows[] = static::decorate_password_row( |
| 2287 |
$pwd_item, |
| 2288 |
(int) $user_id, |
| 2289 |
(string) $user_login, |
| 2290 |
(string) $display_name, |
| 2291 |
'' |
| 2292 |
); |
| 2293 |
} |
| 2294 |
|
| 2295 |
return $rows; |
| 2296 |
} |
| 2297 |
|
| 2298 |
/** |
| 2299 |
* Decorate a password row. |
| 2300 |
* |
| 2301 |
* @param array $pwd_item The password item. |
| 2302 |
* @param int $user_id The user ID. |
| 2303 |
* @param string $user_login The user login. |
| 2304 |
* @param string $user_name The user name. |
| 2305 |
* @param string $user_email The user email. |
| 2306 |
* |
| 2307 |
* @return array The decorated password row. |
| 2308 |
*/ |
| 2309 |
protected static function decorate_password_row( $pwd_item, $user_id, $user_login, $user_name, $user_email ) { |
| 2310 |
$pwd_item['user_id'] = (int) $user_id; |
| 2311 |
$pwd_item['user_login'] = (string) $user_login; |
| 2312 |
$pwd_item['user_full_name'] = (string) $user_name; |
| 2313 |
|
| 2314 |
if ( '' !== $user_email ) { |
| 2315 |
$pwd_item['user_email'] = (string) $user_email; |
| 2316 |
} |
| 2317 |
|
| 2318 |
return $pwd_item; |
| 2319 |
} |
| 2320 |
|
| 2321 |
/** |
| 2322 |
* Render application passwords messages. |
| 2323 |
* |
| 2324 |
* @param array $rows The application password rows. |
| 2325 |
*/ |
| 2326 |
protected static function render_application_passwords_messages( $rows ) { |
| 2327 |
if ( empty( $rows ) ) { |
| 2328 |
if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-app-passwords-welcome-message' ) ) { |
| 2329 |
?> |
| 2330 |
<div class="ui icon message mainwp-welcome-message" style="margin-bottom:0;"> |
| 2331 |
<em data-emoji=":wave:" class="big"></em> |
| 2332 |
<div class="content"> |
| 2333 |
<div class="ui massive header"><?php esc_html_e( 'Get started with MainWP Abilities API / MCP', 'mainwp' ); ?> |
| 2334 |
</div> |
| 2335 |
<p><?php esc_html_e( 'You haven\'t created any Application Passwords. MainWP Abilities API / MCP uses WordPress Application Passwords (not the MainWP API Key).', 'mainwp' ); ?> |
| 2336 |
</p> |
| 2337 |
<p><?php esc_html_e( 'Create a new Application Password (recommended: name it after the client/tool), then use it as the credential when connecting.', 'mainwp' ); ?> |
| 2338 |
</p> |
| 2339 |
</div> |
| 2340 |
<i class="close icon mainwp-notice-dismiss" notice-id="mainwp-app-passwords-welcome-message"></i> |
| 2341 |
</div> |
| 2342 |
<?php |
| 2343 |
} |
| 2344 |
return; |
| 2345 |
} |
| 2346 |
|
| 2347 |
if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-app-passwords-info-message' ) ) { |
| 2348 |
?> |
| 2349 |
<div class="ui info message"> |
| 2350 |
<i class="close icon mainwp-notice-dismiss" notice-id="mainwp-app-passwords-info-message"></i> |
| 2351 |
<?php |
| 2352 |
/* translators: 1: Opening anchor tag for Abilities API link. 2: Closing anchor tag. */ |
| 2353 |
printf( esc_html__( '%1$sMainWP Abilities API%2$s / MCP uses WordPress Application Passwords so you can grant tool access without sharing your account password. Create a dedicated Application Password (for example "MCP Client") and revoke it whenever you no longer need it. This does not affect your regular login password.', 'mainwp' ), '<a href="' . esc_url( 'https://docs.mainwp.com/api-reference/abilities-api/overview' ) . '" target="_blank">', '</a>' ); |
| 2354 |
?> |
| 2355 |
</div> |
| 2356 |
<?php |
| 2357 |
} |
| 2358 |
} |
| 2359 |
|
| 2360 |
/** |
| 2361 |
* Render the application passwords table. |
| 2362 |
* |
| 2363 |
* @param array $rows The application password rows. |
| 2364 |
* @param bool $show_user_col Whether to show the username column. |
| 2365 |
*/ |
| 2366 |
protected static function render_application_passwords_table( $rows, $show_user_col ) { |
| 2367 |
if ( empty( $rows ) ) { |
| 2368 |
MainWP_UI::render_empty_page_placeholder( |
| 2369 |
esc_html__( 'No Application Passwords yet', 'mainwp' ), |
| 2370 |
esc_html__( 'Create your first application password to allow external applications to authenticate with MainWP.', 'mainwp' ), |
| 2371 |
'<em data-emoji=":key:" class="big"></em>' |
| 2372 |
); |
| 2373 |
if ( static::$application_passwords->can_create_application_passwords() ) { |
| 2374 |
?> |
| 2375 |
<div class="ui center aligned segment"> |
| 2376 |
<button type="button" class="ui green button" id="mainwp-create-application-password-button"><?php esc_html_e( 'Add Application Password', 'mainwp' ); ?></button> |
| 2377 |
</div> |
| 2378 |
<?php |
| 2379 |
} |
| 2380 |
return; |
| 2381 |
} |
| 2382 |
|
| 2383 |
// Align revoke (delete) permission with delete_application_passwords capability. |
| 2384 |
$can_revoke = static::$application_passwords->can_delete_application_passwords(); |
| 2385 |
$can_edit = static::$application_passwords->can_edit_application_passwords(); |
| 2386 |
?> |
| 2387 |
<div id="mainwp-message-zone-app-passwords" style="display:none;"></div> |
| 2388 |
<div class="content active application-passwords-list-table-wrapper"> |
| 2389 |
<table id="mainwp-application-password-table" class="ui unstackable single line table" |
| 2390 |
data-can-manage="<?php echo esc_attr( $can_revoke ? '1' : '0' ); ?>" |
| 2391 |
data-can-edit="<?php echo esc_attr( $can_edit ? '1' : '0' ); ?>"> |
| 2392 |
<thead> |
| 2393 |
<tr> |
| 2394 |
<th scope="col" class="no-sort collapsing check-column"> |
| 2395 |
<span class="ui checkbox"> |
| 2396 |
<input aria-label="<?php esc_attr_e( 'Select all Application Passwords', 'mainwp' ); ?>" |
| 2397 |
id="application-password-select-all-top" type="checkbox" /> |
| 2398 |
</span> |
| 2399 |
</th> |
| 2400 |
<th scope="col" class="collapsing"><?php esc_html_e( 'Name', 'mainwp' ); ?></th> |
| 2401 |
|
| 2402 |
<?php if ( $show_user_col ) : ?> |
| 2403 |
<th scope="col" class="collapsing mainwp-col-user"><?php esc_html_e( 'Username', 'mainwp' ); ?></th> |
| 2404 |
<?php endif; ?> |
| 2405 |
|
| 2406 |
<th scope="col"><?php esc_html_e( 'Created', 'mainwp' ); ?></th> |
| 2407 |
<th scope="col" class="collapsing"><?php esc_html_e( 'Last Used', 'mainwp' ); ?></th> |
| 2408 |
<th scope="col" class="collapsing"><?php esc_html_e( 'Last IP', 'mainwp' ); ?></th> |
| 2409 |
<th scope="col" class="no-sort collapsing"></th> |
| 2410 |
</tr> |
| 2411 |
</thead> |
| 2412 |
<tbody id="mainwp-application-password-table-body" class="mainwp-application-password-body-table-manage"> |
| 2413 |
<?php |
| 2414 |
foreach ( $rows as $item ) { |
| 2415 |
static::render_application_password_row( $item, (bool) $show_user_col, (bool) $can_revoke ); |
| 2416 |
} |
| 2417 |
?> |
| 2418 |
</tbody> |
| 2419 |
</table> |
| 2420 |
</div> |
| 2421 |
<?php |
| 2422 |
} |
| 2423 |
|
| 2424 |
/** |
| 2425 |
* Render a single application password row. |
| 2426 |
* |
| 2427 |
* @param array $item The application password item. |
| 2428 |
* @param bool $show_user_col Whether to show the username column. |
| 2429 |
* @param bool $can_revoke Whether the current user can revoke application passwords. |
| 2430 |
*/ |
| 2431 |
protected static function render_application_password_row( $item, $show_user_col, $can_revoke ) { |
| 2432 |
// translators: %s is the application password name. |
| 2433 |
$aria_select = esc_attr( sprintf( __( 'Select %s', 'mainwp' ), $item['name'] ) ); |
| 2434 |
// translators: %s is the application password name. |
| 2435 |
$aria_rename = esc_attr( sprintf( __( 'Rename "%s"', 'mainwp' ), $item['name'] ) ); |
| 2436 |
// translators: %s is the application password name. |
| 2437 |
$aria_revoke = esc_attr( sprintf( __( 'Revoke "%s"', 'mainwp' ), $item['name'] ) ); |
| 2438 |
?> |
| 2439 |
<tr data-uuid="<?php echo esc_attr( $item['uuid'] ); ?>" data-user-id="<?php echo esc_attr( $item['user_id'] ); ?>" |
| 2440 |
class="mainwp-application-password-row"> |
| 2441 |
<td class="check-column"> |
| 2442 |
<div class="ui checkbox"> |
| 2443 |
<input type="checkbox" <?php echo $can_revoke ? '' : 'disabled'; ?> |
| 2444 |
class="mainwp-application-password-checkbox" |
| 2445 |
aria-label="<?php echo $aria_select; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>" |
| 2446 |
value="<?php echo esc_attr( $item['uuid'] ); ?>" |
| 2447 |
data-user-id="<?php echo esc_attr( $item['user_id'] ); ?>" /> |
| 2448 |
</div> |
| 2449 |
</td> |
| 2450 |
|
| 2451 |
<td><?php echo esc_html( $item['name'] ); ?></td> |
| 2452 |
|
| 2453 |
<?php if ( $show_user_col ) : ?> |
| 2454 |
<td><?php echo esc_html( $item['user_login'] ); ?></td> |
| 2455 |
<?php endif; ?> |
| 2456 |
|
| 2457 |
<td data-order="<?php echo esc_attr( $item['created'] ); ?>"> |
| 2458 |
<?php echo esc_html( MainWP_Utility::format_timestamp( $item['created'] ) ); ?> |
| 2459 |
</td> |
| 2460 |
|
| 2461 |
<td data-order="<?php echo ! empty( $item['last_used'] ) ? esc_attr( $item['last_used'] ) : 0; ?>"> |
| 2462 |
<?php |
| 2463 |
if ( ! empty( $item['last_used'] ) ) { |
| 2464 |
echo '<span data-tooltip="' . esc_attr( MainWP_Utility::format_timestamp( $item['last_used'] ) ) . '" data-position="left center" data-inverted="">' . |
| 2465 |
esc_html( MainWP_Utility::time_elapsed_string( $item['last_used'] ) ) . |
| 2466 |
'</span>'; |
| 2467 |
} else { |
| 2468 |
echo '—'; |
| 2469 |
} |
| 2470 |
?> |
| 2471 |
</td> |
| 2472 |
|
| 2473 |
<td> |
| 2474 |
<?php |
| 2475 |
if ( ! empty( $item['last_ip'] ) ) { |
| 2476 |
echo esc_html( $item['last_ip'] ); |
| 2477 |
} else { |
| 2478 |
echo '—'; |
| 2479 |
} |
| 2480 |
?> |
| 2481 |
</td> |
| 2482 |
|
| 2483 |
<td class="right aligned"> |
| 2484 |
<?php if ( static::$application_passwords->can_edit_application_passwords() ) : ?> |
| 2485 |
<button type="button" class="ui mini basic button mainwp-edit-application-password" |
| 2486 |
data-uuid="<?php echo esc_attr( $item['uuid'] ); ?>" |
| 2487 |
data-user-id="<?php echo esc_attr( $item['user_id'] ); ?>" |
| 2488 |
data-name="<?php echo esc_attr( $item['name'] ); ?>" |
| 2489 |
aria-label="<?php echo $aria_rename; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>"> |
| 2490 |
<?php esc_html_e( 'Edit', 'mainwp' ); ?> |
| 2491 |
</button> |
| 2492 |
<?php endif; ?> |
| 2493 |
<?php if ( $can_revoke ) : ?> |
| 2494 |
<button type="button" class="ui mini button mainwp-revoke-application-password" |
| 2495 |
data-uuid="<?php echo esc_attr( $item['uuid'] ); ?>" |
| 2496 |
data-user-id="<?php echo esc_attr( $item['user_id'] ); ?>" |
| 2497 |
aria-label="<?php echo $aria_revoke; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>"> |
| 2498 |
<?php esc_html_e( 'Revoke', 'mainwp' ); ?> |
| 2499 |
</button> |
| 2500 |
<?php endif; ?> |
| 2501 |
</td> |
| 2502 |
</tr> |
| 2503 |
<?php |
| 2504 |
} |
| 2505 |
|
| 2506 |
/** |
| 2507 |
* Determine if user can view REST API. |
| 2508 |
* |
| 2509 |
* @return bool |
| 2510 |
*/ |
| 2511 |
public static function can_access_rest_api() { |
| 2512 |
if ( |
| 2513 |
static::can_view_manage_rest_api() || |
| 2514 |
static::can_create_rest_api_keys() || |
| 2515 |
static::can_delete_rest_api_keys() || |
| 2516 |
static::can_edit_rest_api_keys() |
| 2517 |
) { |
| 2518 |
return true; |
| 2519 |
} |
| 2520 |
return false; |
| 2521 |
} |
| 2522 |
|
| 2523 |
/** |
| 2524 |
* Check if the current user can view and manage REST API keys. |
| 2525 |
* |
| 2526 |
* @return bool |
| 2527 |
*/ |
| 2528 |
public static function can_view_manage_rest_api() { |
| 2529 |
return \mainwp_current_user_can( 'rest_api', 'manage_rest_api_keys' ); |
| 2530 |
} |
| 2531 |
|
| 2532 |
/** |
| 2533 |
* Check if the current user can create REST API keys. |
| 2534 |
* |
| 2535 |
* @return bool |
| 2536 |
*/ |
| 2537 |
public static function can_create_rest_api_keys() { |
| 2538 |
return \mainwp_current_user_can( 'rest_api', 'create_rest_api_keys' ); |
| 2539 |
} |
| 2540 |
|
| 2541 |
/** |
| 2542 |
* Check if the current user can delete REST API keys. |
| 2543 |
* |
| 2544 |
* @return bool |
| 2545 |
*/ |
| 2546 |
public static function can_delete_rest_api_keys() { |
| 2547 |
return \mainwp_current_user_can( 'rest_api', 'delete_rest_api_keys' ); |
| 2548 |
} |
| 2549 |
|
| 2550 |
/** |
| 2551 |
* Check if the current user can edit REST API keys. |
| 2552 |
* |
| 2553 |
* @return bool |
| 2554 |
*/ |
| 2555 |
public static function can_edit_rest_api_keys() { |
| 2556 |
return \mainwp_current_user_can( 'rest_api', 'edit_rest_api_keys' ); |
| 2557 |
} |
| 2558 |
} |
| 2559 |
|