""" API endpoints для управления профилем пользователя Автор: Сергей Антропов Сайт: https://devops.org.ru """ from fastapi import APIRouter, Request, HTTPException, Depends, Form from fastapi.responses import HTMLResponse, JSONResponse from fastapi.templating import Jinja2Templates from pathlib import Path from typing import Optional from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func from app.db.session import get_async_db from app.services.user_service import UserService from app.models.user import User, UserProfile from app.models.database import Preset, Dockerfile, Playbook, CommandHistory from app.auth.deps import get_current_user router = APIRouter() templates_path = Path(__file__).parent.parent.parent.parent / "templates" templates = Jinja2Templates(directory=str(templates_path)) @router.get("/profile", response_class=HTMLResponse) async def profile_page( request: Request, current_user: dict = Depends(get_current_user), db: AsyncSession = Depends(get_async_db) ): """Страница профиля пользователя""" user = await UserService.get_user_by_username(db, current_user.get("username")) if not user: raise HTTPException(status_code=404, detail="Пользователь не найден") # Получаем или создаем профиль result = await db.execute(select(UserProfile).where(UserProfile.user_id == user.id)) profile = result.scalar_one_or_none() if not profile: profile = UserProfile(user_id=user.id) db.add(profile) await db.commit() await db.refresh(profile) # Получаем статистику пользователя username = user.username # Количество созданных preset'ов presets_count = await db.execute( select(func.count(Preset.id)).where(Preset.created_by == username) ) presets_count = presets_count.scalar() or 0 # Количество созданных Dockerfile'ов dockerfiles_count = await db.execute( select(func.count(Dockerfile.id)).where(Dockerfile.created_by == username) ) dockerfiles_count = dockerfiles_count.scalar() or 0 # Количество созданных playbook'ов playbooks_count = await db.execute( select(func.count(Playbook.id)).where(Playbook.created_by == username) ) playbooks_count = playbooks_count.scalar() or 0 # Количество выполненных команд commands_count = await db.execute( select(func.count(CommandHistory.id)).where(CommandHistory.user == username) ) commands_count = commands_count.scalar() or 0 # Количество успешных тестов successful_tests = await db.execute( select(func.count(CommandHistory.id)).where( CommandHistory.user == username, CommandHistory.command_type == "test", CommandHistory.status == "success" ) ) successful_tests = successful_tests.scalar() or 0 return templates.TemplateResponse( "pages/profile/index.html", { "request": request, "user": user, "profile": profile, "stats": { "presets": presets_count, "dockerfiles": dockerfiles_count, "playbooks": playbooks_count, "commands": commands_count, "successful_tests": successful_tests } } ) @router.post("/api/v1/profile") async def update_profile( request: Request, email: Optional[str] = Form(None), full_name: Optional[str] = Form(None), current_user: dict = Depends(get_current_user), db: AsyncSession = Depends(get_async_db) ): """Обновление профиля пользователя""" user = await UserService.get_user_by_username(db, current_user.get("username")) if not user: raise HTTPException(status_code=404, detail="Пользователь не найден") # Получаем или создаем профиль result = await db.execute(select(UserProfile).where(UserProfile.user_id == user.id)) profile = result.scalar_one_or_none() if not profile: profile = UserProfile(user_id=user.id) db.add(profile) if email: profile.email = email if full_name: profile.full_name = full_name await db.commit() await db.refresh(profile) return JSONResponse(content={ "success": True, "message": "Профиль обновлен успешно" }) @router.get("/profile/docker-settings", response_class=HTMLResponse) async def docker_settings_page( request: Request, current_user: dict = Depends(get_current_user), db: AsyncSession = Depends(get_async_db) ): """Страница настроек Docker (Harbor и Docker Hub)""" user = await UserService.get_user_by_username(db, current_user.get("username")) if not user: raise HTTPException(status_code=404, detail="Пользователь не найден") # Получаем или создаем профиль result = await db.execute(select(UserProfile).where(UserProfile.user_id == user.id)) profile = result.scalar_one_or_none() if not profile: profile = UserProfile(user_id=user.id) db.add(profile) await db.commit() await db.refresh(profile) return templates.TemplateResponse( "pages/profile/docker-settings.html", { "request": request, "profile": profile } ) @router.post("/api/v1/profile/docker-settings") async def update_docker_settings( request: Request, dockerhub_username: Optional[str] = Form(None), dockerhub_password: Optional[str] = Form(None), dockerhub_repository: Optional[str] = Form(None), harbor_url: Optional[str] = Form(None), harbor_username: Optional[str] = Form(None), harbor_password: Optional[str] = Form(None), harbor_project: Optional[str] = Form(None), current_user: dict = Depends(get_current_user), db: AsyncSession = Depends(get_async_db) ): """Обновление настроек Docker""" user = await UserService.get_user_by_username(db, current_user.get("username")) if not user: raise HTTPException(status_code=404, detail="Пользователь не найден") # Получаем или создаем профиль result = await db.execute(select(UserProfile).where(UserProfile.user_id == user.id)) profile = result.scalar_one_or_none() if not profile: profile = UserProfile(user_id=user.id) db.add(profile) # Обновляем настройки Docker Hub if dockerhub_username is not None: profile.dockerhub_username = dockerhub_username if dockerhub_password: # TODO: Зашифровать пароль перед сохранением profile.dockerhub_password = dockerhub_password if dockerhub_repository is not None: profile.dockerhub_repository = dockerhub_repository # Обновляем настройки Harbor if harbor_url is not None: profile.harbor_url = harbor_url if harbor_username is not None: profile.harbor_username = harbor_username if harbor_password: # TODO: Зашифровать пароль перед сохранением profile.harbor_password = harbor_password if harbor_project is not None: profile.harbor_project = harbor_project await db.commit() await db.refresh(profile) return JSONResponse(content={ "success": True, "message": "Настройки Docker обновлены успешно" })