feat: Added onboarding_completed flag to User model, UserResponse schem…

- "backend/models.py"
- "backend/schemas.py"
- "backend/routers/auth.py"
- "alembic/versions/030_add_onboarding_completed.py"

GSD-Task: S03/T01
This commit is contained in:
jlightner 2026-04-04 13:13:05 +00:00
parent c5fb352552
commit 102e00f323
4 changed files with 51 additions and 0 deletions

View file

@ -0,0 +1,31 @@
"""add_onboarding_completed
Revision ID: 030_onboarding
Revises: 029
Create Date: 2026-04-04
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers
revision = "030_onboarding"
down_revision = "029_add_email_digest"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.add_column(
"users",
sa.Column(
"onboarding_completed",
sa.Boolean(),
server_default="false",
nullable=False,
),
)
def downgrade() -> None:
op.drop_column("users", "onboarding_completed")

View file

@ -169,6 +169,9 @@ class User(Base):
is_active: Mapped[bool] = mapped_column(
Boolean, default=True, server_default="true"
)
onboarding_completed: Mapped[bool] = mapped_column(
Boolean, default=False, server_default="false"
)
notification_preferences: Mapped[dict] = mapped_column(
JSONB, nullable=False,
server_default='{"email_digests": true, "digest_frequency": "daily"}',

View file

@ -171,3 +171,19 @@ async def seed_invite_codes(session: AsyncSession) -> None:
))
await session.commit()
logger.info("Seeded default invite code: CHRYSOPEDIA-ALPHA-2026")
# ── Onboarding ───────────────────────────────────────────────────────────────
@router.post("/onboarding-complete", response_model=UserResponse)
async def complete_onboarding(
current_user: Annotated[User, Depends(get_current_user)],
session: Annotated[AsyncSession, Depends(get_session)],
):
"""Mark the current user's onboarding as completed."""
current_user.onboarding_completed = True
await session.commit()
await session.refresh(current_user)
logger.info("Onboarding completed: %s", current_user.id)
return UserResponse.model_validate(current_user)

View file

@ -568,6 +568,7 @@ class UserResponse(BaseModel):
role: str
creator_id: uuid.UUID | None = None
is_active: bool = True
onboarding_completed: bool = False
created_at: datetime
impersonating: bool = False