diff --git a/public/js/api.js b/public/js/api.js index 1cfce87..36cdbc4 100644 --- a/public/js/api.js +++ b/public/js/api.js @@ -42,32 +42,13 @@ const Store = { async function api(path, opts = {}) { opts.headers = opts.headers || {}; - // для GET используем cookie (без CORS preflight), для мутаций — Authorization - const isGet = !opts.method || opts.method === 'GET' || opts.method === 'HEAD'; - if (Store.access && !opts.headers.Authorization && !isGet) { - opts.headers.Authorization = `Bearer ${Store.access}`; - } + // НЕ шлём Authorization — используем HttpOnly cookie (без CORS preflight) + // Middleware читает cookie buhapp_at if (opts.body && typeof opts.body === 'object' && !(opts.body instanceof FormData)) { opts.headers['Content-Type'] = 'application/json'; opts.body = JSON.stringify(opts.body); } let r = await fetch(API_BASE + path, { ...opts, credentials: 'include' }); - if (r.status === 401 && Store.refresh) { - // refresh - const r2 = await fetch(API_BASE + '/api/v1/auth/refresh', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ Refresh: Store.refresh }), - }); - if (r2.ok) { - const tokens = await r2.json(); - Store.save(tokens); - opts.headers.Authorization = `Bearer ${Store.access}`; - r = await fetch(API_BASE + path, opts); - } else { - Store.clear(); - } - } const text = await r.text(); let data = null; try { data = text ? JSON.parse(text) : null; } catch { data = text; } diff --git a/public/js/views/profile.js b/public/js/views/profile.js index 64cb039..f320591 100644 --- a/public/js/views/profile.js +++ b/public/js/views/profile.js @@ -95,6 +95,9 @@ const ProfileView = { }, async save() { + const btn = document.getElementById('p-save'); + const orig = btn ? btn.textContent : null; + if (btn) { btn.disabled = true; btn.textContent = '⏳ Сохраняю…'; } try { await API.Auth.updateMe({ name: document.getElementById('p-name').value.trim(), @@ -107,10 +110,14 @@ const ProfileView = { activities: [...this.activities], purposes: [...this.purposes], }); - TG_APP.haptic('notification'); - App.toast('Сохранено ✓'); + try { TG_APP.haptic('notification'); } catch {} + App.toast('✓ Сохранено'); + if (btn) { btn.textContent = '✓ Сохранено'; setTimeout(() => { btn.textContent = orig || 'Сохранить'; btn.disabled = false; }, 1500); } } catch (e) { - TG_APP.showAlert('Ошибка: ' + e.message); + console.error('save profile:', e); + App.toast('⚠️ ' + e.message); + TG_APP.showAlert('Ошибка сохранения: ' + e.message); + if (btn) { btn.disabled = false; btn.textContent = orig || 'Сохранить'; } } }, };