Security enhancement: Remove frontend browser phone interface
- Updated shortcode to redirect to admin browser phone page for enhanced security - Removed frontend browser phone assets (108KB total): - assets/js/browser-phone-frontend.js (85KB) - assets/css/browser-phone-frontend.css (23KB) - Modified shortcode to show secure redirect interface with authentication checks - Added new shortcode attributes: title, button_text, target - Enhanced documentation with security improvements and new behavior - Reduced frontend attack surface by eliminating JavaScript exposure - Improved performance with minimal asset loading for shortcode pages 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -21,67 +21,44 @@ class TWP_Shortcodes {
|
||||
|
||||
/**
|
||||
* Enqueue frontend assets when shortcode is present
|
||||
* Since we now redirect to admin, only basic styling is needed
|
||||
*/
|
||||
public static function enqueue_frontend_assets() {
|
||||
global $post;
|
||||
|
||||
if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'twp_browser_phone')) {
|
||||
// Enqueue Twilio Voice SDK from unpkg CDN (same as backend)
|
||||
wp_enqueue_script(
|
||||
'twilio-voice-sdk',
|
||||
'https://unpkg.com/@twilio/voice-sdk@2.11.0/dist/twilio.min.js',
|
||||
array(),
|
||||
'2.11.0',
|
||||
false // Load in head to ensure it's available
|
||||
);
|
||||
|
||||
// Add backup SDK loading
|
||||
wp_add_inline_script('twilio-voice-sdk', "
|
||||
window.twpLoadTwilioSDK = function() {
|
||||
if (typeof Twilio === 'undefined') {
|
||||
console.warn('Primary Twilio SDK failed, attempting fallback load');
|
||||
var script = document.createElement('script');
|
||||
script.src = 'https://unpkg.com/@twilio/voice-sdk@2.11.0/dist/twilio.min.js';
|
||||
script.onload = function() { console.log('Fallback Twilio SDK loaded'); };
|
||||
script.onerror = function() { console.error('Fallback Twilio SDK failed'); };
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
};
|
||||
|
||||
// Try loading after a delay if not available
|
||||
setTimeout(window.twpLoadTwilioSDK, 2000);
|
||||
", 'after');
|
||||
|
||||
// Enqueue our browser phone script
|
||||
wp_enqueue_script(
|
||||
'twp-browser-phone-frontend',
|
||||
TWP_PLUGIN_URL . 'assets/js/browser-phone-frontend.js',
|
||||
array('jquery', 'twilio-voice-sdk'),
|
||||
TWP_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
// Enqueue mobile-friendly styles
|
||||
wp_enqueue_style(
|
||||
'twp-browser-phone-frontend',
|
||||
TWP_PLUGIN_URL . 'assets/css/browser-phone-frontend.css',
|
||||
array(),
|
||||
TWP_VERSION
|
||||
);
|
||||
|
||||
// Localize script with AJAX data
|
||||
wp_localize_script('twp-browser-phone-frontend', 'twp_frontend_ajax', array(
|
||||
'ajax_url' => admin_url('admin-ajax.php'),
|
||||
'admin_url' => admin_url(),
|
||||
'nonce' => wp_create_nonce('twp_frontend_nonce'),
|
||||
'user_id' => get_current_user_id(),
|
||||
'is_logged_in' => is_user_logged_in()
|
||||
));
|
||||
// Add basic styling for the redirect interface
|
||||
wp_add_inline_style('wp-admin', '
|
||||
.twp-browser-phone-redirect {
|
||||
padding: 20px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
background: #f9f9f9;
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.twp-browser-phone-redirect h3 {
|
||||
margin-top: 0;
|
||||
color: #333;
|
||||
}
|
||||
.twp-browser-phone-redirect p {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.twp-error {
|
||||
padding: 10px;
|
||||
border: 1px solid #dc3232;
|
||||
border-radius: 3px;
|
||||
background: #fbeaea;
|
||||
color: #dc3232;
|
||||
margin: 10px 0;
|
||||
}
|
||||
');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Browser phone shortcode handler
|
||||
* Redirects users to the admin browser phone page
|
||||
*/
|
||||
public static function browser_phone_shortcode($atts) {
|
||||
// Check if user is logged in
|
||||
@@ -97,174 +74,24 @@ class TWP_Shortcodes {
|
||||
// Parse shortcode attributes
|
||||
$atts = shortcode_atts(array(
|
||||
'title' => 'Browser Phone',
|
||||
'show_title' => 'true',
|
||||
'compact' => 'false'
|
||||
'button_text' => 'Access Browser Phone',
|
||||
'target' => '_blank'
|
||||
), $atts, 'twp_browser_phone');
|
||||
|
||||
$show_title = ($atts['show_title'] === 'true');
|
||||
$compact_mode = ($atts['compact'] === 'true');
|
||||
// Generate admin URL for browser phone page
|
||||
$admin_url = admin_url('admin.php?page=twilio-wp-browser-phone');
|
||||
$target = ($atts['target'] === '_blank') ? 'target="_blank"' : '';
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div id="twp-frontend-browser-phone" class="twp-browser-phone-container <?php echo $compact_mode ? 'compact' : ''; ?>">
|
||||
<?php if ($show_title): ?>
|
||||
<h3 class="twp-browser-phone-title"><?php echo esc_html($atts['title']); ?></h3>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Connection Status -->
|
||||
<div class="twp-connection-status">
|
||||
<span class="status-indicator offline" id="twp-status-indicator"></span>
|
||||
<span class="status-text" id="twp-status-text">Connecting...</span>
|
||||
</div>
|
||||
|
||||
<!-- Phone Number Selection -->
|
||||
<div class="twp-phone-selection">
|
||||
<label for="twp-caller-id">Caller ID:</label>
|
||||
<select id="twp-caller-id" class="twp-select">
|
||||
<option value="">Loading...</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Dial Pad -->
|
||||
<div class="twp-dialpad">
|
||||
<div class="twp-number-display">
|
||||
<input type="tel" id="twp-dial-number" placeholder="Enter number to dial" />
|
||||
<button id="twp-clear-number" class="twp-btn-clear" title="Clear">×</button>
|
||||
</div>
|
||||
|
||||
<div class="twp-dial-grid">
|
||||
<button class="twp-dial-btn" data-digit="1">1<span></span></button>
|
||||
<button class="twp-dial-btn" data-digit="2">2<span>ABC</span></button>
|
||||
<button class="twp-dial-btn" data-digit="3">3<span>DEF</span></button>
|
||||
<button class="twp-dial-btn" data-digit="4">4<span>GHI</span></button>
|
||||
<button class="twp-dial-btn" data-digit="5">5<span>JKL</span></button>
|
||||
<button class="twp-dial-btn" data-digit="6">6<span>MNO</span></button>
|
||||
<button class="twp-dial-btn" data-digit="7">7<span>PQRS</span></button>
|
||||
<button class="twp-dial-btn" data-digit="8">8<span>TUV</span></button>
|
||||
<button class="twp-dial-btn" data-digit="9">9<span>WXYZ</span></button>
|
||||
<button class="twp-dial-btn" data-digit="*">*</button>
|
||||
<button class="twp-dial-btn" data-digit="0">0<span>+</span></button>
|
||||
<button class="twp-dial-btn" data-digit="#">#</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Call Controls -->
|
||||
<div class="twp-call-controls">
|
||||
<button id="twp-call-btn" class="twp-btn twp-btn-primary">
|
||||
<span class="call-icon">📞</span>
|
||||
<span class="call-text">Call</span>
|
||||
</button>
|
||||
<button id="twp-hangup-btn" class="twp-btn twp-btn-danger" style="display: none;">
|
||||
<span class="hangup-icon">📞</span>
|
||||
<span class="hangup-text">Hang Up</span>
|
||||
</button>
|
||||
<button id="twp-resume-btn" class="twp-btn twp-btn-warning" style="display: none;">
|
||||
<span class="resume-icon">▶️</span>
|
||||
<span class="resume-text">Resume Call</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Call Info -->
|
||||
<div class="twp-call-info" id="twp-call-info" style="display: none;">
|
||||
<div class="call-timer">
|
||||
<span class="timer-label">Call Duration:</span>
|
||||
<span class="timer-value" id="twp-call-timer">00:00</span>
|
||||
</div>
|
||||
<div class="call-status">
|
||||
<span id="twp-call-status">Connecting...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Call Control Panel (shown during active calls) -->
|
||||
<div class="twp-call-controls-panel" id="twp-call-controls-panel" style="display: none;">
|
||||
<div class="call-control-buttons">
|
||||
<button id="twp-hold-btn" class="twp-btn twp-btn-control" title="Put call on hold">
|
||||
Hold
|
||||
</button>
|
||||
<button id="twp-transfer-btn" class="twp-btn twp-btn-control" title="Transfer to another agent">
|
||||
Transfer
|
||||
</button>
|
||||
<button id="twp-requeue-btn" class="twp-btn twp-btn-control" title="Put call back in queue">
|
||||
Requeue
|
||||
</button>
|
||||
<button id="twp-record-btn" class="twp-btn twp-btn-control" title="Start/stop recording">
|
||||
Record
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Queue Management Section -->
|
||||
<div class="twp-queue-section" id="twp-queue-section">
|
||||
<h4>Your Queues</h4>
|
||||
<div class="twp-queue-list" id="twp-queue-list">
|
||||
<div class="queue-loading">Loading queues...</div>
|
||||
</div>
|
||||
|
||||
<!-- Queue Actions (Always Visible) -->
|
||||
<div class="queue-global-actions" id="twp-queue-global-actions" style="display: none;">
|
||||
<div class="global-queue-actions">
|
||||
<button id="twp-refresh-queues" class="twp-btn twp-btn-secondary">
|
||||
Refresh
|
||||
</button>
|
||||
<button id="twp-alert-toggle" class="twp-btn twp-btn-secondary alert-off">
|
||||
🔕 Alerts OFF
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Queue Controls (Only When Call Selected) -->
|
||||
<div class="twp-queue-controls" id="twp-queue-controls" style="display: none;">
|
||||
<div class="selected-queue-info">
|
||||
<h5 id="selected-queue-name">No queue selected</h5>
|
||||
<div class="queue-stats">
|
||||
<span class="waiting-count">Waiting: <span id="twp-waiting-count">0</span></span>
|
||||
<span class="queue-size">Max: <span id="twp-queue-max-size">-</span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="queue-actions">
|
||||
<button id="twp-accept-queue-call" class="twp-btn twp-btn-success">
|
||||
Accept Next Call
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Voicemail Section -->
|
||||
<div class="twp-voicemail-section" id="twp-voicemail-section">
|
||||
<div class="voicemail-header" id="twp-voicemail-header">
|
||||
<h4>Recent Voicemails</h4>
|
||||
<div class="voicemail-summary">
|
||||
<span class="summary-stats">
|
||||
Total: <span id="twp-total-voicemails">0</span> |
|
||||
Today: <span id="twp-today-voicemails">0</span>
|
||||
</span>
|
||||
<button class="voicemail-toggle" id="twp-voicemail-toggle">
|
||||
<span class="toggle-icon">▼</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="voicemail-content" id="twp-voicemail-content" style="display: none;">
|
||||
<div class="twp-voicemail-list" id="twp-voicemail-list">
|
||||
<div class="voicemail-loading">Loading voicemails...</div>
|
||||
</div>
|
||||
|
||||
<div class="voicemail-actions">
|
||||
<button id="twp-refresh-voicemails" class="twp-btn twp-btn-secondary">
|
||||
Refresh
|
||||
</button>
|
||||
<button id="twp-view-all-voicemails" class="twp-btn twp-btn-secondary">
|
||||
View All
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Audio elements for incoming calls handled by browser -->
|
||||
<audio id="twp-ringtone" style="display: none;"></audio>
|
||||
|
||||
<!-- Error/Success Messages -->
|
||||
<div class="twp-messages" id="twp-messages"></div>
|
||||
<div class="twp-browser-phone-redirect">
|
||||
<h3><?php echo esc_html($atts['title']); ?></h3>
|
||||
<p>The browser phone interface has been moved to the WordPress admin area for enhanced security and functionality.</p>
|
||||
<p>
|
||||
<a href="<?php echo esc_url($admin_url); ?>" <?php echo $target; ?> class="button button-primary">
|
||||
<?php echo esc_html($atts['button_text']); ?>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
|
Reference in New Issue
Block a user