Harden CSP by removing unsafe-inline for scripts
Refactored all inline event handlers (onclick, onchange, onsubmit) to use
addEventListener with data-action attributes and event delegation pattern.
Changes:
- views/*.php: Replaced inline handlers with data-action attributes
- views/admin/*.php: Same refactoring for all admin views
- assets/js/dashboard.js: Added event delegation for bulk/quick action modals
- assets/js/ticket.js: Added event delegation for dynamic elements
- assets/js/markdown.js: Refactored toolbar button handlers
- assets/js/keyboard-shortcuts.js: Refactored modal close button
- SecurityHeadersMiddleware.php: Enabled strict CSP with nonces
The CSP now uses script-src 'self' 'nonce-{nonce}' instead of 'unsafe-inline',
significantly improving XSS protection.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -41,7 +41,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
<div class="ascii-frame-inner">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
||||
<h2 style="margin: 0;">Scheduled Tickets</h2>
|
||||
<button onclick="showCreateModal()" class="btn">+ New Recurring Ticket</button>
|
||||
<button data-action="show-create-modal" class="btn">+ New Recurring Ticket</button>
|
||||
</div>
|
||||
|
||||
<table style="width: 100%;">
|
||||
@@ -91,11 +91,11 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<button onclick="editRecurring(<?php echo $rt['recurring_id']; ?>)" class="btn btn-small">Edit</button>
|
||||
<button onclick="toggleRecurring(<?php echo $rt['recurring_id']; ?>)" class="btn btn-small">
|
||||
<button data-action="edit-recurring" data-id="<?php echo $rt['recurring_id']; ?>" class="btn btn-small">Edit</button>
|
||||
<button data-action="toggle-recurring" data-id="<?php echo $rt['recurring_id']; ?>" class="btn btn-small">
|
||||
<?php echo $rt['is_active'] ? 'Disable' : 'Enable'; ?>
|
||||
</button>
|
||||
<button onclick="deleteRecurring(<?php echo $rt['recurring_id']; ?>)" class="btn btn-small btn-danger">Delete</button>
|
||||
<button data-action="delete-recurring" data-id="<?php echo $rt['recurring_id']; ?>" class="btn btn-small btn-danger">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
@@ -107,13 +107,13 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
</div>
|
||||
|
||||
<!-- Create/Edit Modal -->
|
||||
<div class="settings-modal" id="recurringModal" style="display: none;">
|
||||
<div class="settings-modal" id="recurringModal" style="display: none;" data-action="close-modal-backdrop">
|
||||
<div class="settings-content" style="max-width: 800px; width: 90%;">
|
||||
<div class="settings-header">
|
||||
<h3 id="modalTitle">Create Recurring Ticket</h3>
|
||||
<button class="close-settings" onclick="closeModal()">×</button>
|
||||
<button class="close-settings" data-action="close-modal">×</button>
|
||||
</div>
|
||||
<form id="recurringForm" onsubmit="saveRecurring(event)">
|
||||
<form id="recurringForm">
|
||||
<input type="hidden" id="recurring_id" name="recurring_id">
|
||||
<div class="settings-body">
|
||||
<div class="setting-row">
|
||||
@@ -126,7 +126,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
</div>
|
||||
<div class="setting-row">
|
||||
<label for="schedule_type">Schedule Type *</label>
|
||||
<select id="schedule_type" name="schedule_type" required onchange="updateScheduleOptions()">
|
||||
<select id="schedule_type" name="schedule_type" required data-action="update-schedule-options">
|
||||
<option value="daily">Daily</option>
|
||||
<option value="weekly">Weekly</option>
|
||||
<option value="monthly">Monthly</option>
|
||||
@@ -183,7 +183,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
</div>
|
||||
<div class="settings-footer">
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="closeModal()">Cancel</button>
|
||||
<button type="button" class="btn btn-secondary" data-action="close-modal">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -203,16 +203,51 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
document.getElementById('recurringModal').style.display = 'none';
|
||||
}
|
||||
|
||||
// Close modal on ESC key
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
closeModal();
|
||||
// Event delegation for data-action handlers
|
||||
document.addEventListener('click', function(event) {
|
||||
const target = event.target.closest('[data-action]');
|
||||
if (!target) return;
|
||||
|
||||
const action = target.dataset.action;
|
||||
switch (action) {
|
||||
case 'show-create-modal':
|
||||
showCreateModal();
|
||||
break;
|
||||
case 'close-modal':
|
||||
closeModal();
|
||||
break;
|
||||
case 'close-modal-backdrop':
|
||||
if (event.target === target) closeModal();
|
||||
break;
|
||||
case 'edit-recurring':
|
||||
editRecurring(target.dataset.id);
|
||||
break;
|
||||
case 'toggle-recurring':
|
||||
toggleRecurring(target.dataset.id);
|
||||
break;
|
||||
case 'delete-recurring':
|
||||
deleteRecurring(target.dataset.id);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// Close modal when clicking on backdrop (outside content)
|
||||
document.getElementById('recurringModal').addEventListener('click', (e) => {
|
||||
if (e.target.classList.contains('settings-modal')) {
|
||||
document.addEventListener('change', function(event) {
|
||||
const target = event.target.closest('[data-action]');
|
||||
if (!target) return;
|
||||
|
||||
if (target.dataset.action === 'update-schedule-options') {
|
||||
updateScheduleOptions();
|
||||
}
|
||||
});
|
||||
|
||||
// Form submit handler
|
||||
document.getElementById('recurringForm').addEventListener('submit', function(e) {
|
||||
saveRecurring(e);
|
||||
});
|
||||
|
||||
// Close modal on ESC key
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user