diff --git a/backend/app/schemas/auth.py b/backend/app/schemas/auth.py index 2675141..29e178b 100644 --- a/backend/app/schemas/auth.py +++ b/backend/app/schemas/auth.py @@ -112,6 +112,15 @@ class RegisterRequest(BaseModel): assert result is not None # required=True guarantees non-None 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") @classmethod 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: 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") @classmethod def validate_name_fields(cls, v: str | None) -> str | None: diff --git a/frontend/src/components/auth/LockScreen.tsx b/frontend/src/components/auth/LockScreen.tsx index 9b5383a..0a5bd03 100644 --- a/frontend/src/components/auth/LockScreen.tsx +++ b/frontend/src/components/auth/LockScreen.tsx @@ -649,7 +649,7 @@ export default function LockScreen() { required name="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')}`; })()} />