Wire production domain, CORS for tenant subdomains, celery volume mounts, and nginx reverse proxy configs for apex, API, identity, auth, and wildcard tenants. Co-authored-by: Cursor <cursoragent@cursor.com>
50 lines
1.2 KiB
Python
50 lines
1.2 KiB
Python
from datetime import datetime
|
|
from uuid import UUID
|
|
|
|
from pydantic import BaseModel, EmailStr, Field, field_validator
|
|
|
|
from app.models.types import MembershipRole, UserStatus
|
|
from app.schemas.common import ORMModel
|
|
from shared.phone import normalize_mobile
|
|
|
|
|
|
class UserCreate(BaseModel):
|
|
email: EmailStr
|
|
username: str = Field(..., min_length=3, max_length=150)
|
|
display_name: str | None = None
|
|
password: str = Field(..., min_length=8)
|
|
mobile: str = Field(..., min_length=10, max_length=15)
|
|
|
|
@field_validator("mobile")
|
|
@classmethod
|
|
def validate_mobile(cls, value: str) -> str:
|
|
return normalize_mobile(value)
|
|
|
|
|
|
class UserRead(ORMModel):
|
|
id: UUID
|
|
keycloak_sub: str
|
|
email: str
|
|
username: str | None
|
|
display_name: str | None
|
|
mobile: str | None
|
|
mobile_verified: bool
|
|
mobile_verified_at: datetime | None
|
|
core_user_id: UUID | None
|
|
status: UserStatus
|
|
created_at: datetime
|
|
|
|
|
|
class MembershipCreate(BaseModel):
|
|
user_id: UUID
|
|
role: MembershipRole = MembershipRole.TENANT_MEMBER
|
|
|
|
|
|
class MembershipRead(ORMModel):
|
|
id: UUID
|
|
tenant_id: UUID
|
|
user_id: UUID
|
|
role: MembershipRole
|
|
is_active: bool
|
|
joined_at: datetime
|