feat: homelab deployment - NPM + IONOS DNS + monitoring + NAS backup
- Restructured docker-compose for Nginx Proxy Manager (no custom nginx) - Added domain wordly.art configuration - Added Prometheus + Grafana monitoring stack with pre-configured dashboards - Added PostgreSQL backup script to NAS (daily/weekly/monthly rotation) - Added alert rules for backend, system, and Docker metrics - Updated deployment guide for NPM + IONOS DNS homelab setup - Added marketing plan document - PDF translator and watermark support - Enhanced middleware, routes, and translator modules Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -57,10 +57,12 @@ class FileValidator:
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": ".xlsx",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation": ".pptx",
|
||||
"application/pdf": ".pdf",
|
||||
}
|
||||
|
||||
# Magic bytes for Office Open XML files (ZIP format)
|
||||
OFFICE_MAGIC_BYTES = b"PK\x03\x04"
|
||||
PDF_MAGIC_BYTES = b"%PDF"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -70,7 +72,7 @@ class FileValidator:
|
||||
):
|
||||
self.max_size_bytes = max_size_mb * 1024 * 1024
|
||||
self.max_size_mb = max_size_mb
|
||||
self.allowed_extensions = allowed_extensions or {".xlsx", ".docx", ".pptx"}
|
||||
self.allowed_extensions = allowed_extensions or {".xlsx", ".docx", ".pptx", ".pdf"}
|
||||
self.scan_content = scan_content
|
||||
|
||||
async def validate_async(self, file: UploadFile) -> ValidationResult:
|
||||
@@ -281,11 +283,20 @@ class FileValidator:
|
||||
|
||||
def _validate_magic_bytes(self, content: bytes, extension: str):
|
||||
"""Validate file magic bytes match expected format"""
|
||||
# All supported formats are Office Open XML (ZIP-based)
|
||||
# PDF files start with %PDF
|
||||
if extension.lower() == ".pdf":
|
||||
if not content.startswith(self.PDF_MAGIC_BYTES):
|
||||
raise ValidationError(
|
||||
"File content does not match expected PDF format. "
|
||||
"The file may be corrupted.",
|
||||
code="invalid_file_content",
|
||||
)
|
||||
return
|
||||
# Office files are ZIP-based
|
||||
if not content.startswith(self.OFFICE_MAGIC_BYTES):
|
||||
raise ValidationError(
|
||||
"Le contenu du fichier ne correspond pas au format attendu. "
|
||||
"Le fichier est peut-etre corrompu ou n'est pas un document Office valide.",
|
||||
"File content does not match expected Office format. "
|
||||
"The file may be corrupted or not a valid Office document.",
|
||||
code="invalid_file_content",
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user