104 lines
3.3 KiB
Python
104 lines
3.3 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
from fastapi import APIRouter, Depends, Request
|
|
|
|
from app.api.deps import get_api_admin_user
|
|
from app.api.errors import ApiException
|
|
from app.api.responses import success_payload
|
|
from app.api.schemas import (
|
|
AdminScholarHttpSettingsEnvelope,
|
|
AdminScholarHttpSettingsUpdateRequest,
|
|
)
|
|
from app.db.models import User
|
|
from app.logging_utils import structured_log
|
|
from app.settings import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(prefix="/admin/settings", tags=["api-admin-settings"])
|
|
_MAX_USER_AGENT_LENGTH = 512
|
|
_MAX_ACCEPT_LANGUAGE_LENGTH = 128
|
|
_MAX_COOKIE_LENGTH = 8192
|
|
|
|
|
|
def _normalize_header_value(value: str, *, field_name: str, max_length: int) -> str:
|
|
normalized = value.strip()
|
|
if len(normalized) > max_length:
|
|
raise ApiException(
|
|
status_code=400,
|
|
code="invalid_admin_setting",
|
|
message=f"{field_name} must be {max_length} characters or fewer.",
|
|
)
|
|
return normalized
|
|
|
|
|
|
def _serialize_scholar_http_settings() -> dict[str, object]:
|
|
return {
|
|
"user_agent": settings.scholar_http_user_agent,
|
|
"rotate_user_agent": bool(settings.scholar_http_rotate_user_agent),
|
|
"accept_language": settings.scholar_http_accept_language,
|
|
"cookie": settings.scholar_http_cookie,
|
|
}
|
|
|
|
|
|
def _apply_scholar_http_settings(payload: AdminScholarHttpSettingsUpdateRequest) -> None:
|
|
user_agent = _normalize_header_value(
|
|
payload.user_agent,
|
|
field_name="user_agent",
|
|
max_length=_MAX_USER_AGENT_LENGTH,
|
|
)
|
|
accept_language = _normalize_header_value(
|
|
payload.accept_language,
|
|
field_name="accept_language",
|
|
max_length=_MAX_ACCEPT_LANGUAGE_LENGTH,
|
|
)
|
|
cookie = _normalize_header_value(
|
|
payload.cookie,
|
|
field_name="cookie",
|
|
max_length=_MAX_COOKIE_LENGTH,
|
|
)
|
|
object.__setattr__(settings, "scholar_http_user_agent", user_agent)
|
|
object.__setattr__(settings, "scholar_http_rotate_user_agent", bool(payload.rotate_user_agent))
|
|
object.__setattr__(settings, "scholar_http_accept_language", accept_language)
|
|
object.__setattr__(settings, "scholar_http_cookie", cookie)
|
|
|
|
|
|
@router.get(
|
|
"/scholar-http",
|
|
response_model=AdminScholarHttpSettingsEnvelope,
|
|
)
|
|
async def get_scholar_http_settings(
|
|
request: Request,
|
|
admin_user: User = Depends(get_api_admin_user),
|
|
):
|
|
structured_log(
|
|
logger,
|
|
"info",
|
|
"api.admin.settings.scholar_http_read",
|
|
admin_user_id=int(admin_user.id),
|
|
)
|
|
return success_payload(request, data=_serialize_scholar_http_settings())
|
|
|
|
|
|
@router.put(
|
|
"/scholar-http",
|
|
response_model=AdminScholarHttpSettingsEnvelope,
|
|
)
|
|
async def update_scholar_http_settings(
|
|
payload: AdminScholarHttpSettingsUpdateRequest,
|
|
request: Request,
|
|
admin_user: User = Depends(get_api_admin_user),
|
|
):
|
|
_apply_scholar_http_settings(payload)
|
|
structured_log(
|
|
logger,
|
|
"info",
|
|
"api.admin.settings.scholar_http_updated",
|
|
admin_user_id=int(admin_user.id),
|
|
rotate_user_agent=bool(settings.scholar_http_rotate_user_agent),
|
|
user_agent_set=bool(settings.scholar_http_user_agent.strip()),
|
|
cookie_set=bool(settings.scholar_http_cookie.strip()),
|
|
)
|
|
return success_payload(request, data=_serialize_scholar_http_settings())
|