Remove inline script from API doc, add CSP policy section
Security: - Move env switcher logic to assets/modules/api-env-switcher.js (no inline script) - Register in app.js via initApiEnvSwitcher() - Compliant with CSP script-src (no unsafe-inline needed for this page) API doc: - Add CSP policy section showing all authorized origins per directive - Table: script-src, connect-src, style-src, img-src, font-src, frame-src, form-action, object-src, worker-src - Note: inline scripts not allowed, must use nonce or external file Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -276,45 +276,64 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-brutal overflow-hidden mt-12">
|
||||
<div class="bg-gray-900 text-white px-6 py-3">
|
||||
<h2 class="text-[10px] font-black uppercase tracking-widest">Politique de securite (CSP)</h2>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<p class="font-bold text-sm text-gray-700 mb-4">E-Ticket applique une politique Content-Security-Policy stricte. Voici les origines autorisees par directive :</p>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-xs">
|
||||
<thead>
|
||||
<tr class="bg-gray-100">
|
||||
<th class="px-3 py-2 text-left font-black uppercase tracking-widest">Directive</th>
|
||||
<th class="px-3 py-2 text-left font-black uppercase tracking-widest">Origines autorisees</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="border-b border-gray-100">
|
||||
<td class="px-3 py-2 font-mono font-bold text-indigo-600">script-src</td>
|
||||
<td class="px-3 py-2 font-mono text-gray-600">'self' static.cloudflareinsights.com challenges.cloudflare.com cdn.jsdelivr.net js.stripe.com</td>
|
||||
</tr>
|
||||
<tr class="border-b border-gray-100">
|
||||
<td class="px-3 py-2 font-mono font-bold text-indigo-600">connect-src</td>
|
||||
<td class="px-3 py-2 font-mono text-gray-600">'self' cloudflareinsights.com static.cloudflareinsights.com challenges.cloudflare.com nominatim.openstreetmap.org cdn.jsdelivr.net api.stripe.com</td>
|
||||
</tr>
|
||||
<tr class="border-b border-gray-100">
|
||||
<td class="px-3 py-2 font-mono font-bold text-indigo-600">style-src</td>
|
||||
<td class="px-3 py-2 font-mono text-gray-600">'self' fonts.googleapis.com cdnjs.cloudflare.com cdn.jsdelivr.net 'unsafe-inline'</td>
|
||||
</tr>
|
||||
<tr class="border-b border-gray-100">
|
||||
<td class="px-3 py-2 font-mono font-bold text-indigo-600">img-src</td>
|
||||
<td class="px-3 py-2 font-mono text-gray-600">'self' data: *.tile.openstreetmap.org *.basemaps.cartocdn.com cdn.jsdelivr.net</td>
|
||||
</tr>
|
||||
<tr class="border-b border-gray-100">
|
||||
<td class="px-3 py-2 font-mono font-bold text-indigo-600">font-src</td>
|
||||
<td class="px-3 py-2 font-mono text-gray-600">'self' cdnjs.cloudflare.com fonts.googleapis.com fonts.gstatic.com</td>
|
||||
</tr>
|
||||
<tr class="border-b border-gray-100">
|
||||
<td class="px-3 py-2 font-mono font-bold text-indigo-600">frame-src</td>
|
||||
<td class="px-3 py-2 font-mono text-gray-600">'self' stripe.com *.stripe.com js.stripe.com cloudflare.com *.cloudflareinsights.com challenges.cloudflare.com</td>
|
||||
</tr>
|
||||
<tr class="border-b border-gray-100">
|
||||
<td class="px-3 py-2 font-mono font-bold text-indigo-600">form-action</td>
|
||||
<td class="px-3 py-2 font-mono text-gray-600">'self' auth.esy-web.dev *.stripe.com checkout.stripe.com</td>
|
||||
</tr>
|
||||
<tr class="border-b border-gray-100">
|
||||
<td class="px-3 py-2 font-mono font-bold text-indigo-600">object-src</td>
|
||||
<td class="px-3 py-2 font-mono text-gray-600">'none'</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-3 py-2 font-mono font-bold text-indigo-600">worker-src</td>
|
||||
<td class="px-3 py-2 font-mono text-gray-600">'self' blob:</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="mt-4 text-xs font-bold text-gray-400">Les scripts inline ne sont pas autorises. Tous les scripts doivent etre servis depuis une origine autorisee ou utiliser un nonce CSP.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const envs = {
|
||||
sandbox: { prefix: '/api/sandbox', baseUrl: 'https://ticket.e-cosplay.fr/api/sandbox', color: 'text-orange-400', btnBg: 'bg-orange-500', desc: 'Environnement de test. Les donnees ne sont pas modifiees.' },
|
||||
live: { prefix: '/api/live', baseUrl: 'https://ticket.e-cosplay.fr/api/live', color: 'text-green-400', btnBg: 'bg-green-600', desc: 'Environnement de production. Les donnees sont reelles.' },
|
||||
}
|
||||
|
||||
let current = 'sandbox'
|
||||
|
||||
const buttons = document.querySelectorAll('.env-btn')
|
||||
const baseUrlEl = document.getElementById('env-base-url')
|
||||
const descEl = document.getElementById('env-description')
|
||||
const prefixes = document.querySelectorAll('.api-env-prefix')
|
||||
|
||||
function switchEnv(env) {
|
||||
current = env
|
||||
const config = envs[env]
|
||||
|
||||
buttons.forEach(btn => {
|
||||
const isActive = btn.dataset.env === env
|
||||
btn.className = 'env-btn px-5 py-2 font-black uppercase text-xs tracking-widest transition-all cursor-pointer ' +
|
||||
(isActive ? config.btnBg + ' text-white' : 'bg-gray-800 text-gray-400 hover:text-white')
|
||||
})
|
||||
|
||||
baseUrlEl.textContent = config.baseUrl
|
||||
descEl.textContent = config.desc
|
||||
|
||||
prefixes.forEach(el => {
|
||||
el.textContent = config.prefix
|
||||
el.className = 'api-env-prefix ' + config.color
|
||||
})
|
||||
}
|
||||
|
||||
buttons.forEach(btn => {
|
||||
btn.addEventListener('click', () => switchEnv(btn.dataset.env))
|
||||
})
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user