fix: CSRF token manquant dans les fetch() POST du board et card detail
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped

- board.html: ajout X-CSRF-Token header sur fetch /api/move et /api/issues
- card_detail.html: ajout helper getCsrf() + header sur tous les fetch POST/PATCH
- Sans ce fix, drag & drop, création issue, checklists échouent en production
This commit is contained in:
2026-07-10 08:22:42 -04:00
parent d940481a6f
commit 6b67b25d27
2 changed files with 28 additions and 5 deletions
+10 -2
View File
@@ -244,7 +244,11 @@
title: '', status: 'todo',
create() {
if (!this.title.trim()) return;
fetch(`/api/issues/${owner}/${repo}?title=${encodeURIComponent(this.title)}&labels=${this.status}`, { method: 'POST' })
const csrf = document.cookie.match(/csrf_token=([^;]+)/);
fetch(`/api/issues/${owner}/${repo}?title=${encodeURIComponent(this.title)}&labels=${this.status}`, {
method: 'POST',
headers: { 'X-CSRF-Token': csrf ? csrf[1] : '' }
})
.then(r => r.json())
.then(data => {
this.title = '';
@@ -277,7 +281,11 @@
onEnd: function(evt) {
const cardId = evt.item.dataset.cardId;
const toStatus = evt.to.dataset.status;
fetch(`/api/move?owner=${owner}&repo=${repo}&issue_id=${cardId}&column=${toStatus}`, { method: 'POST' })
const csrf = document.cookie.match(/csrf_token=([^;]+)/);
fetch(`/api/move?owner=${owner}&repo=${repo}&issue_id=${cardId}&column=${toStatus}`, {
method: 'POST',
headers: { 'X-CSRF-Token': csrf ? csrf[1] : '' }
})
.then(() => {
// ponytail: refresh current view after move
const activeTab = document.querySelector('.view-tab.active');
+18 -3
View File
@@ -99,6 +99,12 @@
</div>
<script>
// ponytail: CSRF helper
function getCsrf() {
const m = document.cookie.match(/csrf_token=([^;]+)/);
return m ? m[1] : '';
}
function cardDetail() {
return {
updateField(field, value) {
@@ -109,18 +115,27 @@
console.log('Toggle status');
},
toggleChecklistItem(id, checked) {
fetch(`/api/checklist-items/${id}?checked=${checked}`, { method: 'PATCH' });
fetch(`/api/checklist-items/${id}?checked=${checked}`, {
method: 'PATCH',
headers: { 'X-CSRF-Token': getCsrf() }
});
},
addChecklistItem(clId) {
const content = prompt('Item name:');
if (content) {
fetch(`/api/checklist-items/${owner}/${repo}/${issue_id}/${clId}?content=${encodeURIComponent(content)}`, { method: 'POST' })
fetch(`/api/checklist-items/${owner}/${repo}/${issue_id}/${clId}?content=${encodeURIComponent(content)}`, {
method: 'POST',
headers: { 'X-CSRF-Token': getCsrf() }
})
.then(() => htmx.ajax('GET', `/api/issues/${owner}/${repo}/${issue_id}?format=html`, { target: '#card-modal-content', swap: 'innerHTML' }));
}
},
addChecklist() {
const title = prompt('Checklist name:') || 'Checklist';
fetch(`/api/checklists/${owner}/${repo}/${issue_id}?title=${encodeURIComponent(title)}`, { method: 'POST' })
fetch(`/api/checklists/${owner}/${repo}/${issue_id}?title=${encodeURIComponent(title)}`, {
method: 'POST',
headers: { 'X-CSRF-Token': getCsrf() }
})
.then(() => htmx.ajax('GET', `/api/issues/${owner}/${repo}/${issue_id}?format=html`, { target: '#card-modal-content', swap: 'innerHTML' }));
},
addComment(body) {