From a9c146b192450121df055af4fc0dd2a509cd8bac Mon Sep 17 00:00:00 2001 From: Falknat Date: Sun, 11 Jan 2026 17:48:05 +0700 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B0=D0=B7=D0=B2=D0=B8=D1=82=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B1=D0=B5=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Создание БД 2. Создание бека 3. Пока создали класс юзера --- backend/api/user.php | 64 +++++++++ backend/app/class/enity/class_base.php | 30 ++++ backend/app/class/enity/class_user.php | 188 +++++++++++++++++++++++++ backend/app/config.php | 12 ++ backend/app/restAPI/class_restApi.php | 23 +++ backend/index.php | 18 ++- front_vue/src/api.js | 20 ++- front_vue/src/router.js | 2 +- front_vue/src/views/LoginPage.vue | 9 +- 9 files changed, 351 insertions(+), 15 deletions(-) create mode 100644 backend/api/user.php create mode 100644 backend/app/class/enity/class_base.php create mode 100644 backend/app/class/enity/class_user.php create mode 100644 backend/app/restAPI/class_restApi.php diff --git a/backend/api/user.php b/backend/api/user.php new file mode 100644 index 0000000..321d9b6 --- /dev/null +++ b/backend/api/user.php @@ -0,0 +1,64 @@ +create_session( + $data['username'] ?? null, + $data['password'] ?? null + ); + RestApi::response($result); + } + + // Проверка сессии + if ($action === 'check_session') { + $account = new Account(); + $keycookies = $data['keycookies'] ?? $_COOKIE['session'] ?? null; + $result = $account->check_session($keycookies); + RestApi::response($result); + } + + // Выход (удаление всех сессий) + if ($action === 'logout') { + $account = new Account(); + $keycookies = $data['keycookies'] ?? $_COOKIE['session'] ?? null; + $result = $account->logout($keycookies); + RestApi::response($result); + } + + // Создание пользователя + if ($action === 'create_user') { + $account = new Account(); + $account->name = $data['name'] ?? null; + $account->username = $data['username'] ?? null; + $account->password = $data['password'] ?? null; + $account->id_department = $data['id_department'] ?? null; + $account->avatar_url = $data['avatar_url'] ?? null; + $account->telegram = $data['telegram'] ?? null; + + $result = $account->create(); + RestApi::response($result); + } + + // Проверяем, что метод не пустой + if (!$action) { + RestApi::response(['success' => false, 'error' => 'Укажите метод'], 400); + } +} + +if ($method === 'GET') { + // Получение всех пользователей + $account = new Account(); + $users = $account->getAll(); + + RestApi::response(['success' => true, 'data' => $users]); +} + + +?> diff --git a/backend/app/class/enity/class_base.php b/backend/app/class/enity/class_base.php new file mode 100644 index 0000000..8e14503 --- /dev/null +++ b/backend/app/class/enity/class_base.php @@ -0,0 +1,30 @@ + false, + 'errors' => static::$error_message + ]; + } + return null; + } +} + + +?> \ No newline at end of file diff --git a/backend/app/class/enity/class_user.php b/backend/app/class/enity/class_user.php new file mode 100644 index 0000000..b4441a6 --- /dev/null +++ b/backend/app/class/enity/class_user.php @@ -0,0 +1,188 @@ +error_message = []; + + if (!$this->name) { + $this->addError('name', 'Имя не может быть пустым'); + } + if (!$this->username) { + $this->addError('username', 'Логин не может быть пустым'); + } + if ($this->username && Database::get($this->db_name, ['id'], ['username' => $this->username])) { + $this->addError('username', 'Пользователь с таким логином уже существует'); + } + if (!$this->password) { + $this->addError('password', 'Пароль не может быть пустым'); + } + + return $this->getErrors(); + } + + // Создание нового аккаунта + public function create() { + + // Валидация данных + if ($errors = $this->validate()) { + return $errors; + } + + // Вставляем в БД + Database::insert($this->db_name, [ + 'id_department' => $this->id_department, + 'name' => $this->name, + 'username' => $this->username, + 'password' => $this->password, + 'avatar_url' => $this->avatar_url, + 'telegram' => $this->telegram + ]); + + return ['success' => true]; + } + + // Получение всех пользователей + public function getAll() { + return Database::select($this->db_name, [ + 'id_department', + 'name', + 'username', + 'avatar_url', + 'telegram' + ]); + } + + // Создание сессии для пользователя + public function create_session($name_account, $password) { + + // Получаем полные данные аккаунта по переданному имени аккаунта + $account = Database::get($this->db_name, '*', ['username' => $name_account]); + + + if (!$account) { + $this->addError('username', 'Пользователь не найден'); + return $this->getErrors(); + } + + if ($account['password'] !== $password) { + $this->addError('password', 'Неверный пароль'); + return $this->getErrors(); + } + + $keycookies = $name_account . "_" . bin2hex(random_bytes(32)); + $week_seconds = 604800; // 1 неделя в секундах + $data_closed = date('Y-m-d H:i:s', time() + $week_seconds); + + Database::insert($this->db_name_session, [ + 'id_accounts' => $account['id'], + 'keycookies' => $keycookies, + 'data_create' => date('Y-m-d H:i:s'), + 'data_closed' => $data_closed, + 'ip_address' => $_SERVER['REMOTE_ADDR'], + 'user_agent' => $_SERVER['HTTP_USER_AGENT'] + ]); + + // Устанавливаем cookie + setcookie('session', $keycookies, [ + 'expires' => time() + $week_seconds, + 'path' => '/', + 'httponly' => true, + 'samesite' => 'Lax' + ]); + + return [ + 'success' => true, + 'keycookies' => $keycookies + ]; + } + + // Проверка сессии и получение данных пользователя + public function check_session($keycookies) { + // Проверяем, что сессия не пустая + if (!$keycookies) { + $this->addError('session', 'Сессия не указана'); + return $this->getErrors(); + } + + // Ищем сессию + $session = Database::get($this->db_name_session, '*', [ + 'keycookies' => $keycookies, + 'data_closed[>]' => date('Y-m-d H:i:s') + ]); + + // Проверяем, что сессия не пустая + if (!$session) { + $this->addError('session', 'Сессия не найдена или истекла'); + return $this->getErrors(); + } + + // Получаем данные пользователя + $user = Database::get($this->db_name, [ + 'id_department', + 'name', + 'username', + 'avatar_url', + 'telegram' + ], [ + 'id' => $session['id_accounts'] + ]); + + if (!$user) { + $this->addError('user', 'Пользователь не найден'); + return $this->getErrors(); + } + + return [ + 'success' => true, + 'user' => $user + ]; + } + + // Удаление всех сессий пользователя (logout) + public function logout($keycookies) { + // Проверяем, что сессия не пустая + if (!$keycookies) { + $this->addError('session', 'Сессия не указана'); + return $this->getErrors(); + } + + // Получаем сессию чтобы узнать id пользователя + $session = Database::get($this->db_name_session, ['id_accounts'], [ + 'keycookies' => $keycookies + ]); + + if (!$session) { + $this->addError('session', 'Сессия не найдена'); + return $this->getErrors(); + } + + // Удаляем все сессии этого пользователя + Database::delete($this->db_name_session, [ + 'id_accounts' => $session['id_accounts'] + ]); + + // Удаляем cookie + setcookie('session', '', [ + 'expires' => time() - 3600, + 'path' => '/' + ]); + + return ['success' => true]; + } +} + +?> \ No newline at end of file diff --git a/backend/app/config.php b/backend/app/config.php index 583f396..168f1f5 100644 --- a/backend/app/config.php +++ b/backend/app/config.php @@ -8,6 +8,11 @@ require_once __DIR__ . '/functions/function.php'; require_once __DIR__ . '/functions/routing.php'; + // подключение классов REST API и Entity + require_once __DIR__ . '/restAPI/class_restApi.php'; + require_once __DIR__ . '/class/enity/class_base.php'; + require_once __DIR__ . '/class/enity/class_user.php'; + // Данные подключения к БД define('DB_HOST', '192.168.1.9'); define('DB_USER', 'root'); @@ -16,4 +21,11 @@ define('DB_PORT', 3306); define('DB_CHARSET', 'utf8mb4'); + // Инициализация подключения к БД + Database::init(); + + $routes = [ + '/api/user' => 'api/user.php', + ]; + ?> \ No newline at end of file diff --git a/backend/app/restAPI/class_restApi.php b/backend/app/restAPI/class_restApi.php new file mode 100644 index 0000000..2c175ec --- /dev/null +++ b/backend/app/restAPI/class_restApi.php @@ -0,0 +1,23 @@ + diff --git a/backend/index.php b/backend/index.php index 5150008..dc9e4fb 100644 --- a/backend/index.php +++ b/backend/index.php @@ -2,6 +2,19 @@ require_once __DIR__ . '/app/config.php'; +// CORS заголовки +$origin = $_SERVER['HTTP_ORIGIN'] ?? ''; +header("Access-Control-Allow-Origin: $origin"); +header("Access-Control-Allow-Credentials: true"); +header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS"); +header("Access-Control-Allow-Headers: Content-Type, Authorization"); + +// Preflight запрос +if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { + http_response_code(200); + exit; +} + // Игнорируем запросы к favicon.ico и другим статическим файлам $requestUri = $_SERVER['REQUEST_URI'] ?? ''; if (preg_match('/\.(ico|png|jpg|jpeg|gif|css|js|svg|woff|woff2|ttf|eot)$/i', $requestUri)) { @@ -9,8 +22,7 @@ if (preg_match('/\.(ico|png|jpg|jpeg|gif|css|js|svg|woff|woff2|ttf|eot)$/i', $re exit; } -header('Content-Type: application/json; charset=utf-8'); -$accounts = Database::select('accounts', '*'); +handleRouting($routes); -echo json_encode([$accounts]); +?> diff --git a/front_vue/src/api.js b/front_vue/src/api.js index 3b95358..a6daecc 100644 --- a/front_vue/src/api.js +++ b/front_vue/src/api.js @@ -9,14 +9,24 @@ const request = async (endpoint, options = {}) => { // ==================== AUTH ==================== export const authApi = { - login: (data) => request('/auth', { + login: (username, password) => request('/api/user', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(data) + body: JSON.stringify({ action: 'auth_login', username, password }) }), - check: () => request('/check-auth', { credentials: 'include' }), - logout: () => request('/logout', { credentials: 'include' }) + check: () => request('/api/user', { + method: 'POST', + credentials: 'include', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ action: 'check_session' }) + }), + logout: () => request('/api/user', { + method: 'POST', + credentials: 'include', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ action: 'logout' }) + }) } // ==================== DEPARTMENTS ==================== @@ -57,5 +67,5 @@ export const cardsApi = { // ==================== USERS ==================== export const usersApi = { - getAll: () => request('/users', { credentials: 'include' }) + getAll: () => request('/api/user', { credentials: 'include' }) } \ No newline at end of file diff --git a/front_vue/src/router.js b/front_vue/src/router.js index 6ccd21b..b410ec0 100644 --- a/front_vue/src/router.js +++ b/front_vue/src/router.js @@ -8,7 +8,7 @@ import { authApi } from './api' const checkAuth = async () => { try { const data = await authApi.check() - return data.status === 'ok' + return data.success === true } catch { return false } diff --git a/front_vue/src/views/LoginPage.vue b/front_vue/src/views/LoginPage.vue index 954fc49..1a17824 100644 --- a/front_vue/src/views/LoginPage.vue +++ b/front_vue/src/views/LoginPage.vue @@ -60,15 +60,12 @@ const handleLogin = async () => { loading.value = true try { - const data = await authApi.login({ - login: login.value, - password: password.value - }) + const data = await authApi.login(login.value, password.value) - if (data.status === 'ok') { + if (data.success) { router.push('/') } else { - error.value = 'Неверный логин или пароль' + error.value = data.errors?.username || data.errors?.password || 'Неверный логин или пароль' } } catch (e) { error.value = 'Ошибка подключения к серверу'