feat: 5 улучшений безопасности и UX
1. ✅ Прогресс бар загрузки: - Upload компонент с showUploadList - Кнопка показывает состояние 'Загрузка...' - Визуальный прогресс для каждого файла 2. ✅ OCR проверка полиса (заготовка): - TODO: проверка что загружен полис, а не шляпа - Если шляпа - помечаем себе в policyValidationWarning - Пользователю не говорим (silent validation) 3. ✅ Лимиты файлов: - Максимум 10 файлов - Каждый файл до 15MB - Валидация на фронте и бэкенде - Счетчик: 'Загружено: X/10 файлов' - Кнопка disabled при 10 файлах 4. ✅ Защита от инъекций и безопасность: Backend (upload.py): - Лимит файлов: if len(files) > 10 - Проверка размера: if len(content) > MAX_FILE_SIZE - Валидация типа: allowed_types = ['image/', 'application/pdf'] - Санитизация folder: allowed_folders whitelist Backend (draft.py): - Валидация session_id (max 255 chars) - Валидация step: only [1, 2, 3] - Параметризованные SQL запросы (защита от SQL injection) Frontend: - beforeUpload валидация размера - maxCount={10} - accept только разрешенные форматы 5. ✅ Кнопка 'Начать заново': - Показывается на шаге 2 и 3 (extra в Card) - Сбрасывает всю форму - Возвращает на шаг 1 - Очищает isPhoneVerified Безопасность: - SQL инъекции: параметризованные запросы ($1, $2) - XSS: Pydantic валидация всех inputs - File upload: type + size validation - Path traversal: folder whitelist - Rate limiting: TODO (Redis) UX: - Прогресс загрузки виден - Понятные лимиты (10 файлов по 15MB) - Возможность начать заново в любой момент
This commit is contained in:
@@ -161,20 +161,49 @@ async def upload_files(files: List[UploadFile] = File(...), folder: str = "claim
|
||||
Поддерживает множественную загрузку
|
||||
|
||||
Args:
|
||||
files: Список файлов для загрузки
|
||||
files: Список файлов для загрузки (макс 10 файлов по 15MB)
|
||||
folder: Папка в S3 (claims, policies, documents и т.д.)
|
||||
|
||||
Returns:
|
||||
List[dict]: Список загруженных файлов с URLs
|
||||
"""
|
||||
# Защита: лимит файлов
|
||||
if len(files) > 10:
|
||||
raise HTTPException(status_code=400, detail="Максимум 10 файлов за раз")
|
||||
|
||||
# Защита: санитизация folder
|
||||
allowed_folders = ['claims', 'policies', 'documents', 'passports', 'tickets']
|
||||
if folder not in allowed_folders:
|
||||
folder = 'claims'
|
||||
|
||||
try:
|
||||
uploaded_files = []
|
||||
MAX_FILE_SIZE = 15 * 1024 * 1024 # 15MB
|
||||
|
||||
for file in files:
|
||||
try:
|
||||
# Читаем содержимое файла
|
||||
content = await file.read()
|
||||
|
||||
# Защита: проверка размера файла
|
||||
if len(content) > MAX_FILE_SIZE:
|
||||
uploaded_files.append({
|
||||
"success": False,
|
||||
"filename": file.filename,
|
||||
"error": f"Файл больше 15MB ({len(content) / 1024 / 1024:.1f}MB)"
|
||||
})
|
||||
continue
|
||||
|
||||
# Защита: валидация типа файла
|
||||
allowed_types = ['image/', 'application/pdf']
|
||||
if file.content_type and not any(file.content_type.startswith(t) for t in allowed_types):
|
||||
uploaded_files.append({
|
||||
"success": False,
|
||||
"filename": file.filename,
|
||||
"error": f"Недопустимый тип файла: {file.content_type}"
|
||||
})
|
||||
continue
|
||||
|
||||
# Загружаем в S3
|
||||
file_url = await s3_service.upload_file(
|
||||
file_content=content,
|
||||
|
||||
Reference in New Issue
Block a user