feat: comprehensive test infrastructure improvements
- Fix unit test imports: add env setup in conftest.py before module imports - Add 24 new auth router tests (RBAC, preferences, password validation) - Add 16 new tests for litellm and chat_summary routers - Apply black formatting and ruff linting across codebase - Add pre-commit hooks configuration (black, ruff, file checks) - Increase CI coverage threshold from 40% to 50% Test Results: - 206 tests passing (91 unit + 115 integration) - Coverage: 58.79% on core modules - auth.py: 57% → 85%, litellm.py: 23% → 87%, chat_summary.py: 41% → 100% - auth_service: 96.51%, config: 100%, rbac: 93.48%
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
import docker
|
||||
import re
|
||||
import json
|
||||
from datetime import datetime, timezone, timedelta, time
|
||||
import re
|
||||
from collections import Counter
|
||||
from datetime import datetime, time, timedelta, timezone
|
||||
|
||||
import docker
|
||||
from fastapi import APIRouter, Query
|
||||
|
||||
from config import DOCKER_HOST
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
_client = None
|
||||
|
||||
|
||||
def get_docker_client():
|
||||
"""Get or create Docker client (lazy initialization)."""
|
||||
global _client
|
||||
@@ -17,6 +20,7 @@ def get_docker_client():
|
||||
_client = docker.DockerClient(base_url=DOCKER_HOST, timeout=10)
|
||||
return _client
|
||||
|
||||
|
||||
_tz_cst = timezone(timedelta(hours=8))
|
||||
|
||||
# Suspicious path patterns (scanners, exploits, etc.)
|
||||
@@ -67,9 +71,8 @@ def _parse_authelia_logs(lines: str, limit: int) -> list[dict]:
|
||||
level = obj.get("level", "")
|
||||
msg = obj.get("msg", "")
|
||||
|
||||
is_failed = (
|
||||
level in ("error", "warning")
|
||||
and any(kw in msg.lower() for kw in ("unsuccessful", "banned", "failed", "invalid", "denied"))
|
||||
is_failed = level in ("error", "warning") and any(
|
||||
kw in msg.lower() for kw in ("unsuccessful", "banned", "failed", "invalid", "denied")
|
||||
)
|
||||
# Also catch "not authorized" for anonymous access attempts
|
||||
is_unauthorized = "is not authorized" in msg.lower()
|
||||
@@ -83,14 +86,16 @@ def _parse_authelia_logs(lines: str, limit: int) -> list[dict]:
|
||||
except Exception:
|
||||
ts = ts_raw[:19] if ts_raw else ""
|
||||
|
||||
entries.append({
|
||||
"type": "auth_failure" if is_failed else "unauthorized",
|
||||
"timestamp": ts,
|
||||
"message": msg,
|
||||
"username": obj.get("username", obj.get("user", "")),
|
||||
"ip": obj.get("remote_ip", obj.get("ip", "")),
|
||||
"level": level,
|
||||
})
|
||||
entries.append(
|
||||
{
|
||||
"type": "auth_failure" if is_failed else "unauthorized",
|
||||
"timestamp": ts,
|
||||
"message": msg,
|
||||
"username": obj.get("username", obj.get("user", "")),
|
||||
"ip": obj.get("remote_ip", obj.get("ip", "")),
|
||||
"level": level,
|
||||
}
|
||||
)
|
||||
|
||||
return entries[-limit:]
|
||||
|
||||
@@ -122,18 +127,24 @@ def _parse_caddy_logs(lines: str, limit: int) -> list[dict]:
|
||||
if isinstance(ts_raw, (int, float)):
|
||||
ts = datetime.fromtimestamp(ts_raw, tz=_tz_cst).strftime("%Y-%m-%d %H:%M:%S")
|
||||
else:
|
||||
ts = datetime.fromisoformat(str(ts_raw).replace("Z", "+00:00")).astimezone(_tz_cst).strftime("%Y-%m-%d %H:%M:%S")
|
||||
ts = (
|
||||
datetime.fromisoformat(str(ts_raw).replace("Z", "+00:00"))
|
||||
.astimezone(_tz_cst)
|
||||
.strftime("%Y-%m-%d %H:%M:%S")
|
||||
)
|
||||
except Exception:
|
||||
ts = str(ts_raw)[:19]
|
||||
|
||||
entries.append({
|
||||
"type": "suspicious_request",
|
||||
"timestamp": ts,
|
||||
"message": f"{status} {obj.get('request', {}).get('method', 'GET')} {uri}",
|
||||
"ip": remote_ip,
|
||||
"status": status,
|
||||
"path": uri,
|
||||
})
|
||||
entries.append(
|
||||
{
|
||||
"type": "suspicious_request",
|
||||
"timestamp": ts,
|
||||
"message": f"{status} {obj.get('request', {}).get('method', 'GET')} {uri}",
|
||||
"ip": remote_ip,
|
||||
"status": status,
|
||||
"path": uri,
|
||||
}
|
||||
)
|
||||
|
||||
return entries[-limit:]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user