73 lines
2 KiB
Python
73 lines
2 KiB
Python
|
|
"""Pydantic schemas for file attachments"""
|
||
|
|
|
||
|
|
from datetime import datetime
|
||
|
|
from typing import Optional
|
||
|
|
|
||
|
|
from pydantic import (BaseModel, ConfigDict, Field, field_serializer,
|
||
|
|
field_validator)
|
||
|
|
|
||
|
|
|
||
|
|
class FileUploadRequest(BaseModel):
|
||
|
|
"""Schema for file upload request"""
|
||
|
|
|
||
|
|
entity_type: str = Field(..., description="Type of entity (Card, Comment, etc.)")
|
||
|
|
entity_id: int = Field(..., description="ID of entity")
|
||
|
|
|
||
|
|
@field_validator("entity_type")
|
||
|
|
@classmethod
|
||
|
|
def validate_entity_type(cls, v: str) -> str:
|
||
|
|
"""Validate entity type is allowed"""
|
||
|
|
valid_types = ["Card", "Comment", "Epic", "Board"]
|
||
|
|
if v not in valid_types:
|
||
|
|
raise ValueError(f"Invalid entity_type: {v}. Must be one of {valid_types}")
|
||
|
|
return v
|
||
|
|
|
||
|
|
model_config = ConfigDict(from_attributes=True)
|
||
|
|
|
||
|
|
|
||
|
|
class FileAttachmentWithUrlResponse(BaseModel):
|
||
|
|
"""
|
||
|
|
Schema for file attachment with secure URLs
|
||
|
|
|
||
|
|
Security: Only exposes public-facing information.
|
||
|
|
Internal details (MinIO paths, IDs, etc.) are hidden.
|
||
|
|
"""
|
||
|
|
|
||
|
|
uuid: str
|
||
|
|
original_name: str
|
||
|
|
file_type: str
|
||
|
|
file_size: int
|
||
|
|
created_at: datetime
|
||
|
|
download_url: str
|
||
|
|
thumbnail_url: Optional[str] = None
|
||
|
|
view_url: str
|
||
|
|
mime_type: str
|
||
|
|
|
||
|
|
@field_serializer("created_at")
|
||
|
|
def serialize_created_at(self, value: datetime) -> str:
|
||
|
|
"""Serialize datetime to ISO format string"""
|
||
|
|
return value.isoformat() if value else None
|
||
|
|
|
||
|
|
model_config = ConfigDict(from_attributes=True)
|
||
|
|
|
||
|
|
|
||
|
|
class FileDeleteResponse(BaseModel):
|
||
|
|
"""Schema for file delete response"""
|
||
|
|
|
||
|
|
message: str = Field(..., description="Deletion status message")
|
||
|
|
file_id: int = Field(..., description="ID of deleted file")
|
||
|
|
|
||
|
|
|
||
|
|
class MultipleFilesResponse(BaseModel):
|
||
|
|
"""Schema for multiple files response"""
|
||
|
|
|
||
|
|
files: list[FileAttachmentWithUrlResponse]
|
||
|
|
count: int = Field(..., description="Number of files")
|
||
|
|
|
||
|
|
|
||
|
|
class ValidationError(BaseModel):
|
||
|
|
"""Schema for validation errors"""
|
||
|
|
|
||
|
|
error: str = Field(..., description="Error message")
|
||
|
|
details: Optional[dict] = None
|