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:
Agent Zero
2026-08-16 01:17:18 +02:00
parent 3d9b76cea4
commit abbe7a18fc
306 changed files with 5912 additions and 1827 deletions
+16 -18
View File
@@ -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: