From 011996d78dfc5cf1acd7ed8910cde23275da6827 Mon Sep 17 00:00:00 2001 From: arkonsadter Date: Wed, 14 Jan 2026 21:54:24 +0600 Subject: [PATCH] Add Personal account --- CHANGELOG.md | 38 +++ PROFILE_SYSTEM.md | 228 ++++++++++++++ backend/main.py | 126 +++++++- frontend/src/App.jsx | 67 +++- frontend/src/components/Profile.jsx | 468 ++++++++++++++++++++++++++++ ГОТОВО.md | 19 +- ЛИЧНЫЙ_КАБИНЕТ_ГОТОВ.md | 183 +++++++++++ 7 files changed, 1125 insertions(+), 4 deletions(-) create mode 100644 PROFILE_SYSTEM.md create mode 100644 frontend/src/components/Profile.jsx create mode 100644 ЛИЧНЫЙ_КАБИНЕТ_ГОТОВ.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cc1396..5a51ca5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,43 @@ # 📝 История изменений MC Panel +## Версия 2.1 - Личный кабинет (14.01.2026) + +### ✨ Новые возможности + +#### 👤 Личный кабинет +- Кнопка "Личный кабинет" в header рядом с "Тикеты" +- Три вкладки: Обзор, Имя пользователя, Пароль +- Статистика профиля (серверы, тикеты, роль) +- Список своих серверов +- Изменение имени пользователя с подтверждением паролем +- Изменение пароля с проверкой +- Показ/скрытие паролей в формах + +#### 🔐 Безопасность +- Проверка уникальности имени пользователя +- Автоматическое обновление владельцев серверов при смене имени +- Автоматическое обновление доступов к серверам +- Новый JWT токен при смене имени +- Хеширование паролей (bcrypt) + +#### 📊 Статистика профиля +- Общее количество серверов +- Мои серверы (владелец) +- Доступные серверы +- Статистика по тикетам (всего, на рассмотрении, в работе, закрыто) +- Информация о роли + +### 📁 Новые файлы +- `frontend/src/components/Profile.jsx` - компонент личного кабинета +- `PROFILE_SYSTEM.md` - документация личного кабинета + +### 🔧 API Endpoints +- `PUT /api/profile/username` - изменить имя пользователя +- `PUT /api/profile/password` - изменить пароль +- `GET /api/profile/stats` - получить статистику профиля + +--- + ## Версия 2.0 - Система тикетов (14.01.2026) ### ✨ Новые возможности diff --git a/PROFILE_SYSTEM.md b/PROFILE_SYSTEM.md new file mode 100644 index 0000000..148cf10 --- /dev/null +++ b/PROFILE_SYSTEM.md @@ -0,0 +1,228 @@ +# 👤 Система личного кабинета + +## Что добавлено + +### ✅ Новые возможности + +1. **Личный кабинет** - полноценная система управления профилем +2. **Три вкладки**: + - 📊 **Обзор** - статистика и информация о профиле + - 👤 **Имя пользователя** - изменение имени пользователя + - 🔒 **Пароль** - изменение пароля + +3. **Кнопка "Личный кабинет"** в header рядом с кнопкой "Тикеты" + +### 📊 Вкладка "Обзор" + +#### Информация о пользователе +- Имя пользователя +- Роль (Администратор, Тех. поддержка, Пользователь) +- Цветной бейдж роли + +#### Статистика +- **Серверы**: + - Всего серверов + - Мои серверы (владелец) + - Доступные серверы + +- **Тикеты**: + - Всего тикетов + - На рассмотрении + - В работе + - Закрыто + +- **Роль**: + - Название роли + - Описание прав + +#### Список серверов +- Отображение всех серверов пользователя +- Название и ID сервера +- Красивые карточки + +### 👤 Вкладка "Имя пользователя" + +#### Возможности +- Просмотр текущего имени +- Ввод нового имени (минимум 3 символа) +- Подтверждение паролем +- Автоматический перелогин с новым именем + +#### Безопасность +- Проверка уникальности имени +- Проверка пароля +- Обновление владельцев серверов +- Обновление доступов к серверам +- Новый JWT токен + +### 🔒 Вкладка "Пароль" + +#### Возможности +- Ввод текущего пароля +- Ввод нового пароля (минимум 6 символов) +- Подтверждение нового пароля +- Показ/скрытие паролей + +#### Безопасность +- Проверка текущего пароля +- Проверка совпадения новых паролей +- Хеширование пароля (bcrypt) + +## 🚀 Как использовать + +### Открытие личного кабинета +1. Нажмите кнопку "Личный кабинет" в header +2. Откроется страница с тремя вкладками + +### Просмотр статистики +1. Откройте вкладку "Обзор" +2. Посмотрите информацию о профиле +3. Посмотрите статистику по серверам и тикетам +4. Посмотрите список своих серверов + +### Изменение имени пользователя +1. Откройте вкладку "Имя пользователя" +2. Введите новое имя (минимум 3 символа) +3. Введите текущий пароль для подтверждения +4. Нажмите "Изменить имя пользователя" +5. Вы будете автоматически перелогинены + +⚠️ **Важно**: После изменения имени: +- Обновятся все серверы, где вы владелец +- Обновятся все доступы к серверам +- Вы получите новый токен авторизации + +### Изменение пароля +1. Откройте вкладку "Пароль" +2. Введите текущий пароль +3. Введите новый пароль (минимум 6 символов) +4. Подтвердите новый пароль +5. Нажмите "Изменить пароль" + +⚠️ **Важно**: После изменения пароля используйте новый пароль для входа. + +## 📁 Новые файлы + +### Backend +- Добавлены endpoints в `backend/main.py`: + - `PUT /api/profile/username` - изменить имя пользователя + - `PUT /api/profile/password` - изменить пароль + - `GET /api/profile/stats` - получить статистику профиля + +### Frontend +- `frontend/src/components/Profile.jsx` - компонент личного кабинета + +## 🎨 Интерфейс + +### Вкладки +- Современный дизайн с вкладками +- Плавные переходы между вкладками +- Адаптивный дизайн + +### Карточки статистики +- Цветные иконки +- Числовые показатели +- Детальная информация + +### Формы +- Валидация полей +- Показ/скрытие паролей +- Предупреждения о последствиях +- Кнопки с индикацией загрузки + +## 🔧 Технические детали + +### API Endpoints + +#### PUT /api/profile/username +Изменить имя пользователя + +**Request:** +```json +{ + "new_username": "NewUsername", + "password": "current_password" +} +``` + +**Response:** +```json +{ + "message": "Имя пользователя изменено", + "access_token": "new_jwt_token", + "username": "NewUsername" +} +``` + +#### PUT /api/profile/password +Изменить пароль + +**Request:** +```json +{ + "old_password": "old_password", + "new_password": "new_password" +} +``` + +**Response:** +```json +{ + "message": "Пароль изменён" +} +``` + +#### GET /api/profile/stats +Получить статистику профиля + +**Response:** +```json +{ + "username": "username", + "role": "user", + "owned_servers": [ + { + "name": "server1", + "displayName": "My Server" + } + ], + "accessible_servers": [], + "tickets": { + "total": 5, + "pending": 2, + "in_progress": 1, + "closed": 2 + }, + "total_servers": 1 +} +``` + +### Безопасность + +#### Изменение имени пользователя +1. Проверка пароля +2. Проверка уникальности нового имени +3. Обновление владельцев серверов +4. Обновление доступов к серверам +5. Создание нового JWT токена + +#### Изменение пароля +1. Проверка текущего пароля +2. Проверка длины нового пароля (минимум 6 символов) +3. Хеширование нового пароля (bcrypt) + +## ✅ Готово! + +Система личного кабинета полностью интегрирована в MC Panel. Пользователи могут: +- Просматривать статистику своего профиля +- Изменять имя пользователя +- Изменять пароль +- Видеть свои серверы и тикеты + +### Доступ к личному кабинету +Кнопка "Личный кабинет" доступна всем пользователям в header рядом с кнопкой "Тикеты". + +### Учётные данные по умолчанию +- **Логин**: Sofa12345 +- **Пароль**: arkonsad123 +- **Роль**: admin diff --git a/backend/main.py b/backend/main.py index 02183c9..c112e96 100644 --- a/backend/main.py +++ b/backend/main.py @@ -266,7 +266,7 @@ async def update_user_role(username: str, data: dict, user: dict = Depends(get_c raise HTTPException(404, "Пользователь не найден") new_role = data.get("role") - if new_role not in ["admin", "user"]: + if new_role not in ["admin", "user", "support"]: raise HTTPException(400, "Неверная роль") users[username]["role"] = new_role @@ -274,6 +274,130 @@ async def update_user_role(username: str, data: dict, user: dict = Depends(get_c return {"message": "Роль обновлена"} +# API для личного кабинета +@app.put("/api/profile/username") +async def update_username(data: dict, user: dict = Depends(get_current_user)): + """Изменить имя пользователя""" + new_username = data.get("new_username", "").strip() + password = data.get("password", "") + + if not new_username: + raise HTTPException(400, "Имя пользователя не может быть пустым") + + if len(new_username) < 3: + raise HTTPException(400, "Имя пользователя должно быть не менее 3 символов") + + users = load_users() + + # Проверяем пароль + if not verify_password(password, users[user["username"]]["password"]): + raise HTTPException(400, "Неверный пароль") + + # Проверяем, не занято ли новое имя + if new_username in users and new_username != user["username"]: + raise HTTPException(400, "Это имя пользователя уже занято") + + # Сохраняем данные пользователя + old_username = user["username"] + user_data = users[old_username] + + # Удаляем старую запись и создаём новую + del users[old_username] + user_data["username"] = new_username + users[new_username] = user_data + + # Обновляем владельцев серверов + for server_dir in SERVERS_DIR.iterdir(): + if server_dir.is_dir(): + config = load_server_config(server_dir.name) + if config.get("owner") == old_username: + config["owner"] = new_username + save_server_config(server_dir.name, config) + + # Обновляем доступы к серверам у других пользователей + for username, user_info in users.items(): + if "servers" in user_info and old_username in user_info.get("servers", []): + user_info["servers"] = [new_username if s == old_username else s for s in user_info["servers"]] + + save_users(users) + + # Создаём новый токен + new_token = create_access_token({"sub": new_username, "role": user_data["role"]}) + + return { + "message": "Имя пользователя изменено", + "access_token": new_token, + "username": new_username + } + +@app.put("/api/profile/password") +async def update_password(data: dict, user: dict = Depends(get_current_user)): + """Изменить пароль""" + old_password = data.get("old_password", "") + new_password = data.get("new_password", "") + + if not old_password or not new_password: + raise HTTPException(400, "Заполните все поля") + + if len(new_password) < 6: + raise HTTPException(400, "Новый пароль должен быть не менее 6 символов") + + users = load_users() + + # Проверяем старый пароль + if not verify_password(old_password, users[user["username"]]["password"]): + raise HTTPException(400, "Неверный старый пароль") + + # Устанавливаем новый пароль + users[user["username"]]["password"] = get_password_hash(new_password) + save_users(users) + + return {"message": "Пароль изменён"} + +@app.get("/api/profile/stats") +async def get_profile_stats(user: dict = Depends(get_current_user)): + """Получить статистику профиля""" + users = load_users() + user_data = users.get(user["username"], {}) + + # Подсчитываем серверы пользователя + owned_servers = [] + accessible_servers = [] + + for server_dir in SERVERS_DIR.iterdir(): + if server_dir.is_dir(): + config = load_server_config(server_dir.name) + if config.get("owner") == user["username"]: + owned_servers.append({ + "name": server_dir.name, + "displayName": config.get("displayName", server_dir.name) + }) + elif user["username"] in user_data.get("servers", []) or user["role"] == "admin": + accessible_servers.append({ + "name": server_dir.name, + "displayName": config.get("displayName", server_dir.name) + }) + + # Подсчитываем тикеты + tickets = load_tickets() + user_tickets = [t for t in tickets.values() if t["author"] == user["username"]] + + tickets_stats = { + "total": len(user_tickets), + "pending": len([t for t in user_tickets if t["status"] == "pending"]), + "in_progress": len([t for t in user_tickets if t["status"] == "in_progress"]), + "closed": len([t for t in user_tickets if t["status"] == "closed"]) + } + + return { + "username": user["username"], + "role": user["role"], + "owned_servers": owned_servers, + "accessible_servers": accessible_servers, + "tickets": tickets_stats, + "total_servers": len(owned_servers) + len(accessible_servers) + } + # API для серверов @app.get("/api/servers") async def get_servers(user: dict = Depends(get_current_user)): diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index aa2fd33..39dd9a3 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react'; -import { Server, Play, Square, Terminal, FolderOpen, HardDrive, Settings, Plus, Users as UsersIcon, LogOut, Menu, X, MessageSquare } from 'lucide-react'; +import { Server, Play, Square, Terminal, FolderOpen, HardDrive, Settings, Plus, Users as UsersIcon, LogOut, Menu, X, MessageSquare, UserCircle } from 'lucide-react'; import Console from './components/Console'; import FileManager from './components/FileManager'; import Stats from './components/Stats'; @@ -7,6 +7,7 @@ import ServerSettings from './components/ServerSettings'; import CreateServerModal from './components/CreateServerModal'; import Users from './components/Users'; import Tickets from './components/Tickets'; +import Profile from './components/Profile'; import Auth from './components/Auth'; import ErrorBoundary from './components/ErrorBoundary'; import ThemeSelector from './components/ThemeSelector'; @@ -23,6 +24,7 @@ function App() { const [showCreateModal, setShowCreateModal] = useState(false); const [showUsers, setShowUsers] = useState(false); const [showTickets, setShowTickets] = useState(false); + const [showProfile, setShowProfile] = useState(false); const [connectionError, setConnectionError] = useState(false); const [theme, setTheme] = useState(localStorage.getItem('theme') || 'dark'); const [sidebarOpen, setSidebarOpen] = useState(true); @@ -97,6 +99,12 @@ function App() { localStorage.setItem('theme', newTheme); }; + const handleUsernameChange = (newToken, newUsername) => { + setToken(newToken); + setUser({ ...user, username: newUsername }); + loadServers(); + }; + const startServer = async (serverName) => { try { const response = await axios.post( @@ -235,6 +243,56 @@ function App() { ); } + if (showProfile) { + return ( +
+
+
+
+
+
+
+ +
+
+

