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,16 +1,18 @@
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
import tempfile
|
||||
from typing import Optional
|
||||
import threading
|
||||
|
||||
from fastapi import HTTPException, Request
|
||||
from pydantic import BaseModel
|
||||
from fastapi import HTTPException, Request, status, Depends
|
||||
|
||||
import config
|
||||
|
||||
|
||||
def get_rbac_file():
|
||||
return os.path.join(config.VOLUME_ROOT, "docker/nas-dashboard/rbac.json")
|
||||
|
||||
|
||||
_rbac_lock = threading.RLock()
|
||||
|
||||
ROLE_GROUP_MAP = {
|
||||
@@ -75,7 +77,7 @@ def save_rbac(data: dict):
|
||||
_atomic_json_write(get_rbac_file(), data)
|
||||
|
||||
|
||||
def resolve_role(groups: list[str]) -> Optional[str]:
|
||||
def resolve_role(groups: list[str]) -> str | None:
|
||||
for group in groups:
|
||||
if group in ROLE_GROUP_MAP:
|
||||
return ROLE_GROUP_MAP[group]
|
||||
@@ -107,6 +109,7 @@ def get_sidebar_order(username: str) -> dict | None:
|
||||
def save_sidebar_order(username: str, order: dict):
|
||||
def mutator(rbac):
|
||||
rbac.setdefault("user_overrides", {}).setdefault(username, {})["sidebar_order"] = order
|
||||
|
||||
update_rbac(mutator)
|
||||
|
||||
|
||||
@@ -118,26 +121,32 @@ def has_page_access(user: User, page: str) -> bool:
|
||||
|
||||
def require_page(page: str):
|
||||
"""FastAPI dependency factory — 403 if user lacks page access."""
|
||||
|
||||
async def checker(request: Request):
|
||||
user: User = request.state.user
|
||||
if not has_page_access(user, page):
|
||||
raise HTTPException(status_code=403, detail="Access denied")
|
||||
|
||||
return checker
|
||||
|
||||
|
||||
def require_admin():
|
||||
"""FastAPI dependency — 403 if user is not admin."""
|
||||
|
||||
async def checker(request: Request):
|
||||
user: User = request.state.user
|
||||
if user.role != "admin":
|
||||
raise HTTPException(status_code=403, detail="Admin only")
|
||||
|
||||
return checker
|
||||
|
||||
|
||||
def require_write():
|
||||
"""FastAPI dependency — 403 if viewer tries non-GET method."""
|
||||
|
||||
async def checker(request: Request):
|
||||
user: User = request.state.user
|
||||
if user.role == "viewer" and request.method != "GET":
|
||||
raise HTTPException(status_code=403, detail="Read-only access")
|
||||
|
||||
return checker
|
||||
|
||||
Reference in New Issue
Block a user