Fix CSP blocking admin panel buttons by removing inline onclick handlers
Replace onclick attributes with data-action/data-id attributes and use event delegation. CSP script-src 'self' blocks inline handlers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
797d1e0280
commit
b81874f5ba
@ -317,7 +317,7 @@ async function loadUsers() {
|
|||||||
<td>${user.games_played} (${user.games_won} wins)</td>
|
<td>${user.games_played} (${user.games_won} wins)</td>
|
||||||
<td>${formatDateShort(user.created_at)}</td>
|
<td>${formatDateShort(user.created_at)}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-small" onclick="viewUser('${user.id}')">View</button>
|
<button class="btn btn-small" data-action="view-user" data-id="${user.id}">View</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`;
|
||||||
@ -404,7 +404,7 @@ async function loadGames() {
|
|||||||
<td><span class="badge badge-${game.status === 'playing' ? 'success' : 'info'}">${game.status}</span></td>
|
<td><span class="badge badge-${game.status === 'playing' ? 'success' : 'info'}">${game.status}</span></td>
|
||||||
<td>${formatDate(game.created_at)}</td>
|
<td>${formatDate(game.created_at)}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-small btn-danger" onclick="promptEndGame('${game.game_id}')">End</button>
|
<button class="btn btn-small btn-danger" data-action="end-game" data-id="${game.game_id}">End</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`;
|
||||||
@ -454,8 +454,8 @@ async function loadInvites() {
|
|||||||
<td>${status}</td>
|
<td>${status}</td>
|
||||||
<td>
|
<td>
|
||||||
${invite.is_active && !isExpired && invite.remaining_uses > 0
|
${invite.is_active && !isExpired && invite.remaining_uses > 0
|
||||||
? `<button class="btn btn-small" onclick="copyInviteLink('${invite.code}')">Copy Link</button>
|
? `<button class="btn btn-small" data-action="copy-invite" data-code="${escapeHtml(invite.code)}">Copy Link</button>
|
||||||
<button class="btn btn-small btn-danger" onclick="promptRevokeInvite('${invite.code}')">Revoke</button>`
|
<button class="btn btn-small btn-danger" data-action="revoke-invite" data-code="${escapeHtml(invite.code)}">Revoke</button>`
|
||||||
: '-'
|
: '-'
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
@ -815,6 +815,18 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Delegated click handlers for dynamically-created buttons
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
const btn = e.target.closest('[data-action]');
|
||||||
|
if (!btn) return;
|
||||||
|
|
||||||
|
const action = btn.dataset.action;
|
||||||
|
if (action === 'view-user') viewUser(btn.dataset.id);
|
||||||
|
else if (action === 'end-game') promptEndGame(btn.dataset.id);
|
||||||
|
else if (action === 'copy-invite') copyInviteLink(btn.dataset.code);
|
||||||
|
else if (action === 'revoke-invite') promptRevokeInvite(btn.dataset.code);
|
||||||
|
});
|
||||||
|
|
||||||
// Check auth on load
|
// Check auth on load
|
||||||
checkAuth();
|
checkAuth();
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user