MC Panel

+

Управление серверами

+
+
+
+
+
+ + {user?.username} + + + {user?.role === 'admin' ? 'Админ' : user?.role === 'support' ? 'Поддержка' : 'Пользователь'} + +
+ + + +
+
+
+
+ +
+ ); + } + return (
{/* Header */} @@ -273,6 +331,13 @@ function App() {
+ + + + + + {/* Overview Tab */} + {activeTab === 'overview' && ( +
+ {/* User Info Card */} +
+
+
+ +
+
+

{stats?.username}

+
+ + {getRoleName(stats?.role)} +
+
+
+
+ + {/* Stats Grid */} +
+ {/* Servers */} +
+
+
+ +
+
+

Всего серверов

+

{stats?.total_servers || 0}

+
+
+
+
+ Мои серверы: + {stats?.owned_servers?.length || 0} +
+
+ Доступные: + {stats?.accessible_servers?.length || 0} +
+
+
+ + {/* Tickets */} +
+
+
+ +
+
+

Мои тикеты

+

{stats?.tickets?.total || 0}

+
+
+
+
+ На рассмотрении: + {stats?.tickets?.pending || 0} +
+
+ В работе: + {stats?.tickets?.in_progress || 0} +
+
+ Закрыто: + {stats?.tickets?.closed || 0} +
+
+
+ + {/* Role Info */} +
+
+
+ +
+
+

Ваша роль

+

{getRoleName(stats?.role)}

+
+
+
+ {stats?.role === 'admin' && 'Полный доступ ко всем функциям панели'} + {stats?.role === 'support' && 'Доступ к системе тикетов и поддержке'} + {stats?.role === 'user' && 'Доступ к своим серверам и тикетам'} +
+
+
+ + {/* Servers List */} + {stats?.owned_servers?.length > 0 && ( +
+

Мои серверы

+
+ {stats.owned_servers.map((server) => ( +
+
+ +
+

{server.displayName}

+

{server.name}

+
+
+
+ ))} +
+
+ )} +
+ )} + + {/* Username Tab */} + {activeTab === 'username' && ( +
+

Изменить имя пользователя

+
+
+ + +
+ +
+ + setUsernameForm({ ...usernameForm, new_username: e.target.value })} + placeholder="Введите новое имя" + className={`w-full ${theme.input} ${theme.border} border rounded-xl px-4 py-3 ${theme.text} focus:outline-none focus:ring-2 focus:ring-blue-500 transition`} + /> +

+ Минимум 3 символа +

+
+ +
+ +
+ setUsernameForm({ ...usernameForm, password: e.target.value })} + placeholder="Введите текущий пароль" + className={`w-full ${theme.input} ${theme.border} border rounded-xl px-4 py-3 pr-12 ${theme.text} focus:outline-none focus:ring-2 focus:ring-blue-500 transition`} + /> + +
+
+ +
+

+ ⚠️ После изменения имени пользователя вы будете автоматически перелогинены с новым именем. +

+
+ + +
+
+ )} + + {/* Password Tab */} + {activeTab === 'password' && ( +
+

Изменить пароль

+
+
+ +
+ setPasswordForm({ ...passwordForm, old_password: e.target.value })} + placeholder="Введите текущий пароль" + className={`w-full ${theme.input} ${theme.border} border rounded-xl px-4 py-3 pr-12 ${theme.text} focus:outline-none focus:ring-2 focus:ring-blue-500 transition`} + /> + +
+
+ +
+ +
+ setPasswordForm({ ...passwordForm, new_password: e.target.value })} + placeholder="Введите новый пароль" + className={`w-full ${theme.input} ${theme.border} border rounded-xl px-4 py-3 pr-12 ${theme.text} focus:outline-none focus:ring-2 focus:ring-blue-500 transition`} + /> + +
+

