переделал токен

This commit is contained in:
Zuev
2026-05-27 15:19:18 +03:00
parent d2ef44471b
commit 87cd4cbdc7
28 changed files with 1227 additions and 125 deletions

View File

@@ -295,19 +295,18 @@
<script>
(() => {
const token = localStorage.getItem('token');
const teacherId = localStorage.getItem('userId');
const grid = document.getElementById('schedule-grid');
const statusLine = document.getElementById('status-line');
const weekLabel = document.getElementById('week-label');
const datePicker = document.getElementById('date-picker');
let weekStart = startOfWeek(new Date());
let refreshPromise = null;
document.getElementById('logout-link').addEventListener('click', () => {
localStorage.removeItem('token');
localStorage.removeItem('role');
localStorage.removeItem('departmentId');
localStorage.removeItem('userId');
document.getElementById('logout-link').addEventListener('click', async (event) => {
event.preventDefault();
await logout();
window.location.href = '/';
});
document.getElementById('theme-toggle-local').addEventListener('click', () => {
@@ -471,17 +470,78 @@
return Array.from({ length: 7 }, (_, index) => addDays(weekStart, index));
}
async function fetchJson(url) {
async function fetchJson(url, retryOnUnauthorized = true) {
const token = localStorage.getItem('token');
const response = await fetch(url, {
headers: token ? { Authorization: `Bearer ${token}` } : {}
headers: token ? { Authorization: `Bearer ${token}` } : {},
credentials: 'same-origin'
});
const data = await response.json().catch(() => null);
if (response.status === 401 && retryOnUnauthorized) {
const refreshed = await refreshAccessToken();
if (refreshed) {
return fetchJson(url, false);
}
clearAuthState();
window.location.href = '/';
}
if (!response.ok) {
throw new Error(data?.message || `Ошибка HTTP: ${response.status}`);
}
return data;
}
async function refreshAccessToken() {
if (refreshPromise) {
return refreshPromise;
}
refreshPromise = (async () => {
const response = await fetch('/api/auth/refresh', {
method: 'POST',
credentials: 'same-origin'
});
const data = await response.json().catch(() => null);
if (!response.ok || !data?.token) {
return false;
}
storeAuthState(data);
return true;
})().finally(() => {
refreshPromise = null;
});
return refreshPromise;
}
async function logout() {
try {
await fetch('/api/auth/logout', {
method: 'POST',
credentials: 'same-origin'
});
} catch (error) {
console.warn('Не удалось завершить серверную сессию:', error.message);
} finally {
clearAuthState();
}
}
function storeAuthState(data) {
if (data.token) localStorage.setItem('token', data.token);
if (data.role) localStorage.setItem('role', data.role);
if (data.departmentId !== undefined && data.departmentId !== null) {
localStorage.setItem('departmentId', data.departmentId);
}
if (data.userId !== undefined && data.userId !== null) {
localStorage.setItem('userId', data.userId);
}
}
function clearAuthState() {
['token', 'role', 'departmentId', 'userId'].forEach(key => localStorage.removeItem(key));
}
function showStatus(message, isError) {
statusLine.textContent = message;
statusLine.classList.toggle('error', isError);