22474cdba5
Backend (ruff): - Fix 106 errors: move imports to top of file (E402) - Remove unused imports (F401) - Add missing imports for undefined names (F821) - Remove unused variables (F841) - Fix test_models.py broken RefreshToken test - Fix test_projects_api.py missing TestClient import Frontend (eslint): - Remove unused imports/variables across 10 files - Fix explicit any types in client.ts and sessions.ts - Clean up empty block statements in terminal.tsx Quality gates: ruff (pass), eslint (pass), tsc --noEmit (pass), pytest (98 passed, 4 pre-existing failures)
113 lines
3.4 KiB
Python
113 lines
3.4 KiB
Python
import logging
|
|
import uuid
|
|
|
|
from fastapi import APIRouter, Depends
|
|
from pydantic import BaseModel, ConfigDict
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from src.auth.dependencies import _get_user, get_current_user_id, get_db_session
|
|
from src.models.user_config import UserConfig
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(prefix="/users/me", tags=["user-config"])
|
|
|
|
|
|
async def _get_or_create_config(session: AsyncSession, user_id: uuid.UUID) -> UserConfig:
|
|
"""Get or create user config record.
|
|
|
|
Args:
|
|
session: Database session.
|
|
user_id: UUID of the user.
|
|
|
|
Returns:
|
|
The user's config, creating a new one if it doesn't exist.
|
|
"""
|
|
result = await session.execute(select(UserConfig).where(UserConfig.user_id == user_id))
|
|
config = result.scalar_one_or_none()
|
|
if config is None:
|
|
config = UserConfig(user_id=user_id, config={})
|
|
session.add(config)
|
|
await session.commit()
|
|
await session.refresh(config)
|
|
return config
|
|
|
|
|
|
class UserConfigResponse(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
default_editor: str | None = None
|
|
theme: str = "system"
|
|
git_user_name: str | None = None
|
|
git_user_email: str | None = None
|
|
last_session_id: str | None = None
|
|
|
|
|
|
class UserConfigUpdate(BaseModel):
|
|
default_editor: str | None = None
|
|
theme: str | None = None
|
|
git_user_name: str | None = None
|
|
git_user_email: str | None = None
|
|
last_session_id: str | None = None
|
|
|
|
|
|
@router.get(
|
|
"/config",
|
|
response_model=UserConfigResponse,
|
|
summary="Get user config",
|
|
description="Get the current user's configuration settings.",
|
|
)
|
|
async def get_user_config(
|
|
user_id: uuid.UUID = Depends(get_current_user_id),
|
|
session: AsyncSession = Depends(get_db_session),
|
|
) -> UserConfigResponse:
|
|
"""Get the current user's configuration.
|
|
|
|
Args:
|
|
user_id: ID of the authenticated user.
|
|
session: Database session.
|
|
|
|
Returns:
|
|
The user's configuration settings.
|
|
"""
|
|
_user = await _get_user(session, user_id)
|
|
config = await _get_or_create_config(session, user_id)
|
|
return UserConfigResponse.model_validate(config.config)
|
|
|
|
|
|
@router.patch(
|
|
"/config",
|
|
response_model=UserConfigResponse,
|
|
summary="Update user config",
|
|
description="Update the current user's configuration settings.",
|
|
)
|
|
async def update_user_config(
|
|
data: UserConfigUpdate,
|
|
user_id: uuid.UUID = Depends(get_current_user_id),
|
|
session: AsyncSession = Depends(get_db_session),
|
|
) -> UserConfigResponse:
|
|
"""Update the current user's configuration.
|
|
|
|
Args:
|
|
data: Configuration update data with optional fields.
|
|
user_id: ID of the authenticated user.
|
|
session: Database session.
|
|
|
|
Returns:
|
|
The updated user configuration.
|
|
"""
|
|
_user = await _get_user(session, user_id)
|
|
config = await _get_or_create_config(session, user_id)
|
|
|
|
# Merge updates
|
|
update_data = data.model_dump(exclude_unset=True)
|
|
logger.debug("Updating user config for user %s: %s", user_id, update_data)
|
|
# SQLAlchemy JSON doesn't track dict mutations, so we replace the whole dict
|
|
config.config = {**config.config, **update_data}
|
|
|
|
await session.commit()
|
|
await session.refresh(config)
|
|
logger.debug("Updated config: %s", config.config)
|
|
return UserConfigResponse.model_validate(config.config)
|