Files
ds-chat/backend/app/schemas/site_invite.py
T
ksmithandClaude Sonnet 5 2466e76af1 Require password confirmation on account creation (#40)
Both account-creation surfaces now require the password twice:

- Web signup (invite-based self-service): SignupComplete gains a
  password_confirm field with a model_validator backstop server-side,
  plus a client-side match check in SignupPage.tsx for immediate
  feedback -- the client check is the primary UX, the server check is
  defense in depth so the guarantee doesn't rely on the client alone.
- CLI (python -m app.cli create-user): password is now an optional
  positional argument. If omitted, prompts interactively via getpass
  (hidden input) twice, retrying on mismatch -- matching what "entered
  twice and verified" actually means for a human typing blind. Passing
  the password directly as before still works unchanged, for scripted/
  automated provisioning.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-17 09:48:23 -06:00

44 lines
1.2 KiB
Python

import uuid
from datetime import datetime
from pydantic import BaseModel, ConfigDict, EmailStr, Field, model_validator
from app.models import InviteStatus
class SiteInviteCreate(BaseModel):
email: EmailStr
class SiteInviteRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
email: str
invited_by: uuid.UUID
status: InviteStatus
expires_at: datetime
created_at: datetime
class SignupValidateRead(BaseModel):
email: str
class SignupComplete(BaseModel):
token: str
username: str = Field(min_length=3, max_length=50)
password: str = Field(min_length=8, max_length=200)
password_confirm: str
# Backend backstop -- the signup form does its own client-side match
# check for immediate feedback (see SignupPage.tsx), but account
# creation is irreversible enough (a typo'd password with no recovery
# path until forgot-password) that the guarantee shouldn't rely on the
# client alone.
@model_validator(mode="after")
def _passwords_match(self) -> "SignupComplete":
if self.password != self.password_confirm:
raise ValueError("Passwords don't match")
return self