Cybersecurity-Projects/PROJECTS/advanced/encrypted-p2p-chat/backend/app/schemas/websocket.py

122 lines
2.4 KiB
Python

"""
ⒸAngelaMos | 2025
Pydantic schemas for WebSocket message types
"""
from typing import Any
from datetime import datetime
from uuid import UUID
from pydantic import BaseModel, Field
from app.config import (
ENCRYPTED_CONTENT_MAX_LENGTH,
MESSAGE_ID_MAX_LENGTH,
)
class BaseWSMessage(BaseModel):
"""
Base WebSocket message with common fields
"""
type: str
timestamp: datetime | None = None
class EncryptedMessageWS(BaseWSMessage):
"""
Encrypted message sent over WebSocket
"""
type: str = "encrypted_message"
message_id: str = Field(max_length = MESSAGE_ID_MAX_LENGTH)
sender_id: str
recipient_id: str
room_id: str
content: str = ""
ciphertext: str = Field(max_length = ENCRYPTED_CONTENT_MAX_LENGTH)
nonce: str
header: str
sender_username: str
class TypingIndicatorWS(BaseWSMessage):
"""
Typing indicator message
"""
type: str = "typing"
user_id: str
room_id: str
is_typing: bool
class PresenceUpdateWS(BaseWSMessage):
"""
User presence update message
"""
type: str = "presence"
user_id: str
status: str
last_seen: datetime
class ReadReceiptWS(BaseWSMessage):
"""
Message read receipt
"""
type: str = "receipt"
message_id: str = Field(max_length = MESSAGE_ID_MAX_LENGTH)
user_id: str
read_at: datetime
class ErrorMessageWS(BaseWSMessage):
"""
Error message sent over WebSocket
"""
type: str = "error"
error_code: str
error_message: str
details: dict[str, Any] | None = None
class WSConnectionRequest(BaseModel):
"""
WebSocket connection request with auth token
"""
user_id: UUID
token: str | None = None
class WSHeartbeat(BaseModel):
"""
WebSocket heartbeat ping/pong message
"""
type: str = "heartbeat"
timestamp: datetime
class RoomCreatedWS(BaseModel):
"""
Room created notification sent over WebSocket
"""
type: str = "room_created"
room_id: str
room_type: str
name: str | None
participants: list[dict[str, Any]]
is_encrypted: bool
created_at: str
updated_at: str
class MessageSentWS(BaseWSMessage):
"""
Confirmation sent back to sender after message is stored
"""
type: str = "message_sent"
temp_id: str
message_id: str
room_id: str
status: str = "sent"
created_at: datetime