From 55b3d5f08812145578f00fbe6e921685a56cf836 Mon Sep 17 00:00:00 2001 From: Jester Date: Mon, 19 Jan 2026 08:35:00 +0300 Subject: [PATCH] init --- README.md | 52 --------------- api/check_auth.php | 15 +++++ api/login.php | 37 +++++++++++ api/logout.php | 5 ++ auth/api/check.php | 44 ------------- auth/api/login.php | 87 ------------------------ auth/config.php | 19 ------ auth/config_nas.php | 19 ------ auth/db.php | 17 ----- auth/demo.html | 24 ------- auth/guard.js | 35 ---------- auth/guard.php | 46 ------------- auth/logger.php | 30 --------- auth/login.html | 55 ---------------- auth/login.js | 64 ------------------ auth/rate_limit.php | 55 ---------------- auth/styles.css | 117 --------------------------------- auth/util.php | 53 --------------- config/db.php | 16 +++++ db/schema.sql | 32 --------- docker-pack/Dockerfile | 7 -- docker-pack/README.md | 56 ---------------- docker-pack/docker-compose.yml | 24 ------- docker-pack/seed.sql | 5 -- index.html | 36 ++++++++++ js/auth.js | 58 ++++++++++++++++ login.html | 16 +++++ 27 files changed, 183 insertions(+), 841 deletions(-) delete mode 100644 README.md create mode 100644 api/check_auth.php create mode 100644 api/login.php create mode 100644 api/logout.php delete mode 100644 auth/api/check.php delete mode 100644 auth/api/login.php delete mode 100644 auth/config.php delete mode 100644 auth/config_nas.php delete mode 100644 auth/db.php delete mode 100644 auth/demo.html delete mode 100644 auth/guard.js delete mode 100644 auth/guard.php delete mode 100644 auth/logger.php delete mode 100644 auth/login.html delete mode 100644 auth/login.js delete mode 100644 auth/rate_limit.php delete mode 100644 auth/styles.css delete mode 100644 auth/util.php create mode 100644 config/db.php delete mode 100644 db/schema.sql delete mode 100644 docker-pack/Dockerfile delete mode 100644 docker-pack/README.md delete mode 100644 docker-pack/docker-compose.yml delete mode 100644 docker-pack/seed.sql create mode 100644 index.html create mode 100644 js/auth.js create mode 100644 login.html diff --git a/README.md b/README.md deleted file mode 100644 index 175e84d..0000000 --- a/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# Auth Form (PHP drop-in) - -Современная форма авторизации с проверкой доступа к сайту через MariaDB. -Файлы можно копировать прямо в папку существующего сайта. - -## Требования - -- PHP 7.4+ (mysqli, sessions) -- MariaDB - -## Установка - -1. Создайте базу и таблицы: - - Запустите SQL из `db/schema.sql` -2. Заполните подключение к БД: - - Отредактируйте `auth/config.php` -3. Добавьте пользователя и доступ: - - `INSERT INTO users (login, password_hash) VALUES ('demo', '');` - - `INSERT INTO user_access (user_id, site_key) VALUES (1, 'example.com');` - -## Хэш пароля - -Создать bcrypt-хэш можно так: - -```php - - -``` - -3. Главную страницу не защищайте — вход находится в `/auth/login.html`. -4. Если страницы могут быть PHP, используйте серверную защиту: - -```php - true, + 'user' => [ + 'id' => $_SESSION['user_id'], + 'username' => $_SESSION['username'] + ] + ]); +} else { + echo json_encode(['isLoggedIn' => false]); +} +?> \ No newline at end of file diff --git a/api/login.php b/api/login.php new file mode 100644 index 0000000..9b6d139 --- /dev/null +++ b/api/login.php @@ -0,0 +1,37 @@ +prepare("SELECT * FROM users WHERE username = ?"); + $stmt->execute([$login]); + $user = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($user && password_verify($password, $user['password_hash'])) { + // Успешная авторизация + session_start(); + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + + echo json_encode([ + 'success' => true, + 'message' => 'Вход выполнен успешно', + 'user' => [ + 'id' => $user['id'], + 'username' => $user['username'], + ] + ]); + } else { + echo json_encode(['success' => false, 'message' => 'Неверные учетные данные']); + } +} +?> diff --git a/api/logout.php b/api/logout.php new file mode 100644 index 0000000..829c135 --- /dev/null +++ b/api/logout.php @@ -0,0 +1,5 @@ + true]); +?> \ No newline at end of file diff --git a/auth/api/check.php b/auth/api/check.php deleted file mode 100644 index ddf0eae..0000000 --- a/auth/api/check.php +++ /dev/null @@ -1,44 +0,0 @@ - $clientIp, - "siteKey" => $siteKey, - "status" => "invalid_payload", - ]); - auth_json_response(400, ["ok" => false, "message" => "Неверные данные."]); -} - -$userId = (int) ($_SESSION["auth_user_id"] ?? 0); -if ($userId <= 0) { - auth_json_response(401, ["ok" => false, "message" => "Требуется вход."]); -} - -$db = auth_get_db(); -$stmt = $db->prepare("SELECT 1 FROM user_access WHERE user_id = ? AND site_key = ? LIMIT 1"); -$stmt->bind_param("is", $userId, $siteKey); -$stmt->execute(); -$result = $stmt->get_result(); -$hasAccess = $result && $result->num_rows > 0; -$stmt->close(); - -if (!$hasAccess) { - auth_log_event([ - "ip" => $clientIp, - "userId" => $userId, - "siteKey" => $siteKey, - "status" => "access_denied", - ]); - auth_json_response(403, ["ok" => false, "message" => "Нет доступа."]); -} - -auth_json_response(200, ["ok" => true]); diff --git a/auth/api/login.php b/auth/api/login.php deleted file mode 100644 index 2c66d68..0000000 --- a/auth/api/login.php +++ /dev/null @@ -1,87 +0,0 @@ - $clientIp, - "login" => $login, - "siteKey" => $siteKey, - "status" => "invalid_payload", - ]); - auth_json_response(400, ["ok" => false, "message" => "Неверные данные."]); -} - -$rate = auth_check_rate_limit($clientIp); -if ($rate["limited"]) { - auth_log_event([ - "ip" => $clientIp, - "login" => $login, - "siteKey" => $siteKey, - "status" => "rate_limited", - ]); - header("Retry-After: " . (string) $rate["retry_after"]); - auth_json_response(429, ["ok" => false, "message" => "Слишком много попыток. Попробуйте позже."]); -} - -$db = auth_get_db(); -$stmt = $db->prepare("SELECT id, password_hash FROM users WHERE login = ? LIMIT 1"); -$stmt->bind_param("s", $login); -$stmt->execute(); -$result = $stmt->get_result(); -$row = $result ? $result->fetch_assoc() : null; -$stmt->close(); - -$hash = $row["password_hash"] ?? password_hash("invalid_password", PASSWORD_BCRYPT); -$passwordOk = password_verify($password, $hash); - -if (!$row || !$passwordOk) { - auth_log_event([ - "ip" => $clientIp, - "login" => $login, - "siteKey" => $siteKey, - "status" => "invalid_credentials", - ]); - auth_json_response(401, ["ok" => false, "message" => "Неверный логин или пароль."]); -} - -$stmt = $db->prepare("SELECT 1 FROM user_access WHERE user_id = ? AND site_key = ? LIMIT 1"); -$stmt->bind_param("is", $row["id"], $siteKey); -$stmt->execute(); -$accessResult = $stmt->get_result(); -$hasAccess = $accessResult && $accessResult->num_rows > 0; -$stmt->close(); - -if (!$hasAccess) { - auth_log_event([ - "ip" => $clientIp, - "login" => $login, - "siteKey" => $siteKey, - "status" => "access_denied", - ]); - auth_json_response(403, ["ok" => false, "message" => "Нет доступа к этому сайту."]); -} - -$_SESSION["auth_user_id"] = (int) $row["id"]; -$_SESSION["auth_login"] = $login; -$_SESSION["auth_time"] = time(); - -auth_log_event([ - "ip" => $clientIp, - "login" => $login, - "siteKey" => $siteKey, - "status" => "success", -]); - -auth_json_response(200, ["ok" => true]); diff --git a/auth/config.php b/auth/config.php deleted file mode 100644 index ba7df4b..0000000 --- a/auth/config.php +++ /dev/null @@ -1,19 +0,0 @@ - [ - "host" => "db", - "port" => 3306, - "user" => "root", - "password" => "rootpass", - "name" => "auth_db", - ], - "rate_limit" => [ - "window_seconds" => 300, - "max_attempts" => 10, - ], - "logging" => [ - "dir" => __DIR__ . "/logs", - "file" => __DIR__ . "/logs/auth.log", - ], -]; diff --git a/auth/config_nas.php b/auth/config_nas.php deleted file mode 100644 index e2b4b75..0000000 --- a/auth/config_nas.php +++ /dev/null @@ -1,19 +0,0 @@ - [ - "host" => "127.0.0.1", - "port" => 3306, - "user" => "root", - "password" => "", - "name" => "auth_db", - ], - "rate_limit" => [ - "window_seconds" => 300, - "max_attempts" => 10, - ], - "logging" => [ - "dir" => __DIR__ . "/logs", - "file" => __DIR__ . "/logs/auth.log", - ], -]; diff --git a/auth/db.php b/auth/db.php deleted file mode 100644 index c3feb29..0000000 --- a/auth/db.php +++ /dev/null @@ -1,17 +0,0 @@ -connect_errno) { - http_response_code(500); - echo json_encode(["ok" => false, "message" => "Ошибка сервера."]); - exit; - } - - $mysqli->set_charset("utf8mb4"); - return $mysqli; -} diff --git a/auth/demo.html b/auth/demo.html deleted file mode 100644 index 02c5228..0000000 --- a/auth/demo.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - Демо защищенной страницы - - - - -
-
-
-

