fix: CSRF token dans toutes les requêtes admin (adminFetch)
Tous les appels /api/admin/* passent maintenant par adminFetch() qui ajoute X-CSRF-Token depuis le cookie csrf_token
This commit is contained in:
@@ -551,9 +551,18 @@ document.addEventListener('alpine:init', function() {
|
||||
},
|
||||
|
||||
// ── Admin ──
|
||||
getCsrfToken() {
|
||||
return document.cookie.split('; ').find(r => r.startsWith('csrf_token='))?.split('=')[1] || '';
|
||||
},
|
||||
async adminFetch(url, opts) {
|
||||
opts = opts || {};
|
||||
opts.headers = opts.headers || {};
|
||||
opts.headers['X-CSRF-Token'] = this.getCsrfToken();
|
||||
return await fetch(url, opts);
|
||||
},
|
||||
async loadAdminUsers() {
|
||||
try {
|
||||
var r = await fetch('/api/admin/users');
|
||||
var r = await this.adminFetch('/api/admin/users');
|
||||
var d = await r.json();
|
||||
this.adminUsers = d.users || [];
|
||||
} catch(e) { this.adminUsers = []; }
|
||||
@@ -562,14 +571,14 @@ document.addEventListener('alpine:init', function() {
|
||||
|
||||
async loadAdminStats() {
|
||||
try {
|
||||
var r = await fetch('/api/admin/stats');
|
||||
var r = await this.adminFetch('/api/admin/stats');
|
||||
this.adminStats = await r.json();
|
||||
} catch(e) { this.adminStats = {}; }
|
||||
},
|
||||
|
||||
async loadAdminAudit() {
|
||||
try {
|
||||
var r = await fetch('/api/admin/audit?limit=200');
|
||||
var r = await this.adminFetch('/api/admin/audit?limit=200');
|
||||
var d = await r.json();
|
||||
this.auditEntries = d.entries || [];
|
||||
} catch(e) { this.auditEntries = []; }
|
||||
@@ -579,7 +588,7 @@ document.addEventListener('alpine:init', function() {
|
||||
var u = this.newUser;
|
||||
if (!u.login || !u.password) return;
|
||||
try {
|
||||
var r = await fetch('/api/admin/users', {
|
||||
var r = await this.adminFetch('/api/admin/users', {
|
||||
method: 'POST', headers: {'Content-Type':'application/json'},
|
||||
body: JSON.stringify({login:u.login, name:u.name, email:u.email, password:u.password, is_admin:u.is_admin?1:0})
|
||||
});
|
||||
@@ -600,7 +609,7 @@ document.addEventListener('alpine:init', function() {
|
||||
var body = {name: f.name, email: f.email, is_admin: f.is_admin?1:0, is_active: f.is_active?1:0};
|
||||
if (f.password) body.password = f.password;
|
||||
try {
|
||||
var r = await fetch('/api/admin/users/' + this.editingUser.id, {
|
||||
var r = await this.adminFetch('/api/admin/users/' + this.editingUser.id, {
|
||||
method: 'PUT', headers: {'Content-Type':'application/json'},
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
@@ -614,7 +623,7 @@ document.addEventListener('alpine:init', function() {
|
||||
async adminDeleteUser(id) {
|
||||
if (!confirm('Permanently delete this user and all their data?')) return;
|
||||
try {
|
||||
await fetch('/api/admin/users/' + id, { method: 'DELETE' });
|
||||
await this.adminFetch('/api/admin/users/' + id, { method: 'DELETE' });
|
||||
await this.loadAdminUsers();
|
||||
} catch(e) {}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user