+ Минимум 6 символов +

+
+ +
+ + setPasswordForm({ ...passwordForm, confirm_password: e.target.value })} + placeholder="Повторите новый пароль" + className={`w-full ${theme.input} ${theme.border} border rounded-xl px-4 py-3 ${theme.text} focus:outline-none focus:ring-2 focus:ring-blue-500 transition`} + /> +
+ +
+

+ ⚠️ После изменения пароля используйте новый пароль для входа в систему. +

+
+ + +
+
+ )} + + + ); +} diff --git a/ГОТОВО.md b/ГОТОВО.md index 52e9f4c..a8d0b8b 100644 --- a/ГОТОВО.md +++ b/ГОТОВО.md @@ -7,7 +7,7 @@ - **Новый**: Sofa12345 / arkonsad123 ### 2. Добавлена система тикетов 🎫 -- Кнопка "Тикеты" в header рядом с "Пользователи" +- Кнопка "Тикеты" в header - Создание тикетов с темой и описанием - Чат для общения в тикете - Три статуса: @@ -21,7 +21,16 @@ - Возможность отвечать на тикеты - Отдельный бейдж в интерфейсе -### 4. Улучшено управление пользователями +### 4. Добавлен личный кабинет 👤 +- Кнопка "Личный кабинет" в header рядом с "Тикеты" +- Три вкладки: + - 📊 Обзор - статистика профиля + - 👤 Имя пользователя - изменение имени + - 🔒 Пароль - изменение пароля +- Статистика по серверам и тикетам +- Список своих серверов + +### 5. Улучшено управление пользователями - Выпадающий список для выбора роли - Три роли: Пользователь, Тех. поддержка, Администратор - Цветные индикаторы ролей @@ -80,6 +89,9 @@ http://localhost:3000 - ✅ Создание тикетов - ✅ Общение в своих тикетах - ✅ Смена темы интерфейса +- ✅ Личный кабинет с статистикой +- ✅ Изменение имени пользователя +- ✅ Изменение пароля ### Для тех. поддержки - ✅ Все возможности пользователя @@ -110,6 +122,7 @@ MC Panel/ │ ├── themes.js # Конфигурация тем │ └── components/ │ ├── Auth.jsx # Авторизация +│ ├── Profile.jsx # Личный кабинет │ ├── Tickets.jsx # Список тикетов │ ├── TicketChat.jsx # Чат тикета │ ├── CreateTicketModal.jsx # Создание тикета @@ -121,6 +134,7 @@ MC Panel/ │ └── Документация/ ├── ГОТОВО.md # Этот файл + ├── PROFILE_SYSTEM.md # Документация личного кабинета ├── TICKETS_SYSTEM.md # Документация системы тикетов ├── CHANGELOG.md # История изменений └── БЫСТРЫЙ_СТАРТ.md # Быстрый старт @@ -160,6 +174,7 @@ MC Panel/ - ✅ Система пользователей - ✅ Система тикетов - ✅ Роль тех. поддержки +- ✅ Личный кабинет - ✅ 5 тем оформления - ✅ Современный интерфейс diff --git a/ЛИЧНЫЙ_КАБИНЕТ_ГОТОВ.md b/ЛИЧНЫЙ_КАБИНЕТ_ГОТОВ.md new file mode 100644 index 0000000..5b7ab5e --- /dev/null +++ b/ЛИЧНЫЙ_КАБИНЕТ_ГОТОВ.md @@ -0,0 +1,183 @@ +# ✅ Личный кабинет готов! + +## 🎉 Что добавлено + +### Кнопка "Личный кабинет" +Расположена в header рядом с кнопкой "Тикеты". Доступна всем пользователям. + +### Три вкладки + +#### 1. 📊 Обзор +**Информация о пользователе:** +- Имя пользователя +- Роль с цветным бейджем +- Аватар + +**Статистика:** +- 🖥️ **Серверы**: всего, мои, доступные +- 🎫 **Тикеты**: всего, на рассмотрении, в работе, закрыто +- 🛡️ **Роль**: название и описание прав + +**Список серверов:** +- Все серверы пользователя +- Название и ID +- Красивые карточки + +#### 2. 👤 Имя пользователя +**Возможности:** +- Просмотр текущего имени +- Ввод нового имени (минимум 3 символа) +- Подтверждение паролем +- Автоматический перелогин + +**Что обновляется:** +- Владельцы серверов +- Доступы к серверам +- JWT токен + +#### 3. 🔒 Пароль +**Возможности:** +- Ввод текущего пароля +- Ввод нового пароля (минимум 6 символов) +- Подтверждение нового пароля +- Показ/скрытие паролей (иконка глаза) + +**Безопасность:** +- Проверка текущего пароля +- Проверка совпадения новых паролей +- Хеширование (bcrypt) + +## 🚀 Как использовать + +### Открыть личный кабинет +1. Войдите в панель +2. Нажмите кнопку "Личный кабинет" в header +3. Откроется страница с вкладками + +### Посмотреть статистику +1. Откройте вкладку "Обзор" +2. Посмотрите информацию о профиле +3. Посмотрите статистику +4. Посмотрите список серверов + +### Изменить имя пользователя +1. Откройте вкладку "Имя пользователя" +2. Введите новое имя (минимум 3 символа) +3. Введите текущий пароль +4. Нажмите "Изменить имя пользователя" +5. Вы будете автоматически перелогинены + +⚠️ **Важно**: После изменения имени обновятся все серверы и доступы. + +### Изменить пароль +1. Откройте вкладку "Пароль" +2. Введите текущий пароль +3. Введите новый пароль (минимум 6 символов) +4. Подтвердите новый пароль +5. Нажмите "Изменить пароль" + +⚠️ **Важно**: После изменения пароля используйте новый пароль для входа. + +## 🎨 Дизайн + +### Современный интерфейс +- Вкладки с плавными переходами +- Цветные карточки статистики +- Иконки для каждого раздела +- Адаптивный дизайн + +### Формы +- Валидация полей +- Показ/скрытие паролей +- Предупреждения +- Индикация загрузки + +### Цветовые схемы +- Работает со всеми 5 темами +- Градиентный логотип +- Цветные бейджи ролей + +## 📋 API Endpoints + +### PUT /api/profile/username +Изменить имя пользователя + +```bash +curl -X PUT http://localhost:8000/api/profile/username \ + -H "Authorization: Bearer YOUR_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "new_username": "NewUsername", + "password": "current_password" + }' +``` + +### PUT /api/profile/password +Изменить пароль + +```bash +curl -X PUT http://localhost:8000/api/profile/password \ + -H "Authorization: Bearer YOUR_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "old_password": "old_password", + "new_password": "new_password" + }' +``` + +### GET /api/profile/stats +Получить статистику профиля + +```bash +curl -X GET http://localhost:8000/api/profile/stats \ + -H "Authorization: Bearer YOUR_TOKEN" +``` + +## 🔐 Безопасность + +### Изменение имени +1. ✅ Проверка пароля +2. ✅ Проверка уникальности +3. ✅ Обновление владельцев серверов +4. ✅ Обновление доступов +5. ✅ Новый JWT токен + +### Изменение пароля +1. ✅ Проверка текущего пароля +2. ✅ Проверка длины (минимум 6 символов) +3. ✅ Хеширование (bcrypt) + +## ✅ Готово! + +Личный кабинет полностью интегрирован в MC Panel. Все пользователи могут: +- 📊 Просматривать статистику +- 👤 Изменять имя пользователя +- 🔒 Изменять пароль +- 🖥️ Видеть свои серверы +- 🎫 Видеть статистику по тикетам + +### Тестирование + +1. **Войдите в панель** + - Логин: Sofa12345 + - Пароль: arkonsad123 + +2. **Откройте личный кабинет** + - Нажмите кнопку "Личный кабинет" + +3. **Посмотрите статистику** + - Вкладка "Обзор" + +4. **Измените имя (опционально)** + - Вкладка "Имя пользователя" + - Введите новое имя и пароль + +5. **Измените пароль (опционально)** + - Вкладка "Пароль" + - Введите старый и новый пароли + +## 🎯 Что дальше? + +Система личного кабинета готова к использованию. Теперь пользователи могут полностью управлять своим профилем! + +**Наслаждайтесь! 🚀**