fix(audit): P0-P3 audit fixes — 838 ruff errors → 0, 30 F821 bugs fixed, 118 files changed
- P0: hooks.py 3-tuple fix, trigger_dispatcher Contract, contacts/plugin unregister_actions_by_owner - P0: 5 test files — check_permission mocks removed, hardcoded DB credential → env var - P1: attachment_service DmsFile via Contract helper, restore_registry/history_hooks dedup - P1: mail/plugin restore unregister, mcp_client datetime.now(UTC), saved_views/filters patterns - P1: ProtectedRoute fail-closed, 13 test assertion fixes (bcrypt, DB-URLs, SECRET_KEYs) - P2: deprecated notifications → post_system_message (3 files), forgejo Base, report_generator lazy import - P2: webhooks permissions, deps.py/roles.py plugin perms removed, import_export default - P2: address/tags/entity_links patterns removed, worker.py Contract-Umgehungen fixed - P2: 28 frontend TODOs (hardcoded constants, deprecated notification API) - P3: dead code, duplicates, deprecated imports, private attr, __import__ inline - P3: 8 frontend TODOs (LucideIcons, inline styles, XSS, i18n) - ruff: 838 → 0 (612 auto-fix + 246 manual + 27 F821 regression fix) - F821: 30 → 0 (AutomationDefinition, DmsFile, user_id, Path, Any, String) - Contract-Umgehungen: 2 neue gefunden (worker.py:169, worker.py:280) und gefixt
This commit is contained in:
+16
-18
@@ -22,9 +22,7 @@ from app.core.db import get_db
|
||||
from app.deps import require_permission
|
||||
from app.services import import_export_service
|
||||
from app.services.import_export_helpers import (
|
||||
detect_format,
|
||||
parse_file,
|
||||
write_csv,
|
||||
write_xlsx,
|
||||
)
|
||||
|
||||
@@ -37,7 +35,7 @@ _BACKGROUND_THRESHOLD = 1000
|
||||
@router.post("/import")
|
||||
async def import_csv(
|
||||
file: UploadFile = File(...),
|
||||
entity_type: str = Form("companies"),
|
||||
entity_type: str = Form(...),
|
||||
field_mapping: str = Form(None),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: dict = Depends(require_permission("import_export:write")),
|
||||
@@ -60,13 +58,13 @@ async def import_csv(
|
||||
try:
|
||||
mapping = json.loads(field_mapping)
|
||||
except json.JSONDecodeError:
|
||||
raise HTTPException(status_code=400, detail="Invalid field_mapping JSON")
|
||||
raise HTTPException(status_code=400, detail="Invalid field_mapping JSON") from None
|
||||
|
||||
# Check row count for background processing
|
||||
try:
|
||||
rows = parse_file(file.filename or "upload.csv", content)
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=400, detail=f"Failed to parse file: {exc}")
|
||||
raise HTTPException(status_code=400, detail=f"Failed to parse file: {exc}") from exc
|
||||
|
||||
if len(rows) > _BACKGROUND_THRESHOLD:
|
||||
# Enqueue as background job
|
||||
@@ -87,7 +85,7 @@ async def import_csv(
|
||||
"total": len(rows),
|
||||
}
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to enqueue import job: {exc}")
|
||||
raise HTTPException(status_code=500, detail=f"Failed to enqueue import job: {exc}") from exc
|
||||
|
||||
# Synchronous import for smaller files
|
||||
result = await import_export_service.import_csv(
|
||||
@@ -105,7 +103,7 @@ async def import_csv(
|
||||
@router.post("/import/preview")
|
||||
async def import_csv_preview(
|
||||
file: UploadFile = File(...),
|
||||
entity_type: str = Form("companies"),
|
||||
entity_type: str = Form(...),
|
||||
current_user: dict = Depends(require_permission("import_export:read")),
|
||||
):
|
||||
"""Preview CSV import (dry-run — no DB changes).
|
||||
@@ -121,7 +119,7 @@ async def import_csv_preview(
|
||||
entity_type=entity_type,
|
||||
)
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=400, detail=f"Failed to parse file: {exc}")
|
||||
raise HTTPException(status_code=400, detail=f"Failed to parse file: {exc}") from exc
|
||||
|
||||
return result
|
||||
|
||||
@@ -129,7 +127,7 @@ async def import_csv_preview(
|
||||
@router.post("/import/validate")
|
||||
async def import_validate(
|
||||
file: UploadFile = File(...),
|
||||
entity_type: str = Form("companies"),
|
||||
entity_type: str = Form(...),
|
||||
field_mapping: str = Form(None),
|
||||
current_user: dict = Depends(require_permission("import_export:read")),
|
||||
):
|
||||
@@ -141,7 +139,7 @@ async def import_validate(
|
||||
try:
|
||||
mapping = json.loads(field_mapping)
|
||||
except json.JSONDecodeError:
|
||||
raise HTTPException(status_code=400, detail="Invalid field_mapping JSON")
|
||||
raise HTTPException(status_code=400, detail="Invalid field_mapping JSON") from None
|
||||
|
||||
try:
|
||||
result = import_export_service.validate_import(
|
||||
@@ -151,7 +149,7 @@ async def import_validate(
|
||||
field_mapping=mapping,
|
||||
)
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=400, detail=f"Failed to validate file: {exc}")
|
||||
raise HTTPException(status_code=400, detail=f"Failed to validate file: {exc}") from exc
|
||||
|
||||
return result
|
||||
|
||||
@@ -192,13 +190,13 @@ async def import_contacts_route(
|
||||
try:
|
||||
mapping = json.loads(field_mapping)
|
||||
except json.JSONDecodeError:
|
||||
raise HTTPException(status_code=400, detail="Invalid field_mapping JSON")
|
||||
raise HTTPException(status_code=400, detail="Invalid field_mapping JSON") from None
|
||||
|
||||
# Check row count for background processing
|
||||
try:
|
||||
rows = parse_file(file.filename or "upload.csv", content)
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=400, detail=f"Failed to parse file: {exc}")
|
||||
raise HTTPException(status_code=400, detail=f"Failed to parse file: {exc}") from exc
|
||||
|
||||
if len(rows) > _BACKGROUND_THRESHOLD:
|
||||
from app.services.import_export_jobs import create_import_job
|
||||
@@ -218,7 +216,7 @@ async def import_contacts_route(
|
||||
"total": len(rows),
|
||||
}
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to enqueue import job: {exc}")
|
||||
raise HTTPException(status_code=500, detail=f"Failed to enqueue import job: {exc}") from exc
|
||||
|
||||
result = await import_export_service.import_contacts(
|
||||
db,
|
||||
@@ -253,13 +251,13 @@ async def import_companies_route(
|
||||
try:
|
||||
mapping = json.loads(field_mapping)
|
||||
except json.JSONDecodeError:
|
||||
raise HTTPException(status_code=400, detail="Invalid field_mapping JSON")
|
||||
raise HTTPException(status_code=400, detail="Invalid field_mapping JSON") from None
|
||||
|
||||
# Check row count for background processing
|
||||
try:
|
||||
rows = parse_file(file.filename or "upload.csv", content)
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=400, detail=f"Failed to parse file: {exc}")
|
||||
raise HTTPException(status_code=400, detail=f"Failed to parse file: {exc}") from exc
|
||||
|
||||
if len(rows) > _BACKGROUND_THRESHOLD:
|
||||
from app.services.import_export_jobs import create_import_job
|
||||
@@ -279,7 +277,7 @@ async def import_companies_route(
|
||||
"total": len(rows),
|
||||
}
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to enqueue import job: {exc}")
|
||||
raise HTTPException(status_code=500, detail=f"Failed to enqueue import job: {exc}") from exc
|
||||
|
||||
result = await import_export_service.import_companies(
|
||||
db,
|
||||
@@ -329,7 +327,7 @@ async def export_data(
|
||||
if not all_rows:
|
||||
raise HTTPException(status_code=404, detail="No data to export")
|
||||
headers = all_rows[0]
|
||||
data_rows = [dict(zip(headers, row)) for row in all_rows[1:]]
|
||||
data_rows = [dict(zip(headers, row, strict=False)) for row in all_rows[1:]]
|
||||
|
||||
if format == "xlsx":
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user