firebase_config = $this->get_firebase_config(); add_action('wp_ajax_acb_firebase_auth', [$this, 'handle_firebase_auth']); add_action('wp_ajax_nopriv_acb_firebase_auth', [$this, 'handle_firebase_auth']); add_action('wp_ajax_acb_save_message', [$this, 'save_message']); add_action('wp_ajax_nopriv_acb_save_message', [$this, 'save_message']); add_action('wp_ajax_acb_get_messages', [$this, 'get_messages']); add_action('wp_ajax_nopriv_acb_get_messages', [$this, 'get_messages']); add_action('wp_ajax_acb_save_firebase_config', [$this, 'save_firebase_config']); } /** * Get Firebase configuration * * @return array */ public function get_firebase_config() { $config = get_option('acb_firebase_authentication_value', ''); if (empty($config)) { return []; } $decoded_config = json_decode($config, true); // Validate JSON decode if (json_last_error() !== JSON_ERROR_NONE) { error_log('ACB Firebase Service - Invalid JSON in stored config: ' . json_last_error_msg()); return []; } return is_array($decoded_config) ? $decoded_config : []; } /** * Save Firebase configuration * * @since 1.0.0 */ public function save_firebase_config() { // Verify nonce if (!wp_verify_nonce($_POST['nonce'] ?? '', 'acb_firebase_nonce')) { wp_send_json_error('Security check failed'); } // Check user permissions if (!current_user_can('manage_options')) { wp_send_json_error('Insufficient permissions'); } // Validate POST data exists if (!isset($_POST['config']) || empty($_POST['config'])) { wp_send_json_error('Configuration data is required'); } // Sanitize and unslash config data $config = wp_unslash($_POST['config']); $config = sanitize_textarea_field($config); $config_array = json_decode($config, true); // Validate JSON decode if (json_last_error() !== JSON_ERROR_NONE) { wp_send_json_error('Invalid configuration format: ' . json_last_error_msg()); } if (!is_array($config_array)) { wp_send_json_error('Configuration must be a valid JSON object'); } // Validate required fields $required_fields = ['apiKey', 'authDomain', 'projectId']; foreach ($required_fields as $field) { if (!isset($config_array[$field]) || empty(trim($config_array[$field]))) { wp_send_json_error("Missing or empty required field: $field"); } } // Sanitize configuration values $sanitized_config = []; foreach ($config_array as $key => $value) { $sanitized_key = sanitize_key($key); $sanitized_value = sanitize_text_field($value); if (!empty($sanitized_key) && !empty($sanitized_value)) { $sanitized_config[$sanitized_key] = $sanitized_value; } } // Validate sanitized config still has required fields foreach ($required_fields as $field) { if (!isset($sanitized_config[$field]) || empty($sanitized_config[$field])) { wp_send_json_error("Invalid data for required field: $field"); } } // Save configuration $result = update_option('acb_firebase_authentication_value', wp_json_encode($sanitized_config)); if ($result) { // Update internal config $this->firebase_config = $sanitized_config; wp_send_json_success('Firebase configuration saved successfully'); } else { wp_send_json_error('Failed to save configuration'); } } /** * Handle Firebase authentication * * @since 1.0.0 */ public function handle_firebase_auth() { // Verify nonce if (!wp_verify_nonce($_POST['nonce'] ?? '', 'acb_firebase_nonce')) { wp_send_json_error('Security check failed'); } // Validate required fields exist $required_fields = ['firebase_uid', 'user_name', 'user_email']; foreach ($required_fields as $field) { if (!isset($_POST[$field]) || empty(trim($_POST[$field]))) { wp_send_json_error("Missing required field: $field"); } } // Sanitize and validate input data $firebase_uid = sanitize_text_field(wp_unslash($_POST['firebase_uid'])); $user_name = sanitize_text_field(wp_unslash($_POST['user_name'])); $user_email = sanitize_email(wp_unslash($_POST['user_email'])); $user_avatar = isset($_POST['user_avatar']) ? esc_url_raw(wp_unslash($_POST['user_avatar'])) : ''; $auth_provider = isset($_POST['auth_provider']) ? sanitize_text_field(wp_unslash($_POST['auth_provider'])) : 'firebase'; // Validate email format if (!is_email($user_email)) { wp_send_json_error('Invalid email format'); } // Validate sanitized data if (empty($firebase_uid) || empty($user_name) || empty($user_email)) { wp_send_json_error('Invalid data provided'); } $user_id = $this->create_or_update_user($firebase_uid, $user_name, $user_email, $user_avatar, $auth_provider); if ($user_id) { wp_send_json_success([ 'user_id' => absint($user_id), 'message' => 'Authentication successful' ]); } else { wp_send_json_error('Failed to authenticate user'); } } /** * Create or update user in database * * @param string $firebase_uid * @param string $user_name * @param string $user_email * @param string $user_avatar * @param string $auth_provider * @return int|false */ private function create_or_update_user($firebase_uid, $user_name, $user_email, $user_avatar, $auth_provider) { global $wpdb; $table_users = $wpdb->prefix . 'acb_users'; // Validate table exists if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_users)) !== $table_users) { error_log('ACB Firebase Service - Table does not exist: ' . $table_users); return false; } // Check if user exists $existing_user = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_users WHERE firebase_uid = %s OR user_email = %s", $firebase_uid, $user_email ) ); if ($existing_user) { // Update existing user $result = $wpdb->update( $table_users, [ 'firebase_uid' => $firebase_uid, 'user_name' => $user_name, 'user_email' => $user_email, 'user_avatar' => $user_avatar, 'auth_provider' => $auth_provider, 'last_seen' => current_time('mysql'), 'updated_at' => current_time('mysql') ], ['id' => $existing_user->id], ['%s', '%s', '%s', '%s', '%s', '%s', '%s'], ['%d'] ); return $result !== false ? $existing_user->id : false; } else { // Create new user $result = $wpdb->insert( $table_users, [ 'firebase_uid' => $firebase_uid, 'user_name' => $user_name, 'user_email' => $user_email, 'user_avatar' => $user_avatar, 'auth_provider' => $auth_provider, 'is_admin' => 0, 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql') ], ['%s', '%s', '%s', '%s', '%s', '%d', '%s', '%s'] ); return $result !== false ? $wpdb->insert_id : false; } } /** * Save message to database * * @since 1.0.0 */ public function save_message() { // Verify nonce if (!wp_verify_nonce($_POST['nonce'] ?? '', 'acb_message_nonce')) { wp_send_json_error('Security check failed'); } // Validate required fields exist $required_fields = ['user_id', 'user_name', 'message']; foreach ($required_fields as $field) { if (!isset($_POST[$field]) || empty(trim($_POST[$field]))) { wp_send_json_error("Missing required field: $field"); } } // Sanitize and validate input data $user_id = sanitize_text_field(wp_unslash($_POST['user_id'])); $user_name = sanitize_text_field(wp_unslash($_POST['user_name'])); $user_email = isset($_POST['user_email']) ? sanitize_email(wp_unslash($_POST['user_email'])) : ''; $user_avatar = isset($_POST['user_avatar']) ? esc_url_raw(wp_unslash($_POST['user_avatar'])) : ''; $message = wp_kses_post(wp_unslash($_POST['message'])); // Allow safe HTML for messages $message_type = isset($_POST['message_type']) ? sanitize_text_field(wp_unslash($_POST['message_type'])) : 'text'; $file_url = isset($_POST['file_url']) ? esc_url_raw(wp_unslash($_POST['file_url'])) : ''; // Validate email if provided if (!empty($user_email) && !is_email($user_email)) { wp_send_json_error('Invalid email format'); } // Validate sanitized data if (empty($user_id) || empty($user_name) || empty($message)) { wp_send_json_error('Invalid data provided'); } $message_id = $this->insert_message($user_id, $user_name, $user_email, $user_avatar, $message, $message_type, $file_url); if ($message_id) { wp_send_json_success([ 'message_id' => absint($message_id), 'message' => 'Message saved successfully' ]); } else { wp_send_json_error('Failed to save message'); } } /** * Insert message into database * * @param string $user_id * @param string $user_name * @param string $user_email * @param string $user_avatar * @param string $message * @param string $message_type * @param string $file_url * @return int|false */ private function insert_message($user_id, $user_name, $user_email, $user_avatar, $message, $message_type, $file_url) { global $wpdb; $table_messages = $wpdb->prefix . 'acb_messages'; // Validate table exists if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_messages)) !== $table_messages) { error_log('ACB Firebase Service - Table does not exist: ' . $table_messages); return false; } $result = $wpdb->insert( $table_messages, [ 'user_id' => $user_id, 'user_name' => $user_name, 'user_email' => $user_email, 'user_avatar' => $user_avatar, 'message' => $message, 'message_type' => $message_type, 'file_url' => $file_url, 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql') ], ['%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'] ); return $result !== false ? $wpdb->insert_id : false; } /** * Get messages from database * * @since 1.0.0 */ public function get_messages() { // Verify nonce if (!wp_verify_nonce($_POST['nonce'] ?? '', 'acb_message_nonce')) { wp_send_json_error('Security check failed'); } // Sanitize and validate pagination parameters $limit = isset($_POST['limit']) ? absint($_POST['limit']) : 50; $offset = isset($_POST['offset']) ? absint($_POST['offset']) : 0; // Set reasonable limits $limit = min($limit, 100); // Max 100 messages per request $limit = max($limit, 1); // Min 1 message per request global $wpdb; $table_messages = $wpdb->prefix . 'acb_messages'; // Validate table exists if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_messages)) !== $table_messages) { wp_send_json_error('Messages table does not exist'); } $messages = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table_messages ORDER BY created_at DESC LIMIT %d OFFSET %d", $limit, $offset ) ); if ($messages === false) { wp_send_json_error('Failed to retrieve messages'); } $formatted_messages = []; foreach ($messages as $message) { $formatted_messages[] = [ 'id' => absint($message->id), 'user_id' => esc_html($message->user_id), 'user_name' => esc_html($message->user_name), 'user_email' => esc_html($message->user_email), 'user_avatar' => esc_url($message->user_avatar), 'message' => wp_kses_post($message->message), // Allow safe HTML for display 'message_type' => esc_html($message->message_type), 'file_url' => esc_url($message->file_url), 'created_at' => esc_html($message->created_at), 'formatted_time' => esc_html(date('M d, Y > h:i A', strtotime($message->created_at))) ]; } wp_send_json_success([ 'messages' => array_reverse($formatted_messages), 'total' => count($formatted_messages) ]); } /** * Get user by Firebase UID * * @param string $firebase_uid * @return object|null */ public function get_user_by_firebase_uid($firebase_uid) { global $wpdb; $table_users = $wpdb->prefix . 'acb_users'; // Sanitize input $firebase_uid = sanitize_text_field($firebase_uid); if (empty($firebase_uid)) { return null; } // Validate table exists if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_users)) !== $table_users) { error_log('ACB Firebase Service - Table does not exist: ' . $table_users); return null; } return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_users WHERE firebase_uid = %s", $firebase_uid ) ); } /** * Update user last seen * * @param string $firebase_uid * @return bool */ public function update_user_last_seen($firebase_uid) { global $wpdb; $table_users = $wpdb->prefix . 'acb_users'; // Sanitize input $firebase_uid = sanitize_text_field($firebase_uid); if (empty($firebase_uid)) { return false; } // Validate table exists if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_users)) !== $table_users) { error_log('ACB Firebase Service - Table does not exist: ' . $table_users); return false; } $result = $wpdb->update( $table_users, ['last_seen' => current_time('mysql')], ['firebase_uid' => $firebase_uid], ['%s'], ['%s'] ); return $result !== false; } }