Added Role Owner and new UI for Owner
This commit is contained in:
534
backend/main.py
534
backend/main.py
@@ -2,6 +2,7 @@ from fastapi import FastAPI, WebSocket, UploadFile, File, HTTPException, Depends
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import FileResponse, RedirectResponse
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
from pydantic import BaseModel
|
||||
import asyncio
|
||||
import subprocess
|
||||
import psutil
|
||||
@@ -160,8 +161,15 @@ def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(securit
|
||||
raise HTTPException(status_code=401, detail="Неверный токен")
|
||||
|
||||
def check_server_access(user: dict, server_name: str):
|
||||
# Владелец имеет доступ ко всем серверам
|
||||
if user["role"] == "owner":
|
||||
return True
|
||||
# Админы имеют доступ ко всем серверам
|
||||
if user["role"] == "admin":
|
||||
return True
|
||||
# Проверяем права на серверы
|
||||
if not user.get("permissions", {}).get("servers", True):
|
||||
return False
|
||||
return server_name in user.get("servers", [])
|
||||
|
||||
# API для аутентификации
|
||||
@@ -301,13 +309,25 @@ async def register(data: dict):
|
||||
if username in users:
|
||||
raise HTTPException(400, "Пользователь уже существует")
|
||||
|
||||
role = "admin" if len(users) == 0 else "user"
|
||||
# Первый пользователь становится владельцем
|
||||
role = "owner" if len(users) == 0 else "user"
|
||||
|
||||
users[username] = {
|
||||
"username": username,
|
||||
"password": get_password_hash(password),
|
||||
"role": role,
|
||||
"servers": []
|
||||
"servers": [],
|
||||
"permissions": {
|
||||
"servers": True,
|
||||
"tickets": True,
|
||||
"users": True if role == "owner" else False,
|
||||
"files": True
|
||||
} if role == "owner" else {
|
||||
"servers": True,
|
||||
"tickets": True,
|
||||
"users": False,
|
||||
"files": True
|
||||
}
|
||||
}
|
||||
|
||||
save_users(users)
|
||||
@@ -343,23 +363,43 @@ async def login(data: dict):
|
||||
|
||||
@app.get("/api/auth/me")
|
||||
async def get_me(user: dict = Depends(get_current_user)):
|
||||
users = load_users()
|
||||
user_data = users.get(user["username"], {})
|
||||
|
||||
# Если у пользователя нет прав, создаем дефолтные
|
||||
if "permissions" not in user_data:
|
||||
user_data["permissions"] = {
|
||||
"servers": True,
|
||||
"tickets": True,
|
||||
"users": user_data["role"] in ["owner", "admin"],
|
||||
"files": True
|
||||
}
|
||||
users[user["username"]] = user_data
|
||||
save_users(users)
|
||||
|
||||
return {
|
||||
"username": user["username"],
|
||||
"role": user["role"],
|
||||
"servers": user.get("servers", [])
|
||||
"servers": user.get("servers", []),
|
||||
"permissions": user_data.get("permissions", {})
|
||||
}
|
||||
|
||||
# API для управления пользователями
|
||||
@app.get("/api/users")
|
||||
async def get_users(user: dict = Depends(get_current_user)):
|
||||
# Админы видят всех пользователей
|
||||
# Обычные пользователи тоже видят всех (для управления доступом к своим серверам)
|
||||
# Владелец, админы и тех. поддержка видят всех пользователей
|
||||
users = load_users()
|
||||
return [
|
||||
{
|
||||
"username": u["username"],
|
||||
"role": u["role"],
|
||||
"servers": u.get("servers", [])
|
||||
"servers": u.get("servers", []),
|
||||
"permissions": u.get("permissions", {
|
||||
"servers": True,
|
||||
"tickets": True,
|
||||
"users": u["role"] in ["owner", "admin"],
|
||||
"files": True
|
||||
})
|
||||
}
|
||||
for u in users.values()
|
||||
]
|
||||
@@ -394,8 +434,9 @@ async def update_user_servers(username: str, data: dict, user: dict = Depends(ge
|
||||
|
||||
@app.delete("/api/users/{username}")
|
||||
async def delete_user(username: str, user: dict = Depends(get_current_user)):
|
||||
if user["role"] != "admin":
|
||||
raise HTTPException(403, "Доступ запрещен")
|
||||
# Только владелец может удалять пользователей
|
||||
if user["role"] != "owner":
|
||||
raise HTTPException(403, "Только владелец может удалять пользователей")
|
||||
|
||||
if username == user["username"]:
|
||||
raise HTTPException(400, "Нельзя удалить самого себя")
|
||||
@@ -404,6 +445,10 @@ async def delete_user(username: str, user: dict = Depends(get_current_user)):
|
||||
if username not in users:
|
||||
raise HTTPException(404, "Пользователь не найден")
|
||||
|
||||
# Нельзя удалить другого владельца
|
||||
if users[username]["role"] == "owner":
|
||||
raise HTTPException(400, "Нельзя удалить владельца")
|
||||
|
||||
del users[username]
|
||||
save_users(users)
|
||||
|
||||
@@ -411,8 +456,9 @@ async def delete_user(username: str, user: dict = Depends(get_current_user)):
|
||||
|
||||
@app.put("/api/users/{username}/role")
|
||||
async def update_user_role(username: str, data: dict, user: dict = Depends(get_current_user)):
|
||||
if user["role"] != "admin":
|
||||
raise HTTPException(403, "Доступ запрещен")
|
||||
# Только владелец может изменять роли
|
||||
if user["role"] != "owner":
|
||||
raise HTTPException(403, "Только владелец может изменять роли")
|
||||
|
||||
if username == user["username"]:
|
||||
raise HTTPException(400, "Нельзя изменить свою роль")
|
||||
@@ -425,11 +471,187 @@ async def update_user_role(username: str, data: dict, user: dict = Depends(get_c
|
||||
if new_role not in ["admin", "user", "support", "banned"]:
|
||||
raise HTTPException(400, "Неверная роль")
|
||||
|
||||
# Нельзя назначить роль owner
|
||||
if new_role == "owner":
|
||||
raise HTTPException(400, "Нельзя назначить роль владельца")
|
||||
|
||||
users[username]["role"] = new_role
|
||||
save_users(users)
|
||||
|
||||
return {"message": "Роль обновлена"}
|
||||
|
||||
@app.get("/api/users/{username}/permissions")
|
||||
async def get_user_permissions(username: str, user: dict = Depends(get_current_user)):
|
||||
"""Получить права пользователя"""
|
||||
# Только владелец и админы могут просматривать права
|
||||
if user["role"] not in ["owner", "admin"]:
|
||||
raise HTTPException(403, "Недостаточно прав")
|
||||
|
||||
users = load_users()
|
||||
if username not in users:
|
||||
raise HTTPException(404, "Пользователь не найден")
|
||||
|
||||
target_user = users[username]
|
||||
|
||||
# Если у пользователя нет прав, создаем дефолтные
|
||||
if "permissions" not in target_user:
|
||||
target_user["permissions"] = {
|
||||
"servers": True,
|
||||
"tickets": True,
|
||||
"users": target_user["role"] in ["owner", "admin"],
|
||||
"files": True
|
||||
}
|
||||
users[username] = target_user
|
||||
save_users(users)
|
||||
|
||||
return {
|
||||
"username": username,
|
||||
"role": target_user["role"],
|
||||
"permissions": target_user["permissions"]
|
||||
}
|
||||
|
||||
@app.put("/api/users/{username}/permissions")
|
||||
async def update_user_permissions(username: str, data: dict, user: dict = Depends(get_current_user)):
|
||||
"""Обновить права пользователя (только для владельца)"""
|
||||
if user["role"] != "owner":
|
||||
raise HTTPException(403, "Только владелец может изменять права")
|
||||
|
||||
if username == user["username"]:
|
||||
raise HTTPException(400, "Нельзя изменить свои права")
|
||||
|
||||
users = load_users()
|
||||
if username not in users:
|
||||
raise HTTPException(404, "Пользователь не найден")
|
||||
|
||||
target_user = users[username]
|
||||
|
||||
# Нельзя изменять права владельца
|
||||
if target_user["role"] == "owner":
|
||||
raise HTTPException(400, "Нельзя изменять права владельца")
|
||||
|
||||
permissions = data.get("permissions", {})
|
||||
|
||||
# Валидация прав
|
||||
valid_permissions = ["servers", "tickets", "users", "files"]
|
||||
for perm in permissions:
|
||||
if perm not in valid_permissions:
|
||||
raise HTTPException(400, f"Неверное право: {perm}")
|
||||
|
||||
# Обновляем права
|
||||
if "permissions" not in target_user:
|
||||
target_user["permissions"] = {
|
||||
"servers": True,
|
||||
"tickets": True,
|
||||
"users": False,
|
||||
"files": True
|
||||
}
|
||||
|
||||
target_user["permissions"].update(permissions)
|
||||
users[username] = target_user
|
||||
save_users(users)
|
||||
|
||||
return {
|
||||
"message": "Права обновлены",
|
||||
"permissions": target_user["permissions"]
|
||||
}
|
||||
|
||||
@app.post("/api/users/{username}/revoke-access")
|
||||
async def revoke_user_access(username: str, data: dict, user: dict = Depends(get_current_user)):
|
||||
"""Забрать доступ к определенным ресурсам (только для владельца)"""
|
||||
if user["role"] != "owner":
|
||||
raise HTTPException(403, "Только владелец может забирать доступ")
|
||||
|
||||
users = load_users()
|
||||
if username not in users:
|
||||
raise HTTPException(404, "Пользователь не найден")
|
||||
|
||||
target_user = users[username]
|
||||
|
||||
# Нельзя забирать доступ у владельца
|
||||
if target_user["role"] == "owner":
|
||||
raise HTTPException(400, "Нельзя забирать доступ у владельца")
|
||||
|
||||
resource_type = data.get("type") # "servers", "tickets", "all"
|
||||
|
||||
if resource_type == "servers":
|
||||
# Забираем доступ ко всем серверам
|
||||
target_user["servers"] = []
|
||||
if "permissions" in target_user:
|
||||
target_user["permissions"]["servers"] = False
|
||||
elif resource_type == "tickets":
|
||||
# Забираем доступ к тикетам
|
||||
if "permissions" in target_user:
|
||||
target_user["permissions"]["tickets"] = False
|
||||
elif resource_type == "files":
|
||||
# Забираем доступ к файлам
|
||||
if "permissions" in target_user:
|
||||
target_user["permissions"]["files"] = False
|
||||
elif resource_type == "all":
|
||||
# Забираем весь доступ
|
||||
target_user["servers"] = []
|
||||
if "permissions" in target_user:
|
||||
target_user["permissions"] = {
|
||||
"servers": False,
|
||||
"tickets": False,
|
||||
"users": False,
|
||||
"files": False
|
||||
}
|
||||
else:
|
||||
raise HTTPException(400, "Неверный тип ресурса")
|
||||
|
||||
users[username] = target_user
|
||||
save_users(users)
|
||||
|
||||
return {
|
||||
"message": f"Доступ к {resource_type} забран",
|
||||
"permissions": target_user.get("permissions", {})
|
||||
}
|
||||
|
||||
@app.post("/api/users/{username}/grant-access")
|
||||
async def grant_user_access(username: str, data: dict, user: dict = Depends(get_current_user)):
|
||||
"""Выдать доступ к определенным ресурсам (только для владельца)"""
|
||||
if user["role"] != "owner":
|
||||
raise HTTPException(403, "Только владелец может выдавать доступ")
|
||||
|
||||
users = load_users()
|
||||
if username not in users:
|
||||
raise HTTPException(404, "Пользователь не найден")
|
||||
|
||||
target_user = users[username]
|
||||
resource_type = data.get("type") # "servers", "tickets", "files"
|
||||
|
||||
if "permissions" not in target_user:
|
||||
target_user["permissions"] = {
|
||||
"servers": False,
|
||||
"tickets": False,
|
||||
"users": False,
|
||||
"files": False
|
||||
}
|
||||
|
||||
if resource_type == "servers":
|
||||
target_user["permissions"]["servers"] = True
|
||||
elif resource_type == "tickets":
|
||||
target_user["permissions"]["tickets"] = True
|
||||
elif resource_type == "files":
|
||||
target_user["permissions"]["files"] = True
|
||||
elif resource_type == "all":
|
||||
target_user["permissions"] = {
|
||||
"servers": True,
|
||||
"tickets": True,
|
||||
"users": target_user["role"] in ["admin"],
|
||||
"files": True
|
||||
}
|
||||
else:
|
||||
raise HTTPException(400, "Неверный тип ресурса")
|
||||
|
||||
users[username] = target_user
|
||||
save_users(users)
|
||||
|
||||
return {
|
||||
"message": f"Доступ к {resource_type} выдан",
|
||||
"permissions": target_user["permissions"]
|
||||
}
|
||||
|
||||
# API для личного кабинета
|
||||
@app.put("/api/profile/username")
|
||||
async def update_username(data: dict, user: dict = Depends(get_current_user)):
|
||||
@@ -613,9 +835,13 @@ async def get_user_profile_stats(username: str, user: dict = Depends(get_current
|
||||
async def get_servers(user: dict = Depends(get_current_user)):
|
||||
servers = []
|
||||
try:
|
||||
# Владелец и администратор видят все серверы
|
||||
can_view_all = user.get("role") in ["owner", "admin"] or user.get("permissions", {}).get("view_all_resources", False)
|
||||
|
||||
for server_dir in SERVERS_DIR.iterdir():
|
||||
if server_dir.is_dir():
|
||||
if user["role"] != "admin" and server_dir.name not in user.get("servers", []):
|
||||
# Проверка доступа: владелец/админ видят всё, остальные только свои
|
||||
if not can_view_all and server_dir.name not in user.get("servers", []):
|
||||
continue
|
||||
|
||||
config = load_server_config(server_dir.name)
|
||||
@@ -633,7 +859,7 @@ async def get_servers(user: dict = Depends(get_current_user)):
|
||||
"displayName": config.get("displayName", server_dir.name),
|
||||
"status": "running" if is_running else "stopped"
|
||||
})
|
||||
print(f"Найдено серверов для {user['username']}: {len(servers)}")
|
||||
print(f"Найдено серверов для {user['username']} ({user.get('role', 'user')}): {len(servers)}")
|
||||
except Exception as e:
|
||||
print(f"Ошибка загрузки серверов: {e}")
|
||||
return servers
|
||||
@@ -1243,10 +1469,14 @@ async def rename_file(server_name: str, old_path: str, new_name: str, user: dict
|
||||
@app.get("/api/tickets")
|
||||
async def get_tickets(user: dict = Depends(get_current_user)):
|
||||
"""Получить список тикетов"""
|
||||
# Проверяем права на тикеты
|
||||
if not user.get("permissions", {}).get("tickets", True):
|
||||
raise HTTPException(403, "Нет доступа к тикетам")
|
||||
|
||||
tickets = load_tickets()
|
||||
|
||||
# Админы и тех. поддержка видят все тикеты
|
||||
if user["role"] in ["admin", "support"]:
|
||||
# Владелец, админы и тех. поддержка видят все тикеты
|
||||
if user["role"] in ["owner", "admin", "support"]:
|
||||
return list(tickets.values())
|
||||
|
||||
# Обычные пользователи видят только свои тикеты
|
||||
@@ -1256,6 +1486,10 @@ async def get_tickets(user: dict = Depends(get_current_user)):
|
||||
@app.post("/api/tickets/create")
|
||||
async def create_ticket(data: dict, user: dict = Depends(get_current_user)):
|
||||
"""Создать новый тикет"""
|
||||
# Проверяем права на тикеты
|
||||
if not user.get("permissions", {}).get("tickets", True):
|
||||
raise HTTPException(403, "Нет доступа к тикетам")
|
||||
|
||||
tickets = load_tickets()
|
||||
|
||||
# Генерируем ID тикета
|
||||
@@ -1286,6 +1520,10 @@ async def create_ticket(data: dict, user: dict = Depends(get_current_user)):
|
||||
@app.get("/api/tickets/{ticket_id}")
|
||||
async def get_ticket(ticket_id: str, user: dict = Depends(get_current_user)):
|
||||
"""Получить тикет по ID"""
|
||||
# Проверяем права на тикеты
|
||||
if not user.get("permissions", {}).get("tickets", True):
|
||||
raise HTTPException(403, "Нет доступа к тикетам")
|
||||
|
||||
tickets = load_tickets()
|
||||
|
||||
if ticket_id not in tickets:
|
||||
@@ -1294,7 +1532,7 @@ async def get_ticket(ticket_id: str, user: dict = Depends(get_current_user)):
|
||||
ticket = tickets[ticket_id]
|
||||
|
||||
# Проверка доступа
|
||||
if user["role"] not in ["admin", "support"] and ticket["author"] != user["username"]:
|
||||
if user["role"] not in ["owner", "admin", "support"] and ticket["author"] != user["username"]:
|
||||
raise HTTPException(403, "Нет доступа к этому тикету")
|
||||
|
||||
return ticket
|
||||
@@ -1302,6 +1540,10 @@ async def get_ticket(ticket_id: str, user: dict = Depends(get_current_user)):
|
||||
@app.post("/api/tickets/{ticket_id}/message")
|
||||
async def add_ticket_message(ticket_id: str, data: dict, user: dict = Depends(get_current_user)):
|
||||
"""Добавить сообщение в тикет"""
|
||||
# Проверяем права на тикеты
|
||||
if not user.get("permissions", {}).get("tickets", True):
|
||||
raise HTTPException(403, "Нет доступа к тикетам")
|
||||
|
||||
tickets = load_tickets()
|
||||
|
||||
if ticket_id not in tickets:
|
||||
@@ -1310,7 +1552,7 @@ async def add_ticket_message(ticket_id: str, data: dict, user: dict = Depends(ge
|
||||
ticket = tickets[ticket_id]
|
||||
|
||||
# Проверка доступа
|
||||
if user["role"] not in ["admin", "support"] and ticket["author"] != user["username"]:
|
||||
if user["role"] not in ["owner", "admin", "support"] and ticket["author"] != user["username"]:
|
||||
raise HTTPException(403, "Нет доступа к этому тикету")
|
||||
|
||||
message = {
|
||||
@@ -1329,10 +1571,14 @@ async def add_ticket_message(ticket_id: str, data: dict, user: dict = Depends(ge
|
||||
|
||||
@app.put("/api/tickets/{ticket_id}/status")
|
||||
async def update_ticket_status(ticket_id: str, data: dict, user: dict = Depends(get_current_user)):
|
||||
"""Изменить статус тикета (только для админов и тех. поддержки)"""
|
||||
if user["role"] not in ["admin", "support"]:
|
||||
"""Изменить статус тикета (только для владельца, админов и тех. поддержки)"""
|
||||
if user["role"] not in ["owner", "admin", "support"]:
|
||||
raise HTTPException(403, "Недостаточно прав")
|
||||
|
||||
# Проверяем права на тикеты
|
||||
if not user.get("permissions", {}).get("tickets", True):
|
||||
raise HTTPException(403, "Нет доступа к тикетам")
|
||||
|
||||
tickets = load_tickets()
|
||||
|
||||
if ticket_id not in tickets:
|
||||
@@ -1366,6 +1612,258 @@ async def update_ticket_status(ticket_id: str, data: dict, user: dict = Depends(
|
||||
|
||||
return {"message": "Статус обновлён", "ticket": ticket}
|
||||
|
||||
|
||||
# ============================================
|
||||
# УПРАВЛЕНИЕ ПОЛЬЗОВАТЕЛЯМИ (v1.1.0)
|
||||
# ============================================
|
||||
|
||||
# Загрузка пользователей
|
||||
def load_users_dict():
|
||||
users_file = Path("users.json")
|
||||
if not users_file.exists():
|
||||
return {}
|
||||
with open(users_file, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
def save_users_dict(users):
|
||||
with open("users.json", "w", encoding="utf-8") as f:
|
||||
json.dump(users, f, indent=2, ensure_ascii=False)
|
||||
|
||||
# Проверка прав
|
||||
def require_owner(current_user: dict):
|
||||
if current_user.get("role") != "owner":
|
||||
raise HTTPException(status_code=403, detail="Требуется роль владельца")
|
||||
|
||||
def require_admin_or_owner(current_user: dict):
|
||||
if current_user.get("role") not in ["owner", "admin"]:
|
||||
raise HTTPException(status_code=403, detail="Требуется роль администратора или владельца")
|
||||
|
||||
# 1. Получить список пользователей
|
||||
@app.get("/api/users")
|
||||
async def get_users(current_user: dict = Depends(get_current_user)):
|
||||
require_admin_or_owner(current_user)
|
||||
|
||||
users = load_users_dict()
|
||||
users_list = []
|
||||
for username, user_data in users.items():
|
||||
user_copy = user_data.copy()
|
||||
user_copy.pop("password", None)
|
||||
users_list.append(user_copy)
|
||||
|
||||
return users_list
|
||||
|
||||
# 2. Изменить роль пользователя
|
||||
class RoleChange(BaseModel):
|
||||
role: str
|
||||
|
||||
@app.put("/api/users/{username}/role")
|
||||
async def change_user_role(username: str, role_data: RoleChange, current_user: dict = Depends(get_current_user)):
|
||||
require_owner(current_user)
|
||||
|
||||
users = load_users_dict()
|
||||
|
||||
if username not in users:
|
||||
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||
|
||||
if username == current_user.get("username"):
|
||||
raise HTTPException(status_code=400, detail="Нельзя изменить свою роль")
|
||||
|
||||
valid_roles = ["owner", "admin", "support", "user", "banned"]
|
||||
if role_data.role not in valid_roles:
|
||||
raise HTTPException(status_code=400, detail=f"Неверная роль")
|
||||
|
||||
# Если назначается новый owner, текущий owner становится admin
|
||||
if role_data.role == "owner":
|
||||
for user in users.values():
|
||||
if user.get("role") == "owner":
|
||||
user["role"] = "admin"
|
||||
|
||||
old_role = users[username].get("role", "user")
|
||||
users[username]["role"] = role_data.role
|
||||
|
||||
# Обновляем права
|
||||
if role_data.role == "owner":
|
||||
users[username]["permissions"] = {
|
||||
"manage_users": True, "manage_roles": True, "manage_servers": True,
|
||||
"manage_tickets": True, "manage_files": True, "delete_users": True,
|
||||
"view_all_resources": True
|
||||
}
|
||||
elif role_data.role == "admin":
|
||||
users[username]["permissions"] = {
|
||||
"manage_users": True, "manage_roles": False, "manage_servers": True,
|
||||
"manage_tickets": True, "manage_files": True, "delete_users": False,
|
||||
"view_all_resources": True
|
||||
}
|
||||
elif role_data.role == "support":
|
||||
users[username]["permissions"] = {
|
||||
"manage_users": False, "manage_roles": False, "manage_servers": False,
|
||||
"manage_tickets": True, "manage_files": False, "delete_users": False,
|
||||
"view_all_resources": False
|
||||
}
|
||||
elif role_data.role == "banned":
|
||||
users[username]["permissions"] = {
|
||||
"manage_users": False, "manage_roles": False, "manage_servers": False,
|
||||
"manage_tickets": False, "manage_files": False, "delete_users": False,
|
||||
"view_all_resources": False
|
||||
}
|
||||
else: # user
|
||||
users[username]["permissions"] = {
|
||||
"manage_users": False, "manage_roles": False, "manage_servers": True,
|
||||
"manage_tickets": True, "manage_files": True, "delete_users": False,
|
||||
"view_all_resources": False
|
||||
}
|
||||
|
||||
save_users_dict(users)
|
||||
|
||||
return {"message": f"Роль изменена с {old_role} на {role_data.role}", "user": {"username": username, "role": role_data.role}}
|
||||
|
||||
# 3. Заблокировать пользователя
|
||||
class BanRequest(BaseModel):
|
||||
reason: str = "Заблокирован администратором"
|
||||
|
||||
@app.post("/api/users/{username}/ban")
|
||||
async def ban_user(username: str, ban_data: BanRequest, current_user: dict = Depends(get_current_user)):
|
||||
require_admin_or_owner(current_user)
|
||||
|
||||
users = load_users_dict()
|
||||
|
||||
if username not in users:
|
||||
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||
|
||||
if username == current_user.get("username"):
|
||||
raise HTTPException(status_code=400, detail="Нельзя заблокировать самого себя")
|
||||
|
||||
if users[username].get("role") == "owner":
|
||||
raise HTTPException(status_code=400, detail="Нельзя заблокировать владельца")
|
||||
|
||||
users[username]["role"] = "banned"
|
||||
users[username]["permissions"] = {
|
||||
"manage_users": False, "manage_roles": False, "manage_servers": False,
|
||||
"manage_tickets": False, "manage_files": False, "delete_users": False,
|
||||
"view_all_resources": False
|
||||
}
|
||||
users[username]["ban_reason"] = ban_data.reason
|
||||
|
||||
save_users_dict(users)
|
||||
|
||||
return {"message": f"Пользователь {username} заблокирован", "username": username, "reason": ban_data.reason}
|
||||
|
||||
# 4. Разблокировать пользователя
|
||||
@app.post("/api/users/{username}/unban")
|
||||
async def unban_user(username: str, current_user: dict = Depends(get_current_user)):
|
||||
require_admin_or_owner(current_user)
|
||||
|
||||
users = load_users_dict()
|
||||
|
||||
if username not in users:
|
||||
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||
|
||||
if users[username].get("role") != "banned":
|
||||
raise HTTPException(status_code=400, detail="Пользователь не заблокирован")
|
||||
|
||||
users[username]["role"] = "user"
|
||||
users[username]["permissions"] = {
|
||||
"manage_users": False, "manage_roles": False, "manage_servers": True,
|
||||
"manage_tickets": True, "manage_files": True, "delete_users": False,
|
||||
"view_all_resources": False
|
||||
}
|
||||
users[username].pop("ban_reason", None)
|
||||
|
||||
save_users_dict(users)
|
||||
|
||||
return {"message": f"Пользователь {username} разблокирован", "username": username}
|
||||
|
||||
# 5. Удалить пользователя
|
||||
@app.delete("/api/users/{username}")
|
||||
async def delete_user(username: str, current_user: dict = Depends(get_current_user)):
|
||||
require_owner(current_user)
|
||||
|
||||
users = load_users_dict()
|
||||
|
||||
if username not in users:
|
||||
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||
|
||||
if username == current_user.get("username"):
|
||||
raise HTTPException(status_code=400, detail="Нельзя удалить самого себя")
|
||||
|
||||
if users[username].get("role") == "owner":
|
||||
raise HTTPException(status_code=400, detail="Нельзя удалить владельца")
|
||||
|
||||
del users[username]
|
||||
save_users_dict(users)
|
||||
|
||||
return {"message": f"Пользователь {username} удалён", "username": username}
|
||||
|
||||
# 6. Выдать доступ к серверу
|
||||
class ServerAccess(BaseModel):
|
||||
server_name: str
|
||||
|
||||
@app.post("/api/users/{username}/access/servers")
|
||||
async def grant_server_access(username: str, access: ServerAccess, current_user: dict = Depends(get_current_user)):
|
||||
require_admin_or_owner(current_user)
|
||||
|
||||
users = load_users_dict()
|
||||
|
||||
if username not in users:
|
||||
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||
|
||||
if "resource_access" not in users[username]:
|
||||
users[username]["resource_access"] = {"servers": [], "tickets": [], "files": []}
|
||||
|
||||
if access.server_name not in users[username]["resource_access"]["servers"]:
|
||||
users[username]["resource_access"]["servers"].append(access.server_name)
|
||||
|
||||
# Также добавляем в старое поле servers для совместимости
|
||||
if "servers" not in users[username]:
|
||||
users[username]["servers"] = []
|
||||
if access.server_name not in users[username]["servers"]:
|
||||
users[username]["servers"].append(access.server_name)
|
||||
|
||||
save_users_dict(users)
|
||||
|
||||
return {"message": f"Доступ к серверу {access.server_name} выдан", "server": access.server_name, "user": username}
|
||||
|
||||
# 7. Забрать доступ к серверу
|
||||
@app.delete("/api/users/{username}/access/servers/{server_name}")
|
||||
async def revoke_server_access(username: str, server_name: str, current_user: dict = Depends(get_current_user)):
|
||||
require_admin_or_owner(current_user)
|
||||
|
||||
users = load_users_dict()
|
||||
|
||||
if username not in users:
|
||||
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||
|
||||
if "resource_access" in users[username] and "servers" in users[username]["resource_access"]:
|
||||
if server_name in users[username]["resource_access"]["servers"]:
|
||||
users[username]["resource_access"]["servers"].remove(server_name)
|
||||
|
||||
# Также удаляем из старого поля servers
|
||||
if "servers" in users[username] and server_name in users[username]["servers"]:
|
||||
users[username]["servers"].remove(server_name)
|
||||
|
||||
save_users_dict(users)
|
||||
|
||||
return {"message": f"Доступ к серверу {server_name} отозван", "server": server_name, "user": username}
|
||||
|
||||
# 8. Изменить права пользователя
|
||||
class PermissionsUpdate(BaseModel):
|
||||
permissions: dict
|
||||
|
||||
@app.put("/api/users/{username}/permissions")
|
||||
async def update_user_permissions(username: str, perms: PermissionsUpdate, current_user: dict = Depends(get_current_user)):
|
||||
require_owner(current_user)
|
||||
|
||||
users = load_users_dict()
|
||||
|
||||
if username not in users:
|
||||
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||
|
||||
users[username]["permissions"] = perms.permissions
|
||||
save_users_dict(users)
|
||||
|
||||
return {"message": f"Права пользователя {username} обновлены", "permissions": perms.permissions}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
|
||||
Reference in New Issue
Block a user