from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import select from sqlalchemy.orm import Session from app.core.security import hash_password from app.db.session import get_db from app.models.entities import AppSetting, Home, HomeMembership, HomeRole, InstanceRole, User from app.schemas.common import SetupCreate, SetupStatus, UserOut from app.services.audit import audit router = APIRouter() @router.get("/status", response_model=SetupStatus) def setup_status(db: Session = Depends(get_db)) -> SetupStatus: admin_exists = db.scalar(select(User).where(User.instance_role == InstanceRole.ADMIN)) is not None instance = db.get(AppSetting, "instance") return SetupStatus(needs_setup=not admin_exists, instance=instance.value if instance else None) @router.post("/complete", response_model=UserOut, status_code=status.HTTP_201_CREATED) def complete_setup(payload: SetupCreate, db: Session = Depends(get_db)) -> User: if db.scalar(select(User).where(User.instance_role == InstanceRole.ADMIN)): raise HTTPException(status_code=409, detail="Instance already initialized") user = User( email=str(payload.email).lower(), name=payload.name, password_hash=hash_password(payload.password), instance_role=InstanceRole.ADMIN, language=payload.language, theme=payload.theme, timezone=payload.timezone, ) home = Home(name=f"{payload.name}'s Home") db.add_all( [ user, home, AppSetting( key="instance", value={ "name": payload.instance_name, "public_url": payload.public_url, "language": payload.language, "theme": payload.theme, "timezone": payload.timezone, "registration_enabled": False, "security": {"login_rate_limit": "10/minute"}, "notifications": {"default_warning_days": 5}, }, ), ] ) db.flush() db.add(HomeMembership(home_id=home.id, user_id=user.id, role=HomeRole.OWNER)) audit(db, user, "instance.setup", "user", user.id) db.commit() db.refresh(user) return user