diff --git a/src/components/Autherization/Authe.vue b/src/components/Autherization/Authe.vue index 5e19cbc..dd137a1 100644 --- a/src/components/Autherization/Authe.vue +++ b/src/components/Autherization/Authe.vue @@ -1,6 +1,7 @@ diff --git a/src/components/Istochnik_section/Istochnik.vue b/src/components/Istochnik_section/Istochnik.vue index f57f971..0541931 100644 --- a/src/components/Istochnik_section/Istochnik.vue +++ b/src/components/Istochnik_section/Istochnik.vue @@ -21,12 +21,16 @@ v-model="searchQuery" type="text" placeholder="Поиск..." + id="source-search" + name="source_search" class="w-full h-12 dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 pl-11" /> diff --git a/src/components/Istochnik_section/Istochnik_one_kard.vue b/src/components/Istochnik_section/Istochnik_one_kard.vue index a0bf320..1bf3a94 100644 --- a/src/components/Istochnik_section/Istochnik_one_kard.vue +++ b/src/components/Istochnik_section/Istochnik_one_kard.vue @@ -8,6 +8,8 @@ :value="props.source.url" type="text" placeholder="URL источника" + :id="'source-url-' + props.source.url" + :name="'source_url_' + props.source.url" readonly class="flex-1 sm:mr-1 h-12 dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 min-w-0" /> @@ -15,6 +17,8 @@ :value="props.source.promt" type="text" placeholder="Промт" + :id="'source-promt-' + props.source.url" + :name="'source_promt_' + props.source.url" readonly class="h-12 dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 w-1/3 sm:max-w-20" /> diff --git a/src/components/News_section/General_section.vue b/src/components/News_section/General_section.vue index 69083c4..14aa1b9 100644 --- a/src/components/News_section/General_section.vue +++ b/src/components/News_section/General_section.vue @@ -20,12 +20,16 @@ v-model="searchQuery" type="text" placeholder="Поиск..." + id="news-search" + name="news_search" class="dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 pl-11" /> diff --git a/src/services/api.js b/src/services/api.js index e849820..b0cbb02 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -1,20 +1,50 @@ import axios from 'axios' +import { getAuthToken, logout } from '@/utils/auth.js' const API_BASE_8001 = 'https://allowlgroup.ru/api/8001' const API_BASE_8002 = 'https://allowlgroup.ru/api/8002' const API_BASE_8004 = 'https://allowlgroup.ru/api/8004' +// Настройка с withCredentials для работы с cookie +// Настройка без withCredentials для теста +const commonConfig = { + headers: { 'Content-Type': 'application/json' }, + withCredentials: true, // Важно для отправки cookie + // withCredentials: true, # Временно отключено для теста +} + export const api8001 = axios.create({ baseURL: API_BASE_8001, - headers: { 'Content-Type': 'application/json' }, + ...commonConfig, }) export const api8002 = axios.create({ baseURL: API_BASE_8002, - headers: { 'Content-Type': 'application/json' }, + ...commonConfig, }) export const api8004 = axios.create({ baseURL: API_BASE_8004, - headers: { 'Content-Type': 'application/json' }, + ...commonConfig, }) + +// Добавляем токен из cookie в заголовки для защищённых запросов +api8004.interceptors.request.use((config) => { + const token = getAuthToken() + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config +}) + +// Обработка ошибок 401 - автоматический выход +api8004.interceptors.response.use( + (response) => response, + (error) => { + if (error.response?.status === 401) { + logout() + window.location.reload() + } + return Promise.reject(error) + } +) diff --git a/src/services/authService.js b/src/services/authService.js index 190a138..db6cadc 100644 --- a/src/services/authService.js +++ b/src/services/authService.js @@ -1,6 +1,27 @@ import { api8004 } from './api.js' +import { setAuthToken, setUsername, getAuthToken, getUsername } from '@/utils/auth.js' export async function login(username, password) { const { data } = await api8004.post('/login', { username, password }) + + // Бэкенд сам устанавливает cookie, нам нужно только убедиться что токен сохранён + if (data.message === 'Login successful' && data.token) { + setAuthToken(data.token) + setUsername(username) + } + return data } + +// Проверяем авторизацию по наличию cookie (без лишнего запроса) +export async function checkAuth() { + const token = getAuthToken() + if (!token) { + return { authenticated: false } + } + + // Просто проверяем наличие токена и возвращаем username + return { authenticated: true, user: { username: getUsername() } } +} + + diff --git a/src/utils/auth.js b/src/utils/auth.js new file mode 100644 index 0000000..8597407 --- /dev/null +++ b/src/utils/auth.js @@ -0,0 +1,101 @@ +/** + * Утилиты для работы с cookie + */ + +const TOKEN_COOKIE_NAME = 'auth_token' +const USERNAME_COOKIE_NAME = 'username' + +/** + * Устанавливает cookie + * @param {string} name - имя cookie + * @param {string} value - значение cookie + * @param {number} days - срок хранения в днях + */ +function setCookie(name, value, days = 30) { + const date = new Date() + date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000) + const expires = `expires=${date.toUTCString()}` + document.cookie = `${name}=${encodeURIComponent(value)};${expires};path=/;SameSite=Lax` +} + +/** + * Получает cookie по имени + * @param {string} name - имя cookie + * @returns {string|null} значение cookie или null + */ +function getCookie(name) { + const nameEQ = `${name}=` + const ca = document.cookie.split(';') + for (let i = 0; i < ca.length; i++) { + let c = ca[i] + while (c.charAt(0) === ' ') c = c.substring(1) + if (c.indexOf(nameEQ) === 0) { + return decodeURIComponent(c.substring(nameEQ.length, c.length)) + } + } + return null +} + +/** + * Удаляет cookie + * @param {string} name - имя cookie + */ +function removeCookie(name) { + document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/` +} + +/** + * Сохраняет токен авторизации (для совместимости) + * @param {string} token - токен + */ +export function setAuthToken(token) { + setCookie(TOKEN_COOKIE_NAME, token, 30) +} + +/** + * Сохраняет имя пользователя + * @param {string} username - имя пользователя + */ +export function setUsername(username) { + setCookie(USERNAME_COOKIE_NAME, username, 30) +} + +/** + * Получает токен авторизации + * @returns {string|null} + */ +export function getAuthToken() { + return getCookie(TOKEN_COOKIE_NAME) +} + +/** + * Получает имя пользователя + * @returns {string|null} + */ +export function getUsername() { + return getCookie(USERNAME_COOKIE_NAME) +} + +/** + * Проверяет, авторизован ли пользователь + * @returns {boolean} + */ +export function isAuthenticated() { + return getAuthToken() !== null +} + +/** + * Выполняет выход из системы + */ +export function logout() { + removeCookie(TOKEN_COOKIE_NAME) + removeCookie(USERNAME_COOKIE_NAME) +} + +/** + * Очищает все данные авторизации + */ +export function clearAuthData() { + logout() +} +