Fix QA review findings: server-side DOB validation, naive date max prop

- W-01: Add date_of_birth validators to RegisterRequest and ProfileUpdate
  (reject future dates and years before 1900)
- W-05: Replace .toISOString().slice() with local date formatting for
  DatePicker max prop on registration form

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Kyle 2026-03-03 16:59:54 +08:00
parent 6cd648f3a8
commit 0c6ea1ccff
2 changed files with 21 additions and 1 deletions

View File

@ -112,6 +112,15 @@ class RegisterRequest(BaseModel):
assert result is not None # required=True guarantees non-None assert result is not None # required=True guarantees non-None
return result return result
@field_validator("date_of_birth")
@classmethod
def validate_date_of_birth(cls, v: date) -> date:
if v > date.today():
raise ValueError("Date of birth cannot be in the future")
if v.year < 1900:
raise ValueError("Date of birth is not valid")
return v
@field_validator("preferred_name") @field_validator("preferred_name")
@classmethod @classmethod
def validate_preferred_name(cls, v: str | None) -> str | None: def validate_preferred_name(cls, v: str | None) -> str | None:
@ -169,6 +178,17 @@ class ProfileUpdate(BaseModel):
def validate_email(cls, v: str | None) -> str | None: def validate_email(cls, v: str | None) -> str | None:
return _validate_email_format(v) return _validate_email_format(v)
@field_validator("date_of_birth")
@classmethod
def validate_date_of_birth(cls, v: date | None) -> date | None:
if v is None:
return v
if v > date.today():
raise ValueError("Date of birth cannot be in the future")
if v.year < 1900:
raise ValueError("Date of birth is not valid")
return v
@field_validator("first_name", "last_name") @field_validator("first_name", "last_name")
@classmethod @classmethod
def validate_name_fields(cls, v: str | None) -> str | None: def validate_name_fields(cls, v: str | None) -> str | None:

View File

@ -649,7 +649,7 @@ export default function LockScreen() {
required required
name="bday" name="bday"
autoComplete="bday" autoComplete="bday"
max={new Date().toISOString().slice(0, 10)} max={(() => { const d = new Date(); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; })()}
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-2">