- users.py: list_users, create_user, update_user_status, initiate_password_reset, update_ai_config, delete_user, create_system_topic (7 routes) - quotas.py: get_user_quota, update_user_quota (2 routes) - ai.py: get_ai_config_models, test_ai_connection, get_ai_config, update_system_ai_config (4 routes); validate_provider_id call-through (D-11) - shared.py: _user_to_dict helper (T-02-27 / SEC-07 field whitelist) - __init__.py: router aggregator with prefix=/api/admin; 13 routes total - admin.py monolith renamed to admin_OLD_REMOVE_IN_TASK_3.py (deleted in task 3) - All sub-routers have NO prefix (D-04) - All handlers inject Depends(get_current_admin) (T-08-04-01)
29 lines
966 B
Python
29 lines
966 B
Python
"""Shared helpers for the admin API package.
|
|
|
|
These helpers are used by 2+ admin sub-modules and must not live in __init__.py
|
|
to avoid circular imports (T-08-04-04, RESEARCH.md Pitfall 2).
|
|
|
|
_ai_config_to_dict lives in ai.py (only ai.py uses it — local is correct).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from db.models import User
|
|
|
|
|
|
def _user_to_dict(user: User) -> dict:
|
|
"""Return a safe subset of User fields — never includes password_hash,
|
|
credentials_enc, totp_secret, or any document content (T-02-27, SEC-07).
|
|
"""
|
|
return {
|
|
"id": str(user.id),
|
|
"handle": user.handle,
|
|
"email": user.email,
|
|
"role": user.role,
|
|
"is_active": user.is_active,
|
|
"totp_enabled": user.totp_enabled,
|
|
"ai_provider": user.ai_provider,
|
|
"ai_model": user.ai_model,
|
|
"password_must_change": user.password_must_change,
|
|
"created_at": user.created_at.isoformat() if user.created_at else None,
|
|
}
|