Развитие бека
1. Создание БД 2. Создание бека 3. Пока создали класс юзера
This commit is contained in:
64
backend/api/user.php
Normal file
64
backend/api/user.php
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$method = $_SERVER['REQUEST_METHOD'];
|
||||||
|
|
||||||
|
if ($method === 'POST') {
|
||||||
|
$data = RestApi::getInput();
|
||||||
|
$action = $data['action'] ?? null;
|
||||||
|
|
||||||
|
// Авторизация
|
||||||
|
if ($action === 'auth_login') {
|
||||||
|
$account = new Account();
|
||||||
|
$result = $account->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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
30
backend/app/class/enity/class_base.php
Normal file
30
backend/app/class/enity/class_base.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class BaseEntity
|
||||||
|
|
||||||
|
{
|
||||||
|
protected static $status_error = 0;
|
||||||
|
protected static $error_message = [];
|
||||||
|
|
||||||
|
// Вспомогательные методы для работы с ошибками
|
||||||
|
protected function addError($key, $message)
|
||||||
|
{
|
||||||
|
static::$status_error = 1;
|
||||||
|
static::$error_message[$key] = $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получить ошибки
|
||||||
|
public function getErrors()
|
||||||
|
{
|
||||||
|
if (static::$error_message) {
|
||||||
|
return [
|
||||||
|
'success' => false,
|
||||||
|
'errors' => static::$error_message
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
188
backend/app/class/enity/class_user.php
Normal file
188
backend/app/class/enity/class_user.php
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Account extends BaseEntity {
|
||||||
|
|
||||||
|
protected $db_name = 'accounts';
|
||||||
|
protected $db_name_session = 'accounts_session';
|
||||||
|
|
||||||
|
// Переменные свойств объекта
|
||||||
|
|
||||||
|
public $id_department;
|
||||||
|
public $name;
|
||||||
|
public $username;
|
||||||
|
public $password;
|
||||||
|
public $avatar_url;
|
||||||
|
public $telegram;
|
||||||
|
|
||||||
|
// Валидация данных при создании аккаунта
|
||||||
|
protected function validate() {
|
||||||
|
$this->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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -8,6 +8,11 @@
|
|||||||
require_once __DIR__ . '/functions/function.php';
|
require_once __DIR__ . '/functions/function.php';
|
||||||
require_once __DIR__ . '/functions/routing.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_HOST', '192.168.1.9');
|
||||||
define('DB_USER', 'root');
|
define('DB_USER', 'root');
|
||||||
@@ -16,4 +21,11 @@
|
|||||||
define('DB_PORT', 3306);
|
define('DB_PORT', 3306);
|
||||||
define('DB_CHARSET', 'utf8mb4');
|
define('DB_CHARSET', 'utf8mb4');
|
||||||
|
|
||||||
|
// Инициализация подключения к БД
|
||||||
|
Database::init();
|
||||||
|
|
||||||
|
$routes = [
|
||||||
|
'/api/user' => 'api/user.php',
|
||||||
|
];
|
||||||
|
|
||||||
?>
|
?>
|
||||||
23
backend/app/restAPI/class_restApi.php
Normal file
23
backend/app/restAPI/class_restApi.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class RestApi {
|
||||||
|
|
||||||
|
// Получить данные из JSON запроса
|
||||||
|
public static function getInput(): array {
|
||||||
|
$json = file_get_contents('php://input');
|
||||||
|
$data = json_decode($json, true);
|
||||||
|
|
||||||
|
return $data ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Отправить JSON ответ
|
||||||
|
public static function response($data, int $code = 200): void {
|
||||||
|
http_response_code($code);
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
echo json_encode($data, JSON_UNESCAPED_UNICODE);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -2,6 +2,19 @@
|
|||||||
|
|
||||||
require_once __DIR__ . '/app/config.php';
|
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 и другим статическим файлам
|
// Игнорируем запросы к favicon.ico и другим статическим файлам
|
||||||
$requestUri = $_SERVER['REQUEST_URI'] ?? '';
|
$requestUri = $_SERVER['REQUEST_URI'] ?? '';
|
||||||
if (preg_match('/\.(ico|png|jpg|jpeg|gif|css|js|svg|woff|woff2|ttf|eot)$/i', $requestUri)) {
|
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;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
|
||||||
|
|
||||||
$accounts = Database::select('accounts', '*');
|
handleRouting($routes);
|
||||||
|
|
||||||
echo json_encode([$accounts]);
|
?>
|
||||||
|
|||||||
@@ -9,14 +9,24 @@ const request = async (endpoint, options = {}) => {
|
|||||||
|
|
||||||
// ==================== AUTH ====================
|
// ==================== AUTH ====================
|
||||||
export const authApi = {
|
export const authApi = {
|
||||||
login: (data) => request('/auth', {
|
login: (username, password) => request('/api/user', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify({ action: 'auth_login', username, password })
|
||||||
}),
|
}),
|
||||||
check: () => request('/check-auth', { credentials: 'include' }),
|
check: () => request('/api/user', {
|
||||||
logout: () => request('/logout', { credentials: 'include' })
|
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 ====================
|
// ==================== DEPARTMENTS ====================
|
||||||
@@ -57,5 +67,5 @@ export const cardsApi = {
|
|||||||
|
|
||||||
// ==================== USERS ====================
|
// ==================== USERS ====================
|
||||||
export const usersApi = {
|
export const usersApi = {
|
||||||
getAll: () => request('/users', { credentials: 'include' })
|
getAll: () => request('/api/user', { credentials: 'include' })
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ import { authApi } from './api'
|
|||||||
const checkAuth = async () => {
|
const checkAuth = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await authApi.check()
|
const data = await authApi.check()
|
||||||
return data.status === 'ok'
|
return data.success === true
|
||||||
} catch {
|
} catch {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,15 +60,12 @@ const handleLogin = async () => {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await authApi.login({
|
const data = await authApi.login(login.value, password.value)
|
||||||
login: login.value,
|
|
||||||
password: password.value
|
|
||||||
})
|
|
||||||
|
|
||||||
if (data.status === 'ok') {
|
if (data.success) {
|
||||||
router.push('/')
|
router.push('/')
|
||||||
} else {
|
} else {
|
||||||
error.value = 'Неверный логин или пароль'
|
error.value = data.errors?.username || data.errors?.password || 'Неверный логин или пароль'
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error.value = 'Ошибка подключения к серверу'
|
error.value = 'Ошибка подключения к серверу'
|
||||||
|
|||||||
Reference in New Issue
Block a user