Демо защищенной страницы

-

- Если вы видите эту страницу, доступ разрешен. -

-
- Перейти к форме входа -
-
- - diff --git a/auth/guard.js b/auth/guard.js deleted file mode 100644 index d01db12..0000000 --- a/auth/guard.js +++ /dev/null @@ -1,35 +0,0 @@ -function authGetSiteKey() { - const meta = document.querySelector('meta[name="site-key"]'); - if (meta && meta.content) return meta.content.trim(); - const bodyKey = document.body?.dataset?.siteKey; - if (bodyKey) return bodyKey.trim(); - return window.location.hostname || "unknown"; -} - -function authBuildLoginUrl(siteKey) { - const current = window.location.pathname + window.location.search; - const params = new URLSearchParams({ - siteKey, - redirect: current, - }); - return `/auth/login.html?${params.toString()}`; -} - -async function authCheckAccess() { - const siteKey = authGetSiteKey(); - try { - const response = await fetch(`/auth/api/check.php?siteKey=${encodeURIComponent(siteKey)}`, { - method: "GET", - headers: { "Accept": "application/json" }, - credentials: "same-origin", - }); - - if (response.ok) return; - - window.location.href = authBuildLoginUrl(siteKey); - } catch (error) { - window.location.href = authBuildLoginUrl(siteKey); - } -} - -authCheckAccess(); diff --git a/auth/guard.php b/auth/guard.php deleted file mode 100644 index 31bb05c..0000000 --- a/auth/guard.php +++ /dev/null @@ -1,46 +0,0 @@ - auth_get_client_ip(), - "siteKey" => $siteKey, - "status" => "invalid_payload", - ]); - header("Location: /auth/login.html"); - exit; -} - -$userId = (int) ($_SESSION["auth_user_id"] ?? 0); -if ($userId <= 0) { - $redirect = $_SERVER["REQUEST_URI"] ?? "/"; - header("Location: /auth/login.html?siteKey=" . urlencode($siteKey) . "&redirect=" . urlencode($redirect)); - exit; -} - -$db = auth_get_db(); -$stmt = $db->prepare("SELECT 1 FROM user_access WHERE user_id = ? AND site_key = ? LIMIT 1"); -$stmt->bind_param("is", $userId, $siteKey); -$stmt->execute(); -$result = $stmt->get_result(); -$hasAccess = $result && $result->num_rows > 0; -$stmt->close(); - -if (!$hasAccess) { - auth_log_event([ - "ip" => auth_get_client_ip(), - "userId" => $userId, - "siteKey" => $siteKey, - "status" => "access_denied", - ]); - header("Location: /auth/login.html?siteKey=" . urlencode($siteKey)); - exit; -} diff --git a/auth/logger.php b/auth/logger.php deleted file mode 100644 index e5c6644..0000000 --- a/auth/logger.php +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - Вход - - - -
-
-
-

