File: /var/www/html/wp-content/plugins/uptime-monitor-plus/includes/class-ajax.php
<?php
defined('ABSPATH') || exit;
/**
* AJAX handlers for UptimeMonitor+.
*/
class UptimeMonitorPlus_Ajax {
/**
* Initialize AJAX hooks.
*/
public static function init() {
add_action( 'wp_ajax_uptimemonitorplus_login', array( __CLASS__, 'handle_login' ) );
add_action( 'wp_ajax_uptimemonitorplus_disconnect', array( __CLASS__, 'handle_disconnect' ) );
add_action( 'wp_ajax_uptimemonitorplus_get_domain', array( __CLASS__, 'handle_get_domain' ) );
add_action( 'wp_ajax_uptimemonitorplus_get_ssl', array( __CLASS__, 'handle_get_ssl' ) );
add_action( 'wp_ajax_uptimemonitorplus_get_sparklines', array( __CLASS__, 'handle_get_sparklines' ) );
add_action( 'wp_ajax_uptimemonitorplus_get_checks', array( __CLASS__, 'handle_get_checks' ) );
add_action( 'wp_ajax_uptimemonitorplus_get_analytics', array( __CLASS__, 'handle_get_analytics' ) );
add_action( 'wp_ajax_uptimemonitorplus_get_errors', array( __CLASS__, 'handle_get_errors' ) );
add_action( 'wp_ajax_uptimemonitorplus_get_incidents', array( __CLASS__, 'handle_get_incidents' ) );
add_action( 'wp_ajax_uptimemonitorplus_get_calendar', array( __CLASS__, 'handle_get_calendar' ) );
add_action( 'wp_ajax_uptimemonitorplus_update_notifications', array( __CLASS__, 'handle_update_notifications' ) );
add_action( 'wp_ajax_uptimemonitorplus_dashboard_widget', array( __CLASS__, 'handle_dashboard_widget' ) );
}
/**
* Verify nonce and capability.
*
* @return bool
*/
private static function verify_request() {
if ( ! check_ajax_referer( 'uptimemonitorplus_nonce', 'nonce', false ) ) {
wp_send_json_error( array( 'message' => 'Invalid nonce' ), 403 );
return false;
}
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( array( 'message' => 'Insufficient permissions' ), 403 );
return false;
}
return true;
}
/**
* Handle login AJAX request.
*/
public static function handle_login() {
if ( ! self::verify_request() ) {
return;
}
$email = isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : '';
$password = isset( $_POST['password'] ) ? sanitize_text_field( wp_unslash( $_POST['password'] ) ) : '';
if ( empty( $email ) || empty( $password ) ) {
wp_send_json_error( array( 'message' => 'Email and password are required' ), 400 );
return;
}
$client = new UptimeMonitorPlus_API_Client();
$result = $client->login( $email, $password );
if ( is_wp_error( $result ) ) {
$error_data = $result->get_error_data();
wp_send_json_error( array(
'message' => $result->get_error_message(),
'code' => $result->get_error_code(),
), isset( $error_data['status'] ) ? $error_data['status'] : 400 );
return;
}
if ( empty( $result['accessToken'] ) ) {
wp_send_json_error( array( 'message' => 'No access token received' ), 400 );
return;
}
// Store JWT temporarily in a transient (expires in 10 minutes)
set_transient( 'uptimemonitorplus_jwt_token', $result['accessToken'], 600 );
// Auto-register domain
$register_result = self::auto_register_domain( $result['accessToken'] );
if ( is_wp_error( $register_result ) ) {
$error_data = $register_result->get_error_data();
wp_send_json_error( array(
'message' => $register_result->get_error_message(),
'code' => $register_result->get_error_code(),
), isset( $error_data['status'] ) ? $error_data['status'] : 400 );
return;
}
// Clear JWT transient after successful registration
delete_transient( 'uptimemonitorplus_jwt_token' );
wp_send_json_success( $register_result );
}
/**
* Auto-register domain and generate API token.
*
* @param string $jwt_token JWT access token.
* @return array|WP_Error
*/
private static function auto_register_domain( $jwt_token ) {
$client = new UptimeMonitorPlus_API_Client();
$site_url = site_url();
// Get user's domains
$domains = $client->get_domains( $jwt_token );
if ( is_wp_error( $domains ) ) {
return $domains;
}
$domain_list = isset( $domains['domains'] ) ? $domains['domains'] : $domains;
$domain_id = null;
// Normalize site URL for comparison
$normalized_site = strtolower( rtrim( preg_replace( '#^https?://#', '', $site_url ), '/' ) );
// Search for existing domain
if ( is_array( $domain_list ) ) {
foreach ( $domain_list as $domain ) {
$domain_url = isset( $domain['url'] ) ? $domain['url'] : '';
$normalized_domain = strtolower( rtrim( preg_replace( '#^https?://#', '', $domain_url ), '/' ) );
if ( $normalized_domain === $normalized_site ) {
$domain_id = $domain['id'];
break;
}
}
}
// Create domain if not found
if ( ! $domain_id ) {
$create_result = $client->create_domain( $jwt_token, $site_url );
if ( is_wp_error( $create_result ) ) {
return $create_result;
}
$domain_id = isset( $create_result['id'] ) ? $create_result['id'] : null;
if ( ! $domain_id ) {
return new WP_Error( 'DOMAIN_CREATE_FAILED', 'Failed to create domain' );
}
}
// Generate API token
$token_result = $client->generate_api_token( $jwt_token, $domain_id );
if ( is_wp_error( $token_result ) ) {
return $token_result;
}
if ( empty( $token_result['token'] ) ) {
return new WP_Error( 'TOKEN_GENERATE_FAILED', 'Failed to generate API token' );
}
// Save options
update_option( 'uptimemonitorplus_api_token', sanitize_text_field( $token_result['token'] ) );
update_option( 'uptimemonitorplus_domain_id', sanitize_text_field( $domain_id ) );
return array(
'domain_id' => $domain_id,
'connected' => true,
);
}
/**
* Handle disconnect AJAX request.
*/
public static function handle_disconnect() {
if ( ! self::verify_request() ) {
return;
}
$domain_id = get_option( 'uptimemonitorplus_domain_id', '' );
if ( ! empty( $domain_id ) ) {
// Try to revoke the token via API (best-effort)
$jwt_token = get_transient( 'uptimemonitorplus_jwt_token' );
if ( $jwt_token ) {
$client = new UptimeMonitorPlus_API_Client();
$client->revoke_api_token( $jwt_token, $domain_id );
}
}
// Clear stored options
update_option( 'uptimemonitorplus_api_token', '' );
update_option( 'uptimemonitorplus_domain_id', '' );
update_option( 'uptimemonitorplus_extra_email', '' );
// Clear all transients
global $wpdb;
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s",
'_transient_uptimemonitorplus_%',
'_transient_timeout_uptimemonitorplus_%'
)
);
wp_send_json_success( array( 'disconnected' => true ) );
}
/**
* Handle get domain data AJAX request.
*/
public static function handle_get_domain() {
if ( ! self::verify_request() ) {
return;
}
$client = new UptimeMonitorPlus_API_Client();
$result = $client->get_domain();
if ( is_wp_error( $result ) ) {
self::handle_api_error( $result );
return;
}
wp_send_json_success( $result );
}
/**
* Handle get SSL data AJAX request.
*/
public static function handle_get_ssl() {
if ( ! self::verify_request() ) {
return;
}
$client = new UptimeMonitorPlus_API_Client();
$result = $client->get_ssl();
if ( is_wp_error( $result ) ) {
self::handle_api_error( $result );
return;
}
wp_send_json_success( $result );
}
/**
* Handle get sparklines AJAX request.
*/
public static function handle_get_sparklines() {
if ( ! self::verify_request() ) {
return;
}
$client = new UptimeMonitorPlus_API_Client();
$result = $client->get_sparklines();
if ( is_wp_error( $result ) ) {
self::handle_api_error( $result );
return;
}
wp_send_json_success( $result );
}
/**
* Handle get checks AJAX request.
*/
public static function handle_get_checks() {
if ( ! self::verify_request() ) {
return;
}
$params = array();
if ( isset( $_POST['cursor'] ) ) {
$params['cursor'] = sanitize_text_field( wp_unslash( $_POST['cursor'] ) );
} elseif ( isset( $_GET['cursor'] ) ) {
$params['cursor'] = sanitize_text_field( wp_unslash( $_GET['cursor'] ) );
}
if ( isset( $_POST['limit'] ) ) {
$params['limit'] = absint( $_POST['limit'] );
} elseif ( isset( $_GET['limit'] ) ) {
$params['limit'] = absint( $_GET['limit'] );
}
if ( isset( $_POST['date'] ) ) {
$params['date'] = sanitize_text_field( wp_unslash( $_POST['date'] ) );
} elseif ( isset( $_GET['date'] ) ) {
$params['date'] = sanitize_text_field( wp_unslash( $_GET['date'] ) );
}
if ( isset( $_POST['tz'] ) ) {
$params['tz'] = sanitize_text_field( wp_unslash( $_POST['tz'] ) );
} elseif ( isset( $_GET['tz'] ) ) {
$params['tz'] = sanitize_text_field( wp_unslash( $_GET['tz'] ) );
}
$client = new UptimeMonitorPlus_API_Client();
$result = $client->get_checks( $params );
if ( is_wp_error( $result ) ) {
self::handle_api_error( $result );
return;
}
wp_send_json_success( $result );
}
/**
* Handle get analytics AJAX request.
*/
public static function handle_get_analytics() {
if ( ! self::verify_request() ) {
return;
}
$range = isset( $_POST['range'] ) ? sanitize_text_field( wp_unslash( $_POST['range'] ) ) : ( isset( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '24h' );
$client = new UptimeMonitorPlus_API_Client();
$result = $client->get_analytics( $range );
if ( is_wp_error( $result ) ) {
self::handle_api_error( $result );
return;
}
wp_send_json_success( $result );
}
/**
* Handle get errors AJAX request.
*/
public static function handle_get_errors() {
if ( ! self::verify_request() ) {
return;
}
$range = isset( $_POST['range'] ) ? sanitize_text_field( wp_unslash( $_POST['range'] ) ) : ( isset( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '24h' );
$client = new UptimeMonitorPlus_API_Client();
$result = $client->get_errors( $range );
if ( is_wp_error( $result ) ) {
self::handle_api_error( $result );
return;
}
wp_send_json_success( $result );
}
/**
* Handle get incidents AJAX request.
*/
public static function handle_get_incidents() {
if ( ! self::verify_request() ) {
return;
}
$page = isset( $_POST['page'] ) ? absint( $_POST['page'] ) : ( isset( $_GET['page'] ) ? absint( $_GET['page'] ) : 1 );
$page_size = isset( $_POST['pageSize'] ) ? absint( $_POST['pageSize'] ) : ( isset( $_GET['pageSize'] ) ? absint( $_GET['pageSize'] ) : 20 );
$client = new UptimeMonitorPlus_API_Client();
$result = $client->get_incidents( $page, $page_size );
if ( is_wp_error( $result ) ) {
self::handle_api_error( $result );
return;
}
wp_send_json_success( $result );
}
/**
* Handle get calendar AJAX request.
*/
public static function handle_get_calendar() {
if ( ! self::verify_request() ) {
return;
}
$months = isset( $_POST['months'] ) ? absint( $_POST['months'] ) : ( isset( $_GET['months'] ) ? absint( $_GET['months'] ) : 3 );
$offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : ( isset( $_GET['offset'] ) ? intval( $_GET['offset'] ) : 0 );
$tz = isset( $_POST['tz'] ) ? sanitize_text_field( wp_unslash( $_POST['tz'] ) ) : ( isset( $_GET['tz'] ) ? sanitize_text_field( wp_unslash( $_GET['tz'] ) ) : 'UTC' );
$client = new UptimeMonitorPlus_API_Client();
$result = $client->get_calendar( $months, $offset, $tz );
if ( is_wp_error( $result ) ) {
self::handle_api_error( $result );
return;
}
wp_send_json_success( $result );
}
/**
* Handle update notifications AJAX request.
*/
public static function handle_update_notifications() {
if ( ! self::verify_request() ) {
return;
}
$data = array();
if ( isset( $_POST['emailNotifications'] ) ) {
$data['emailNotifications'] = rest_sanitize_boolean( wp_unslash( $_POST['emailNotifications'] ) );
}
if ( isset( $_POST['sslAlertSuppressedDays'] ) ) {
$raw = wp_unslash( $_POST['sslAlertSuppressedDays'] );
if ( is_array( $raw ) ) {
$data['sslAlertSuppressedDays'] = array_values( array_map( 'absint', $raw ) );
} else {
$data['sslAlertSuppressedDays'] = array();
}
}
if ( isset( $_POST['extraEmail'] ) ) {
$email = sanitize_email( wp_unslash( $_POST['extraEmail'] ) );
$data['extraEmail'] = ! empty( $email ) ? $email : null;
}
$client = new UptimeMonitorPlus_API_Client();
$result = $client->update_notifications( $data );
if ( is_wp_error( $result ) ) {
self::handle_api_error( $result );
return;
}
wp_send_json_success( $result );
}
/**
* Handle dashboard widget AJAX request.
*/
public static function handle_dashboard_widget() {
if ( ! self::verify_request() ) {
return;
}
$cached = get_transient( 'uptimemonitorplus_widget_data' );
if ( false !== $cached ) {
wp_send_json_success( $cached );
return;
}
$client = new UptimeMonitorPlus_API_Client();
$domain_data = $client->get_domain();
if ( is_wp_error( $domain_data ) ) {
self::handle_api_error( $domain_data );
return;
}
$widget_data = array( 'domain' => $domain_data );
// Try to get SSL data
$ssl_data = $client->get_ssl();
if ( ! is_wp_error( $ssl_data ) ) {
$widget_data['ssl'] = $ssl_data;
}
// Try to get sparkline data
$sparkline_data = $client->get_sparklines();
if ( ! is_wp_error( $sparkline_data ) ) {
$widget_data['sparkline'] = $sparkline_data;
}
// Cache for 5 minutes
set_transient( 'uptimemonitorplus_widget_data', $widget_data, 300 );
wp_send_json_success( $widget_data );
}
/**
* Handle API errors, detecting 401 for token invalidation.
*
* @param WP_Error $error The WP_Error object.
*/
private static function handle_api_error( $error ) {
$error_data = $error->get_error_data();
$status = isset( $error_data['status'] ) ? $error_data['status'] : 400;
if ( 401 === $status ) {
// Token is invalid or expired - clear stored token
update_option( 'uptimemonitorplus_api_token', '' );
update_option( 'uptimemonitorplus_domain_id', '' );
}
wp_send_json_error( array(
'message' => $error->get_error_message(),
'code' => $error->get_error_code(),
), $status );
}
}