api development
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2025-08-08 21:58:36 +09:00
parent d58302c2c8
commit cc87dcc0fa
157 changed files with 14629 additions and 7 deletions

View File

@@ -0,0 +1,123 @@
#!/usr/bin/env bash
set -euo pipefail
# 1) Репозиторий: приводить user_id к uuid.UUID
cat > services/profiles/src/app/repositories/profile_repository.py <<'PY'
import uuid
from typing import Optional
from sqlalchemy import select
from sqlalchemy.orm import Session
from app.models.profile import Profile
from app.schemas.profile import ProfileCreate
class ProfileRepository:
def __init__(self, db: Session):
self.db = db
@staticmethod
def _to_uuid(v) -> uuid.UUID:
if isinstance(v, uuid.UUID):
return v
return uuid.UUID(str(v))
def get_by_user(self, user_id) -> Optional[Profile]:
uid = self._to_uuid(user_id)
stmt = select(Profile).where(Profile.user_id == uid)
return self.db.execute(stmt).scalar_one_or_none()
def create(self, user_id, obj: ProfileCreate) -> Profile:
uid = self._to_uuid(user_id)
p = Profile(
user_id=uid,
gender=obj.gender,
city=obj.city,
languages=obj.languages or [],
interests=obj.interests or [],
)
self.db.add(p)
self.db.commit()
self.db.refresh(p)
return p
PY
# 2) Схемы: дефолты - пустые списки (чтобы не было None → JSONB)
cat > services/profiles/src/app/schemas/profile.py <<'PY'
from __future__ import annotations
from typing import Optional, List
from pydantic import BaseModel, Field
class ProfileBase(BaseModel):
gender: str
city: str
languages: List[str] = Field(default_factory=list)
interests: List[str] = Field(default_factory=list)
class ProfileCreate(ProfileBase):
pass
class ProfileOut(ProfileBase):
id: str
user_id: str
class Config:
from_attributes = True
PY
# 3) Роут: ловим ошибки явно → 400 вместо 500
cat > services/profiles/src/app/api/routes/profiles.py <<'PY'
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError, DataError
from app.db.deps import get_db
from app.schemas.profile import ProfileCreate, ProfileOut
from app.services.profile_service import ProfileService
from app.core.security import get_current_user # возвращает объект с полями sub, email, role
router = APIRouter(prefix="/v1/profiles", tags=["profiles"])
@router.get("/me", response_model=ProfileOut)
def get_my_profile(db: Session = Depends(get_db), user=Depends(get_current_user)):
svc = ProfileService(db)
p = svc.get_by_user(user.sub)
if not p:
# 404, если профиль отсутствует
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Profile not found")
return p
@router.post("", response_model=ProfileOut, status_code=status.HTTP_201_CREATED)
def create_profile(payload: ProfileCreate, db: Session = Depends(get_db), user=Depends(get_current_user)):
svc = ProfileService(db)
try:
existing = svc.get_by_user(user.sub)
if existing:
return existing
p = svc.create(user.sub, payload)
return p
except (IntegrityError, DataError, ValueError) as exc:
db.rollback()
raise HTTPException(status_code=400, detail=f"Invalid data: {exc}")
PY
# 4) Сервис — тонкая обёртка над репозиторием
cat > services/profiles/src/app/services/profile_service.py <<'PY'
from sqlalchemy.orm import Session
from app.repositories.profile_repository import ProfileRepository
from app.schemas.profile import ProfileCreate
class ProfileService:
def __init__(self, db: Session):
self.repo = ProfileRepository(db)
def get_by_user(self, user_id):
return self.repo.get_by_user(user_id)
def create(self, user_id, obj: ProfileCreate):
return self.repo.create(user_id, obj)
PY
echo "[profiles] rebuilding..."
docker compose build profiles
docker compose restart profiles