Files
saas_backend/app/schemas/auth/invitation_schema.py
T
2026-08-31 20:39:41 -04:00

69 lines
2.0 KiB
Python

"""What the invitation endpoints accept and return.
Two response shapes on purpose. `InvitationResponse` is for the administrator
who sent it and may name the role and the sender. `InvitationPreview` is for a
signed-out stranger holding a link, and says only enough to answer "am I in the
right place" — the workspace name and the address it was sent to. Anything more
would make a guessed token a way to read a workspace's staff list.
Neither ever carries the token. It exists once, in the response to creating an
invitation, and is a SHA-256 everywhere else.
"""
from __future__ import annotations
import uuid
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel, ConfigDict, EmailStr, Field
class InvitationCreate(BaseModel):
email: EmailStr
role_id: Optional[uuid.UUID] = None
first_name: Optional[str] = Field(default=None, max_length=100)
last_name: Optional[str] = Field(default=None, max_length=100)
class InvitationResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
email: str
first_name: Optional[str] = None
last_name: Optional[str] = None
role_id: Optional[uuid.UUID] = None
invited_by_id: Optional[uuid.UUID] = None
expires_at: datetime
accepted_at: Optional[datetime] = None
revoked_at: Optional[datetime] = None
created_at: datetime
state: str
class InvitationCreated(BaseModel):
invitation: InvitationResponse
acceptance_url: str
email_sent: bool
class InvitationPreview(BaseModel):
"""What a signed-out visitor holding a link is told."""
email: str
workspace_name: str
expires_at: datetime
class InvitationAccept(BaseModel):
token: str = Field(min_length=1)
password: str = Field(min_length=1)
first_name: Optional[str] = Field(default=None, max_length=100)
last_name: Optional[str] = Field(default=None, max_length=100)
class InvitationList(BaseModel):
items: List[InvitationResponse]
total: int