Files
resolutionflow/backend/app/schemas/auth_password.py
chihlasm ad59446332 feat: user management — admin create, password reset, archive/delete, quick invite
Phase 1: must_change_password enforcement + change password endpoint/page
Phase 2: Admin user creation (M365-style) with temp password
Phase 3: Password reset (self-service forgot + admin-triggered)
Phase 4: User archive (soft delete) + hard delete with precheck
Phase 5: Quick invite from admin Users page

Also fixes:
- Auto-create subscription for accounts missing one
- Hard delete precheck ignores sole-member personal accounts
- Seed script patches tree nodes for validation compliance

Migrations: 031 (must_change_password), 032 (password_reset_tokens), 033 (user soft delete)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 01:42:51 -05:00

47 lines
1.3 KiB
Python

import re
from typing import Optional
from pydantic import BaseModel, EmailStr, Field, field_validator
def _validate_password_complexity(v: str) -> str:
if not re.search(r'[A-Z]', v):
raise ValueError('Password must contain at least one uppercase letter')
if not re.search(r'[a-z]', v):
raise ValueError('Password must contain at least one lowercase letter')
if not re.search(r'[0-9]', v):
raise ValueError('Password must contain at least one digit')
return v
class ChangePasswordRequest(BaseModel):
current_password: str
new_password: str = Field(..., min_length=10, description="Password must be at least 10 characters")
@field_validator('new_password')
@classmethod
def password_complexity(cls, v: str) -> str:
return _validate_password_complexity(v)
class ForgotPasswordRequest(BaseModel):
email: EmailStr
class VerifyResetTokenRequest(BaseModel):
token: str
class VerifyResetTokenResponse(BaseModel):
valid: bool
email: Optional[str] = None
class ResetPasswordRequest(BaseModel):
token: str
new_password: str = Field(..., min_length=10, description="Password must be at least 10 characters")
@field_validator('new_password')
@classmethod
def password_complexity(cls, v: str) -> str:
return _validate_password_complexity(v)