from datetime import datetime from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from ..database import AsyncSessionLocal from ..dependencies import get_db, get_current_user from ..models.user import User from ..models.library import Library from ..models.session import ServerSetting from ..services.auth import verify_password, create_token from ..schemas.auth import LoginRequest, LoginResponse, AuthorizeResponse from ..schemas.user import UserOut, UserSettings, ServerSettingsOut router = APIRouter(tags=["auth"]) def _build_user_out(user: User) -> UserOut: raw_settings = user.settings or {} settings = UserSettings(**{k: v for k, v in raw_settings.items() if k in UserSettings.model_fields}) return UserOut( id=user.id, username=user.username, email=user.email, is_admin=user.is_admin, is_active=user.is_active, last_seen=user.last_seen, created_at=user.created_at, token=user.token, settings=settings, type="root" if user.is_admin else "user", permissions={ "download": True, "update": user.is_admin, "delete": user.is_admin, "upload": user.is_admin, "access_all_libraries": True, "access_explicit_content": True, }, ) @router.post("/login", response_model=LoginResponse) async def login(body: LoginRequest, db: AsyncSession = Depends(get_db)): result = await db.execute( select(User).where(User.username == body.username, User.is_active == True) ) user = result.scalar_one_or_none() if not user or not verify_password(body.password, user.password_hash): raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials") token = create_token(user.id) user.token = token user.last_seen = datetime.utcnow() await db.commit() # Erste Library als Default zurückgeben lib_result = await db.execute(select(Library).limit(1)) first_lib = lib_result.scalar_one_or_none() return LoginResponse( user=_build_user_out(user), user_default_library_id=first_lib.id if first_lib else None, server_settings=ServerSettingsOut(), ) @router.post("/logout") async def logout(current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)): current_user.token = None await db.commit() return {"success": True} @router.get("/api/authorize", response_model=AuthorizeResponse) async def authorize(current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)): current_user.last_seen = datetime.utcnow() await db.commit() lib_result = await db.execute(select(Library)) libraries = lib_result.scalars().all() from ..routers.libraries import _library_to_out libs_out = [_library_to_out(lib) for lib in libraries] first_lib_id = libraries[0].id if libraries else None return AuthorizeResponse( user=_build_user_out(current_user), libraries=libs_out, user_default_library_id=first_lib_id, server_settings=ServerSettingsOut(), ) @router.get("/ping") async def ping(): return {"success": True} @router.get("/health") async def health(): return {"status": "ok"}