Files
magistr/frontend/admin/js/api.js
2026-07-19 14:40:43 +03:00

160 lines
3.8 KiB
JavaScript
Executable File

import {
clearAuthState,
fetchWithAuth,
getAccessToken,
getAuthState,
logoutSession,
refreshAccessToken,
restoreSession,
storeAuthState
} from '../../auth-session.js';
export function getToken() {
return getAccessToken();
}
export function getSession() {
return getAuthState();
}
export async function initializeSession() {
return restoreSession();
}
export function isAuthenticatedAsAdmin() {
const role = getAuthState()?.role;
return getToken() && role === 'ADMIN';
}
export function isAuthenticatedAsRole(expectedRole) {
const role = getAuthState()?.role;
return getToken() && role === expectedRole;
}
export function isAuthenticatedAsAny(roles) {
const role = getAuthState()?.role;
return getToken() && roles.includes(role);
}
function getHeaders(contentType = 'application/json') {
const headers = {};
const token = getToken();
if (token) {
headers.Authorization = `Bearer ${token}`;
}
if (contentType) {
headers['Content-Type'] = contentType;
}
return headers;
}
export async function apiFetch(endpoint, method = 'GET', body = null, retryOnUnauthorized = true) {
const options = {
method,
headers: getHeaders(body ? 'application/json' : null),
credentials: 'same-origin'
};
if (body) {
options.body = JSON.stringify(body);
}
const response = await fetchWithAuth(endpoint, options);
let data;
try {
data = await response.json();
} catch (e) {
data = null;
}
if (response.status === 401 && retryOnUnauthorized) {
clearAuthState();
window.location.replace('/');
}
if (!response.ok) {
const error = new Error(data?.message || `Ошибка HTTP: ${response.status}`);
error.status = response.status;
error.data = data;
throw error;
}
return data;
}
export { clearAuthState, refreshAccessToken, storeAuthState };
const cache = new Map();
const CACHABLE_PREFIXES = [
'/api/departments',
'/api/specialties',
'/api/education-forms',
'/api/users/teachers',
'/api/equipments',
'/api/classrooms'
];
function invalidateCache(url) {
const cacheKeysToClear = [
'/api/departments',
'/api/specialties',
'/api/education-forms',
'/api/users',
'/api/teacher-requests',
'/api/department/teacher-requests',
'/api/department/teachers',
'/api/equipments',
'/api/classrooms'
];
const affectedPrefixes = new Set(cacheKeysToClear.filter(prefix => url.includes(prefix)));
if (url.includes('/api/teacher-requests')) {
affectedPrefixes.add('/api/users');
}
if (url.includes('/api/department/teachers')) {
affectedPrefixes.add('/api/users/teachers');
}
for (const prefix of affectedPrefixes) {
for (const cacheKey of cache.keys()) {
if (cacheKey.includes(prefix)) {
cache.delete(cacheKey);
}
}
}
}
export function clearCache() {
cache.clear();
}
export async function logout() {
await logoutSession();
clearCache();
}
export const api = {
get: async (url) => {
const isCachable = CACHABLE_PREFIXES.some(prefix => url.startsWith(prefix));
if (isCachable) {
if (!cache.has(url)) {
cache.set(url, await apiFetch(url, 'GET'));
}
return cache.get(url);
}
return apiFetch(url, 'GET');
},
post: async (url, body) => {
invalidateCache(url);
return apiFetch(url, 'POST', body);
},
put: async (url, body) => {
invalidateCache(url);
return apiFetch(url, 'PUT', body);
},
delete: async (url, body = null) => {
invalidateCache(url);
return apiFetch(url, 'DELETE', body);
}
};