Skip to content

Commit 9af14ab

Browse files
bpamiriclaude
andcommitted
fix: add CSRF tokens to HTMX endpoints and fetch calls (wd-cz1)
- Add global htmx:configRequest listener to auto-inject CSRF token on non-GET requests - Add authenticityToken to bookmark.js and reading-tracker.js fetch POST calls - Add CSRF tokens to blog show.cfm hx-post elements Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9978364 commit 9af14ab

File tree

5 files changed

+43
-7
lines changed

5 files changed

+43
-7
lines changed

app/views/web/BlogController/show.cfm

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,15 @@
296296
if (rect.top <= window.innerHeight - 50) {
297297
completed = true;
298298
const blogId = document.querySelector('[data-blog-id]').getAttribute('data-blog-id');
299+
var csrfToken = document.querySelector('meta[name="csrf-token"]');
300+
var tokenVal = csrfToken ? csrfToken.getAttribute('content') : '';
299301
fetch('/reading-history/complete', {
300302
method: 'POST',
301-
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
302-
body: 'blogId=' + blogId
303+
headers: {
304+
'Content-Type': 'application/x-www-form-urlencoded',
305+
'X-CSRF-TOKEN': tokenVal
306+
},
307+
body: 'blogId=' + blogId + '&authenticityToken=' + encodeURIComponent(tokenVal)
303308
});
304309
}
305310
}

public/javascripts/adminglobal.js

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/javascripts/bookmark.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
// Bookmark toggle
22
function toggleBookmark(blogId, button) {
3+
var token = document.querySelector('meta[name="csrf-token"]');
4+
var tokenValue = token ? token.getAttribute('content') : '';
35
fetch('/bookmark/toggle', {
46
method: 'POST',
5-
headers: {'Content-Type': 'application/json'},
7+
headers: {
8+
'Content-Type': 'application/json',
9+
'X-CSRF-TOKEN': tokenValue
10+
},
611
body: JSON.stringify({blogId: blogId})
712
})
813
.then(response => response.json())
914
.then(data => {
1015
if (data.bookmarked) {
11-
button.innerHTML = ' Bookmarked';
16+
button.textContent = '\u2605 Bookmarked';
1217
button.classList.add('bookmarked');
1318
} else {
14-
button.innerHTML = ' Bookmark';
19+
button.textContent = '\u2606 Bookmark';
1520
button.classList.remove('bookmarked');
1621
}
1722
});

public/javascripts/global.js

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/javascripts/reading-tracker.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ class ReadingTracker {
33
constructor(blogId) {
44
this.blogId = blogId;
55
this.trackingInterval = null;
6+
var tokenEl = document.querySelector('meta[name="csrf-token"]');
7+
this.csrfToken = tokenEl ? tokenEl.getAttribute('content') : '';
68
this.init();
79
}
810

@@ -26,15 +28,21 @@ class ReadingTracker {
2628
trackRead() {
2729
fetch('/reading-history/track', {
2830
method: 'POST',
29-
headers: {'Content-Type': 'application/json'},
31+
headers: {
32+
'Content-Type': 'application/json',
33+
'X-CSRF-TOKEN': this.csrfToken
34+
},
3035
body: JSON.stringify({blogId: this.blogId})
3136
});
3237
}
3338

3439
markComplete() {
3540
fetch('/reading-history/complete', {
3641
method: 'POST',
37-
headers: {'Content-Type': 'application/json'},
42+
headers: {
43+
'Content-Type': 'application/json',
44+
'X-CSRF-TOKEN': this.csrfToken
45+
},
3846
body: JSON.stringify({blogId: this.blogId})
3947
});
4048
clearInterval(this.trackingInterval);

0 commit comments

Comments
 (0)