Add Notification and new mini desing

This commit is contained in:
2026-01-15 13:26:04 +06:00
parent 303d38f28e
commit 8edd7131a2
56 changed files with 3554 additions and 5197 deletions

View File

@@ -73,8 +73,8 @@ IS_WINDOWS = sys.platform == 'win32'
def init_users():
if not USERS_FILE.exists():
admin_user = {
"username": "Sofa12345",
"password": pwd_context.hash("arkonsad123"),
"username": "Root",
"password": pwd_context.hash("Admin"),
"role": "admin",
"servers": []
}
@@ -1005,23 +1005,88 @@ async def download_file(server_name: str, path: str, user: dict = Depends(get_cu
@app.post("/api/servers/{server_name}/files/upload")
async def upload_file(server_name: str, path: str, file: UploadFile = File(...), user: dict = Depends(get_current_user)):
print(f"Upload request: server={server_name}, path='{path}', filename='{file.filename}'")
if not check_server_access(user, server_name):
raise HTTPException(403, "Нет доступа к этому серверу")
server_path = SERVERS_DIR / server_name
target_path = server_path / path / file.filename
print(f"Target path: {target_path}")
print(f"Server path: {server_path}")
print(f"Path starts with server_path: {str(target_path).startswith(str(server_path))}")
if not str(target_path).startswith(str(server_path)):
raise HTTPException(400, "Недопустимый путь")
target_path.parent.mkdir(parents=True, exist_ok=True)
try:
target_path.parent.mkdir(parents=True, exist_ok=True)
print(f"Created directory: {target_path.parent}")
except Exception as e:
print(f"Error creating directory: {e}")
raise HTTPException(500, f"Ошибка создания директории: {str(e)}")
with open(target_path, "wb") as f:
content = await file.read()
f.write(content)
try:
with open(target_path, "wb") as f:
content = await file.read()
f.write(content)
print(f"File written successfully: {target_path}")
except Exception as e:
print(f"Error writing file: {e}")
raise HTTPException(500, f"Ошибка записи файла: {str(e)}")
return {"message": "Файл загружен"}
@app.post("/api/servers/{server_name}/files/create")
async def create_file_or_folder(server_name: str, data: dict, user: dict = Depends(get_current_user)):
"""Создать новый файл или папку"""
if not check_server_access(user, server_name):
raise HTTPException(403, "Нет доступа к этому серверу")
item_type = data.get("type") # "file" or "folder"
name = data.get("name", "").strip()
path = data.get("path", "") # Текущая папка
if not name:
raise HTTPException(400, "Имя не может быть пустым")
if item_type not in ["file", "folder"]:
raise HTTPException(400, "Тип должен быть 'file' или 'folder'")
server_path = SERVERS_DIR / server_name
# Формируем полный путь
if path:
full_path = server_path / path / name
else:
full_path = server_path / name
print(f"Creating {item_type}: {full_path}")
# Проверка безопасности
if not str(full_path).startswith(str(server_path)):
raise HTTPException(400, "Недопустимый путь")
try:
if item_type == "folder":
# Создаем папку
full_path.mkdir(parents=True, exist_ok=True)
# Создаем .gitkeep чтобы папка не была пустой
gitkeep = full_path / ".gitkeep"
gitkeep.touch()
print(f"Folder created: {full_path}")
else:
# Создаем файл
full_path.parent.mkdir(parents=True, exist_ok=True)
full_path.touch()
print(f"File created: {full_path}")
return {"message": f"{'Папка' if item_type == 'folder' else 'Файл'} создан(а)", "path": str(full_path)}
except Exception as e:
print(f"Error creating {item_type}: {e}")
raise HTTPException(500, f"Ошибка создания: {str(e)}")
@app.delete("/api/servers/{server_name}/files")
async def delete_file(server_name: str, path: str, user: dict = Depends(get_current_user)):
if not check_server_access(user, server_name):
@@ -1098,6 +1163,82 @@ async def rename_file(server_name: str, old_path: str, new_name: str, user: dict
old_file_path.rename(new_file_path)
return {"message": "Файл переименован"}
@app.post("/api/servers/{server_name}/files/move")
async def move_file(server_name: str, data: dict, user: dict = Depends(get_current_user)):
"""Переместить файл или папку"""
if not check_server_access(user, server_name):
raise HTTPException(403, "Нет доступа к этому серверу")
source_path = data.get("source", "").strip()
destination_path = data.get("destination", "").strip()
if not source_path:
raise HTTPException(400, "Не указан исходный путь")
server_path = SERVERS_DIR / server_name
source_full = server_path / source_path
# Формируем путь назначения
if destination_path:
# Извлекаем имя файла из source_path
file_name = source_full.name
dest_full = server_path / destination_path / file_name
else:
# Перемещение в корень
file_name = source_full.name
dest_full = server_path / file_name
print(f"Moving: {source_full} -> {dest_full}")
# Проверки безопасности
if not source_full.exists():
raise HTTPException(404, "Исходный файл не найден")
if not str(source_full).startswith(str(server_path)):
raise HTTPException(400, "Недопустимый исходный путь")
if not str(dest_full).startswith(str(server_path)):
raise HTTPException(400, "Недопустимый путь назначения")
if dest_full.exists():
raise HTTPException(400, "Файл с таким именем уже существует в папке назначения")
try:
# Создаем папку назначения если не существует
dest_full.parent.mkdir(parents=True, exist_ok=True)
# Перемещаем файл/папку
import shutil
shutil.move(str(source_full), str(dest_full))
print(f"Moved successfully: {dest_full}")
return {"message": "Файл перемещен", "new_path": str(dest_full)}
except Exception as e:
print(f"Error moving file: {e}")
raise HTTPException(500, f"Ошибка перемещения: {str(e)}")
@app.put("/api/servers/{server_name}/files/rename")
async def rename_file(server_name: str, old_path: str, new_name: str, user: dict = Depends(get_current_user)):
if not check_server_access(user, server_name):
raise HTTPException(403, "Нет доступа к этому серверу")
server_path = SERVERS_DIR / server_name
old_file_path = server_path / old_path
if not old_file_path.exists() or not str(old_file_path).startswith(str(server_path)):
raise HTTPException(404, "Файл не найден")
new_file_path = old_file_path.parent / new_name
if new_file_path.exists():
raise HTTPException(400, "Файл с таким именем уже существует")
if not str(new_file_path).startswith(str(server_path)):
raise HTTPException(400, "Недопустимое имя файла")
old_file_path.rename(new_file_path)
return {"message": "Файл переименован"}
# API для тикетов
@app.get("/api/tickets")
async def get_tickets(user: dict = Depends(get_current_user)):

View File

@@ -1,129 +1 @@
{
"1": {
"id": "1",
"title": "Пошёл нахуй",
"description": "Свин",
"author": "arkonsad",
"status": "closed",
"created_at": "2026-01-14T15:20:26.344010",
"updated_at": "2026-01-14T15:22:02.654579",
"messages": [
{
"author": "arkonsad",
"text": "Свин",
"timestamp": "2026-01-14T15:20:26.344010"
},
{
"author": "Sofa12345",
"text": "Ты че",
"timestamp": "2026-01-14T15:21:19.943424"
},
{
"author": "Sofa12345",
"text": "ахуел",
"timestamp": "2026-01-14T15:21:24.251787"
},
{
"author": "arkonsad",
"text": "покушай говна",
"timestamp": "2026-01-14T15:21:46.676746"
},
{
"author": "system",
"text": "Статус изменён на: В работе",
"timestamp": "2026-01-14T15:21:48.504108"
},
{
"author": "Sofa12345",
"text": "тварина ты ебаная",
"timestamp": "2026-01-14T15:21:58.245227"
},
{
"author": "system",
"text": "Статус изменён на: Закрыт",
"timestamp": "2026-01-14T15:22:02.654579"
}
]
},
"2": {
"id": "2",
"title": "Разраб даун",
"description": "помогите разраб минды даун, а киро вообще маньяк на коммиты в гитею",
"author": "MihailPrud",
"status": "closed",
"created_at": "2026-01-15T03:25:33.660528",
"updated_at": "2026-01-15T03:27:41.117949",
"messages": [
{
"author": "MihailPrud",
"text": "помогите разраб минды даун, а киро вообще маньяк на коммиты в гитею",
"timestamp": "2026-01-15T03:25:33.660528"
},
{
"author": "system",
"text": "Статус изменён на: В работе",
"timestamp": "2026-01-15T03:25:56.445796"
},
{
"author": "Sofa12345",
"text": "Дааааа, туда этого бота",
"timestamp": "2026-01-15T03:25:58.592839"
},
{
"author": "MihailPrud",
"text": "памагете",
"timestamp": "2026-01-15T03:26:20.740325"
},
{
"author": "Sofa12345",
"text": "чим",
"timestamp": "2026-01-15T03:26:29.038071"
},
{
"author": "MihailPrud",
"text": "у миня -30 и минет в школу надоть",
"timestamp": "2026-01-15T03:26:37.692369"
},
{
"author": "Sofa12345",
"text": "пиздец нахуй блять",
"timestamp": "2026-01-15T03:26:48.846565"
},
{
"author": "MihailPrud",
"text": "согласен",
"timestamp": "2026-01-15T03:26:56.324587"
},
{
"author": "Sofa12345",
"text": "Nahyi eto school nyxna",
"timestamp": "2026-01-15T03:27:15.968192"
},
{
"author": "Sofa12345",
"text": "pizdets",
"timestamp": "2026-01-15T03:27:21.810953"
},
{
"author": "MihailPrud",
"text": "не нужна",
"timestamp": "2026-01-15T03:27:24.548623"
},
{
"author": "MihailPrud",
"text": "но ходить надоть",
"timestamp": "2026-01-15T03:27:31.625634"
},
{
"author": "system",
"text": "Статус изменён на: Закрыт",
"timestamp": "2026-01-15T03:27:38.480740"
},
{
"author": "MihailPrud",
"text": "для баланса вселеннной",
"timestamp": "2026-01-15T03:27:41.117949"
}
]
}
}
{}

View File

@@ -11,15 +11,10 @@
"arkonsad": {
"username": "arkonsad",
"password": "$2b$12$z.AYkfa/MlTYFd9rLNfBmu9JHOFKUe8YdddnqCmRqAxc7vGQeo392",
"role": "banned",
"role": "user",
"servers": [
"123"
"123",
"sdfsdf"
]
},
"Sofa12345": {
"username": "Sofa12345",
"password": "$2b$12$Fph20p2mwgOAqoT77wSA3.n1S7NiHLa28aiNOwWcz3PfNhgC5pp5.",
"role": "admin",
"servers": []
}
}