Added Daemon system and fixed interface
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-01-16 18:56:21 +06:00
parent fbfddf3c7a
commit d188cec1f0
24 changed files with 1974 additions and 4985 deletions

View File

@@ -332,7 +332,7 @@ async def register(data: dict):
save_users(users)
access_token = create_access_token(data={"sub": username})
access_token = create_access_token(data={"sub": username, "role": role})
return {
"access_token": access_token,
"token_type": "bearer",
@@ -353,7 +353,7 @@ async def login(data: dict):
if not verify_password(password, user["password"]):
raise HTTPException(401, "Неверное имя пользователя или пароль")
access_token = create_access_token(data={"sub": username})
access_token = create_access_token(data={"sub": username, "role": user["role"]})
return {
"access_token": access_token,
"token_type": "bearer",
@@ -838,12 +838,12 @@ 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)
is_admin_or_owner = user.get("role") in ["owner", "admin"]
for server_dir in SERVERS_DIR.iterdir():
if server_dir.is_dir():
# Проверка доступа: владелец/админ видят всё, остальные только свои
if not can_view_all and server_dir.name not in user.get("servers", []):
if not is_admin_or_owner and server_dir.name not in user.get("servers", []):
continue
config = load_server_config(server_dir.name)
@@ -859,9 +859,14 @@ async def get_servers(user: dict = Depends(get_current_user)):
servers.append({
"name": server_dir.name,
"displayName": config.get("displayName", server_dir.name),
"status": "running" if is_running else "stopped"
"status": "running" if is_running else "stopped",
"owner": config.get("owner", "unknown")
})
print(f"Найдено серверов для {user['username']} ({user.get('role', 'user')}): {len(servers)}")
print(f"[DEBUG] User: {user['username']} (role: {user.get('role', 'user')})")
print(f"[DEBUG] Is admin/owner: {is_admin_or_owner}")
print(f"[DEBUG] Servers found: {len(servers)}")
except Exception as e:
print(f"Ошибка загрузки серверов: {e}")
return servers
@@ -869,34 +874,84 @@ async def get_servers(user: dict = Depends(get_current_user)):
@app.post("/api/servers/create")
async def create_server(data: dict, user: dict = Depends(get_current_user)):
server_name = data.get("name", "").strip()
daemon_id = data.get("daemonId", "local")
if not server_name or not server_name.replace("_", "").replace("-", "").isalnum():
raise HTTPException(400, "Недопустимое имя сервера")
server_path = SERVERS_DIR / server_name
if server_path.exists():
raise HTTPException(400, "Сервер с таким именем уже существует")
# Если создаем на демоне
if daemon_id != "local":
# Загружаем демоны
from daemons import load_daemons
daemons = load_daemons()
if daemon_id not in daemons:
raise HTTPException(404, "Демон не найден")
daemon = daemons[daemon_id]
# Отправляем запрос на создание сервера на демоне
url = f"http://{daemon['address']}:{daemon['port']}/api/servers/create"
headers = {"Authorization": f"Bearer {daemon['key']}"}
try:
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.post(url, json={
"name": server_name,
"displayName": data.get("displayName", server_name),
"startCommand": data.get("startCommand", "java -Xmx2G -Xms1G -jar server.jar nogui"),
"owner": user["username"]
}, headers=headers)
if response.status_code != 200:
raise HTTPException(400, f"Ошибка создания сервера на демоне: {response.text}")
except httpx.RequestError as e:
raise HTTPException(400, f"Ошибка подключения к демону: {str(e)}")
# Сохраняем информацию о сервере локально
config = {
"name": server_name,
"displayName": data.get("displayName", server_name),
"startCommand": data.get("startCommand", "java -Xmx2G -Xms1G -jar server.jar nogui"),
"owner": user["username"],
"daemonId": daemon_id,
"daemonName": daemon["name"]
}
# Создаем локальную запись о сервере
server_path = SERVERS_DIR / f"{daemon_id}_{server_name}"
server_path.mkdir(parents=True, exist_ok=True)
save_server_config(f"{daemon_id}_{server_name}", config)
else:
# Создаем локально
server_path = SERVERS_DIR / server_name
if server_path.exists():
raise HTTPException(400, "Сервер с таким именем уже существует")
server_path.mkdir(parents=True)
config = {
"name": server_name,
"displayName": data.get("displayName", server_name),
"startCommand": data.get("startCommand", "java -Xmx2G -Xms1G -jar server.jar nogui"),
"owner": user["username"],
"daemonId": "local"
}
save_server_config(server_name, config)
server_path.mkdir(parents=True)
config = {
"name": server_name,
"displayName": data.get("displayName", server_name),
"startCommand": data.get("startCommand", "java -Xmx2G -Xms1G -jar server.jar nogui"),
"owner": user["username"] # Сохраняем владельца
}
save_server_config(server_name, config)
# Если пользователь не админ, автоматически выдаем ему доступ
if user["role"] != "admin":
# Если пользователь не админ/owner, автоматически выдаем ему доступ
if user["role"] not in ["admin", "owner"]:
users = load_users()
if user["username"] in users:
if "servers" not in users[user["username"]]:
users[user["username"]]["servers"] = []
if server_name not in users[user["username"]]["servers"]:
users[user["username"]]["servers"].append(server_name)
server_key = f"{daemon_id}_{server_name}" if daemon_id != "local" else server_name
if server_key not in users[user["username"]]["servers"]:
users[user["username"]]["servers"].append(server_key)
save_users(users)
return {"message": "Сервер создан", "name": server_name}
return {"message": "Сервер создан", "name": server_name, "daemonId": daemon_id}
@app.get("/api/servers/{server_name}/config")
async def get_server_config(server_name: str, user: dict = Depends(get_current_user)):
@@ -1869,6 +1924,16 @@ async def update_user_permissions(username: str, perms: PermissionsUpdate, curre
return {"message": f"Права пользователя {username} обновлены", "permissions": perms.permissions}
# ============================================
# API для управления демонами
# ============================================
from daemons import router as daemons_router
# Подключаем роутер демонов
app.include_router(daemons_router)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)