- Добавлена колонка 'Тип' во все таблицы истории сборок - Для push операций отображается registry вместо платформ - Сохранение пользователя при создании push лога - Исправлена ошибка с logger в push_docker_image endpoint - Улучшено отображение истории сборок с визуальными индикаторами
218 lines
7.8 KiB
Python
218 lines
7.8 KiB
Python
"""
|
|
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 обновлены успешно"
|
|
})
|