fc / apps /cases /api /folder_binding_api.py
jun2024's picture
Upload 2241 files
b4f2238 verified
Raw History Blame Contribute Delete
6.04 kB
"""案件文件夹绑定 API"""
from __future__ import annotations
import logging
from typing import Any
from django.http import HttpRequest
from ninja import Router
from apps.cases.schemas import (
CaseFolderBindingCreateSchema,
CaseFolderBindingResponseSchema,
FolderBrowseEntrySchema,
FolderBrowseResponseSchema,
)
from apps.core.security import get_request_access_context
logger = logging.getLogger("apps.cases.api")
router = Router()
def _get_folder_binding_service() -> Any:
"""工厂函数:获取案件文件夹绑定服务"""
from apps.cases.services import CaseFolderBindingService # type: ignore[attr-defined]
from apps.core.dependencies import (
build_case_service_with_deps,
build_client_service,
build_contract_query_service,
build_document_service,
)
return CaseFolderBindingService(
document_service=build_document_service(),
case_service=build_case_service_with_deps(
contract_service=build_contract_query_service(),
client_service=build_client_service(),
),
)
@router.post("/{case_id}/folder-binding", response=CaseFolderBindingResponseSchema)
def create_folder_binding(request: HttpRequest, case_id: int, data: CaseFolderBindingCreateSchema) -> Any:
"""创建或更新案件文件夹绑定"""
service = _get_folder_binding_service()
ctx = get_request_access_context(request)
binding = service.create_binding_ctx(case_id=case_id, folder_path=data.folder_path, ctx=ctx)
is_accessible: bool = service.check_folder_accessible(binding.folder_path)
display_path: str = service.format_path_for_display(binding.folder_path)
logger.info(
"case_folder_binding_upsert",
extra={
"action": "case_folder_binding_upsert",
"case_id": case_id,
"folder_path": str(getattr(binding, "folder_path", "") or ""),
"display_path": str(display_path or ""),
"is_accessible": bool(is_accessible),
"user_id": getattr(getattr(ctx, "user", None), "id", None),
},
)
return CaseFolderBindingResponseSchema.from_binding(
binding,
is_accessible=is_accessible,
display_path=display_path,
)
@router.get("/{case_id}/folder-binding", response=CaseFolderBindingResponseSchema | None)
def get_folder_binding(request: HttpRequest, case_id: int) -> CaseFolderBindingResponseSchema | None:
"""获取案件文件夹绑定信息"""
service = _get_folder_binding_service()
ctx = get_request_access_context(request)
binding = service.get_binding_ctx(case_id=case_id, ctx=ctx)
if not binding:
return None
is_accessible: bool = service.check_folder_accessible(binding.folder_path)
display_path: str = service.format_path_for_display(binding.folder_path)
return CaseFolderBindingResponseSchema.from_binding(binding, is_accessible=is_accessible, display_path=display_path)
@router.delete("/{case_id}/folder-binding")
def delete_folder_binding(request: HttpRequest, case_id: int) -> dict[str, bool | str]:
"""删除案件文件夹绑定"""
service = _get_folder_binding_service()
ctx = get_request_access_context(request)
success: bool = service.delete_binding_ctx(case_id=case_id, ctx=ctx)
logger.info(
"case_folder_binding_delete",
extra={
"action": "case_folder_binding_delete",
"case_id": case_id,
"success": bool(success),
"user_id": getattr(getattr(ctx, "user", None), "id", None),
},
)
return {"success": success, "message": "文件夹绑定删除成功" if success else "未找到绑定记录"}
@router.get("/folder-browse", response=FolderBrowseResponseSchema)
def browse_folders(request: HttpRequest, path: str | None = None, include_hidden: bool = False) -> Any:
service = _get_folder_binding_service()
ctx = get_request_access_context(request)
service.require_admin(ctx)
if not path or not str(path).strip():
default_path = service.get_default_browse_path()
if default_path:
path = str(default_path)
else:
roots = service.get_browse_roots()
entries = [FolderBrowseEntrySchema(name=(p.name or str(p)), path=str(p)) for p in roots]
logger.info(
"case_folder_browse_roots",
extra={
"action": "case_folder_browse_roots",
"include_hidden": bool(include_hidden),
"roots_count": len(roots),
"user_id": getattr(getattr(ctx, "user", None), "id", None),
},
)
return FolderBrowseResponseSchema(
browsable=True,
message=None,
path=None,
parent_path=None,
entries=entries,
)
browsable, browse_message = service.is_browsable_path(str(path))
if not browsable:
return FolderBrowseResponseSchema(
browsable=False,
message=browse_message,
path=str(path).strip(),
parent_path=None,
entries=[],
)
resolved = service.resolve_under_allowed_roots(str(path))
entries = [
FolderBrowseEntrySchema(**item) for item in service.list_subdirs(str(path), include_hidden=include_hidden)
]
parent_path: str | None = service.compute_parent_path(resolved)
logger.info(
"case_folder_browse",
extra={
"action": "case_folder_browse",
"path": str(path).strip(),
"resolved_path": str(resolved),
"include_hidden": bool(include_hidden),
"entries_count": len(entries),
"user_id": getattr(getattr(ctx, "user", None), "id", None),
},
)
return FolderBrowseResponseSchema(
browsable=True,
message=None,
path=str(resolved),
parent_path=parent_path,
entries=entries,
)