Добро пожаловать

-

Войдите, чтобы продолжить

-
- -
- - - - - - -
-
-
-
- - - diff --git a/auth/login.js b/auth/login.js deleted file mode 100644 index 29c6671..0000000 --- a/auth/login.js +++ /dev/null @@ -1,64 +0,0 @@ -const form = document.getElementById("login-form"); -const messageEl = document.getElementById("form-message"); - -function getSiteKey() { - const params = new URLSearchParams(window.location.search); - const urlKey = params.get("siteKey"); - if (urlKey) return urlKey.trim(); - const meta = document.querySelector('meta[name="site-key"]'); - if (meta && meta.content) return meta.content.trim(); - return window.location.hostname || "unknown"; -} - -function getRedirectUrl() { - const params = new URLSearchParams(window.location.search); - return params.get("redirect") || "/"; -} - -function setMessage(text, type) { - messageEl.textContent = text; - messageEl.classList.remove("form__message--error", "form__message--success"); - if (type === "error") messageEl.classList.add("form__message--error"); - if (type === "success") messageEl.classList.add("form__message--success"); -} - -form.addEventListener("submit", async (event) => { - event.preventDefault(); - const formData = new FormData(form); - const login = String(formData.get("login") || "").trim(); - const password = String(formData.get("password") || ""); - const siteKey = getSiteKey(); - - if (!login || !password) { - setMessage("Введите логин и пароль.", "error"); - return; - } - - setMessage("Проверяем данные...", ""); - const submitButton = form.querySelector("button[type='submit']"); - submitButton.disabled = true; - - try { - const response = await fetch("./api/login.php", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ login, password, siteKey }), - }); - const data = await response.json().catch(() => ({})); - - if (!response.ok) { - setMessage(data?.message || "Ошибка входа.", "error"); - return; - } - - setMessage("Доступ разрешен.", "success"); - const redirect = getRedirectUrl(); - setTimeout(() => { - window.location.href = redirect; - }, 400); - } catch (error) { - setMessage("Сеть недоступна.", "error"); - } finally { - submitButton.disabled = false; - } -}); diff --git a/auth/rate_limit.php b/auth/rate_limit.php deleted file mode 100644 index 69c1c89..0000000 --- a/auth/rate_limit.php +++ /dev/null @@ -1,55 +0,0 @@ - 1, - "reset_at" => $now + $window, - ]; - - if (is_file($file)) { - $raw = @file_get_contents($file); - $decoded = $raw ? json_decode($raw, true) : null; - if (is_array($decoded) && isset($decoded["count"], $decoded["reset_at"])) { - if ($now <= (int) $decoded["reset_at"]) { - $decoded["count"] = (int) $decoded["count"] + 1; - $data = $decoded; - } - } - } - - $limited = $data["count"] > $max; - $retryAfter = max(0, $data["reset_at"] - $now); - - $payload = json_encode($data); - if ($payload !== false) { - $fh = @fopen($file, "cb+"); - if ($fh !== false) { - if (flock($fh, LOCK_EX)) { - ftruncate($fh, 0); - fwrite($fh, $payload); - fflush($fh); - flock($fh, LOCK_UN); - } - fclose($fh); - } - } - - return [ - "limited" => $limited, - "retry_after" => $retryAfter, - ]; -} diff --git a/auth/styles.css b/auth/styles.css deleted file mode 100644 index 90cb6aa..0000000 --- a/auth/styles.css +++ /dev/null @@ -1,117 +0,0 @@ -*, -*::before, -*::after { - box-sizing: border-box; -} - -body { - margin: 0; - font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif; - color: #0b1320; - background: radial-gradient(circle at top, #f0f4ff 0%, #e4ecff 45%, #dfe8ff 100%); - min-height: 100vh; -} - -.page { - min-height: 100vh; - display: flex; - align-items: center; - justify-content: center; - padding: 40px 16px; -} - -.card { - width: min(420px, 100%); - background: rgba(255, 255, 255, 0.75); - backdrop-filter: blur(16px); - border-radius: 20px; - padding: 32px; - box-shadow: 0 20px 60px rgba(25, 42, 80, 0.15); - border: 1px solid rgba(255, 255, 255, 0.6); -} - -.card__header { - margin-bottom: 24px; -} - -.card__header h1 { - margin: 0 0 8px; - font-size: 26px; - font-weight: 700; -} - -.card__subtitle { - margin: 0; - color: #51607a; - font-size: 14px; -} - -.form { - display: grid; - gap: 16px; -} - -.field { - display: grid; - gap: 8px; -} - -.field__label { - font-size: 13px; - color: #4c5a73; -} - -.field__input { - width: 100%; - border-radius: 12px; - border: 1px solid #d6def2; - padding: 12px 14px; - font-size: 15px; - transition: border 0.2s ease, box-shadow 0.2s ease; -} - -.field__input:focus { - outline: none; - border-color: #6f87ff; - box-shadow: 0 0 0 4px rgba(111, 135, 255, 0.2); -} - -.button { - display: inline-block; - text-decoration: none; - text-align: center; - border: none; - border-radius: 12px; - padding: 12px 16px; - font-size: 15px; - font-weight: 600; - color: #fff; - background: linear-gradient(120deg, #5b7cfa, #7b5bfa); - cursor: pointer; - transition: transform 0.2s ease, box-shadow 0.2s ease; -} - -.button:hover { - transform: translateY(-1px); - box-shadow: 0 12px 24px rgba(91, 124, 250, 0.25); -} - -.button:disabled { - cursor: not-allowed; - opacity: 0.7; - box-shadow: none; -} - -.form__message { - min-height: 20px; - font-size: 13px; - color: #4c5a73; -} - -.form__message--error { - color: #b91c1c; -} - -.form__message--success { - color: #166534; -} diff --git a/auth/util.php b/auth/util.php deleted file mode 100644 index f62a945..0000000 --- a/auth/util.php +++ /dev/null @@ -1,53 +0,0 @@ -= 3 && $len <= 64; -} - -function auth_is_valid_password(string $password): bool -{ - $len = mb_strlen($password, "UTF-8"); - return $len >= 8 && $len <= 128; -} - -function auth_is_valid_site_key(string $siteKey): bool -{ - $len = mb_strlen($siteKey, "UTF-8"); - return $len >= 3 && $len <= 255; -} diff --git a/config/db.php b/config/db.php new file mode 100644 index 0000000..2b71884 --- /dev/null +++ b/config/db.php @@ -0,0 +1,16 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +} catch(PDOException $e) { + die("Ошибка подключения: " . $e->getMessage()); +} +?> diff --git a/db/schema.sql b/db/schema.sql deleted file mode 100644 index a77a91e..0000000 --- a/db/schema.sql +++ /dev/null @@ -1,32 +0,0 @@ -CREATE DATABASE IF NOT EXISTS auth_db - CHARACTER SET utf8mb4 - COLLATE utf8mb4_unicode_ci; - -USE auth_db; - -CREATE TABLE IF NOT EXISTS users ( - id INT UNSIGNED NOT NULL AUTO_INCREMENT, - login VARCHAR(64) NOT NULL UNIQUE, - password_hash VARCHAR(255) NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (id) -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS user_access ( - id INT UNSIGNED NOT NULL AUTO_INCREMENT, - user_id INT UNSIGNED NOT NULL, - site_key VARCHAR(255) NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (id), - UNIQUE KEY unique_access (user_id, site_key), - CONSTRAINT fk_user_access_user - FOREIGN KEY (user_id) REFERENCES users(id) - ON DELETE CASCADE -) ENGINE=InnoDB; - --- Пример: --- INSERT INTO users (login, password_hash) --- VALUES ('demo', '$2a$10$YOUR_BCRYPT_HASH_HERE'); --- --- INSERT INTO user_access (user_id, site_key) --- VALUES (1, 'example.com'); diff --git a/docker-pack/Dockerfile b/docker-pack/Dockerfile deleted file mode 100644 index 96ac392..0000000 --- a/docker-pack/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM php:8.2-apache - -RUN docker-php-ext-install mysqli - -RUN a2enmod rewrite headers - -WORKDIR /var/www/html diff --git a/docker-pack/README.md b/docker-pack/README.md deleted file mode 100644 index c3e4ca5..0000000 --- a/docker-pack/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# Docker инструкция (Windows) - -Все файлы для Docker лежат в `docker-pack/` и не трогают текущее решение. - -## Требования - -- Docker Desktop (включите WSL2 backend) - -## Быстрый старт - -1. Перейдите в каталог: - - `cd d:\work\code\auth\docker-pack` -2. Соберите и запустите контейнеры: - - `docker compose up -d --build` -3. Откройте в браузере: - - `http://localhost:8080/auth/login.html` - -## Настройка БД - -По умолчанию MariaDB поднимается с: - -- БД: `auth_db` -- root пароль: `rootpass` - -Схема создается автоматически из `../db/schema.sql`. -Пользователь `demo` добавляется автоматически из `seed.sql`. - -### Тестовые данные - -По умолчанию создается пользователь: - -- логин: `demo` -- пароль: `demo12345` -- site_key: `localhost` - -Если нужно изменить — отредактируйте `seed.sql` и пересоздайте контейнеры: - -- `docker compose down -v` -- `docker compose up -d --build` - -## Важно про конфиг PHP - -В `auth/config.php` укажите параметры подключения: - -- host: `db` -- port: `3306` -- user: `root` -- password: `rootpass` -- name: `auth_db` - -Если хотите оставить `auth/config.php` для локальной сети, заведите отдельную копию -только для Docker и подмените ее через volume в `docker-compose.yml`. - -## Остановка - -- `docker compose down` diff --git a/docker-pack/docker-compose.yml b/docker-pack/docker-compose.yml deleted file mode 100644 index 24e4167..0000000 --- a/docker-pack/docker-compose.yml +++ /dev/null @@ -1,24 +0,0 @@ -version: "3.9" - -services: - web: - build: . - ports: - - "8080:80" - volumes: - - ../auth:/var/www/html/auth:ro - depends_on: - - db - - db: - image: mariadb:11 - environment: - MARIADB_ROOT_PASSWORD: rootpass - MARIADB_DATABASE: auth_db - volumes: - - ../db/schema.sql:/docker-entrypoint-initdb.d/01-schema.sql:ro - - ./seed.sql:/docker-entrypoint-initdb.d/02-seed.sql:ro - - db_data:/var/lib/mysql - -volumes: - db_data: diff --git a/docker-pack/seed.sql b/docker-pack/seed.sql deleted file mode 100644 index a9b3545..0000000 --- a/docker-pack/seed.sql +++ /dev/null @@ -1,5 +0,0 @@ -INSERT INTO users (login, password_hash) -VALUES ('demo', '$2y$10$MyDhXOP.UZAHJcE1KWoQU.PJfxa5C82FePAuZYphCMaXya.Ylxlne'); - -INSERT INTO user_access (user_id, site_key) -VALUES (1, 'localhost'); diff --git a/index.html b/index.html new file mode 100644 index 0000000..aaef4f8 --- /dev/null +++ b/index.html @@ -0,0 +1,36 @@ + + + + Личный кабинет + + +
+ + + + + \ No newline at end of file diff --git a/js/auth.js b/js/auth.js new file mode 100644 index 0000000..d61cb3b --- /dev/null +++ b/js/auth.js @@ -0,0 +1,58 @@ +// Общие функции для AJAX запросов +async function sendRequest(url, data) { + try { + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data) + }); + return await response.json(); + } catch (error) { + console.error('Ошибка:', error); + return { success: false, message: 'Ошибка сети' }; + } +} + +// Обработка регистрации +if (document.getElementById('registerForm')) { + document.getElementById('registerForm').addEventListener('submit', async function(e) { + e.preventDefault(); + + const formData = new FormData(this); + const data = Object.fromEntries(formData); + + const result = await sendRequest('api/register.php', data); + + if (result.success) { + alert(result.message); + window.location.href = 'login.html'; + } else { + alert('Ошибка: ' + result.message); + } + }); +} + +// Обработка входа +if (document.getElementById('loginForm')) { + document.getElementById('loginForm').addEventListener('submit', async function(e) { + e.preventDefault(); + + const formData = new FormData(this); + const data = Object.fromEntries(formData); + + const result = await sendRequest('api/login.php', data); + + if (result.success) { + // Сохраняем данные пользователя в localStorage + localStorage.setItem('user', JSON.stringify(result.user)); + localStorage.setItem('isLoggedIn', 'true'); + + alert(result.message); + window.location.href = 'index.html'; + } else { + alert('Ошибка: ' + result.message); + } + }); +} \ No newline at end of file diff --git a/login.html b/login.html new file mode 100644 index 0000000..fa588b8 --- /dev/null +++ b/login.html @@ -0,0 +1,16 @@ + + + + Вход + + +

Вход

+
+ + + +
+ + + + \ No newline at end of file