Files
ShiErFeng/shierfeng-fastapi-backend/module_business/service/test_batch_access_service.py
T

82 lines
3.1 KiB
Python

from sqlalchemy.ext.asyncio import AsyncSession
from exceptions.exception import PermissionException
from module_admin.entity.vo.user_vo import CurrentUserModel
from module_business.dao.test_batch_dao import TestBatchDao
from module_business.domain.enums import TestBatchStatus
from module_business.domain.test_batch_scope import TestBatchScope
from module_business.entity.do.test_batch_do import BizTestBatch
class TestBatchAccessService:
"""测试批次作用域与管理权限校验。"""
@staticmethod
def _is_super_admin(current_user: CurrentUserModel) -> bool:
return current_user.user is not None and current_user.user.admin is True
@staticmethod
def _raise_unavailable() -> None:
raise PermissionException({'reason': 'TEST_BATCH_UNAVAILABLE'}, '当前测试批次不可用')
@staticmethod
def _raise_closed() -> None:
raise PermissionException({'reason': 'TEST_BATCH_UNAVAILABLE'}, '当前测试批次已关闭')
@classmethod
def assert_super_admin(cls, current_user: CurrentUserModel) -> None:
"""确保当前用户由超级管理员标记明确授信。"""
if not cls._is_super_admin(current_user):
raise PermissionException('', '仅超级管理员可执行测试批次管理操作')
@classmethod
async def resolve_scope(
cls,
db: AsyncSession,
current_user: CurrentUserModel,
batch_id: int | None,
*,
write: bool = False,
) -> TestBatchScope:
"""解析并验证业务请求可使用的数据作用域。"""
if batch_id is None:
return TestBatchScope.formal()
batch = await TestBatchDao.get_batch(db, batch_id)
if batch is None or batch.status == TestBatchStatus.PURGED.value:
cls._raise_unavailable()
if not cls._is_super_admin(current_user):
user_id = current_user.user.user_id if current_user.user is not None else None
if user_id is None or not await TestBatchDao.user_is_authorized(db, batch_id, user_id):
cls._raise_unavailable()
if batch.status == TestBatchStatus.CLOSED.value:
if write:
cls._raise_closed()
cls._raise_unavailable()
if batch.status != TestBatchStatus.ACTIVE.value:
cls._raise_unavailable()
return TestBatchScope(
batch_id=batch_id,
mode='TEST',
status=TestBatchStatus.ACTIVE,
writable=True,
)
@classmethod
async def lock_active_batch(cls, db: AsyncSession, scope: TestBatchScope) -> BizTestBatch | None:
"""在写入前锁定并重新确认测试批次仍为 ACTIVE。"""
if scope.mode == 'FORMAL':
return None
batch = await TestBatchDao.get_batch_for_update(db, scope.batch_id)
if batch is None or batch.status == TestBatchStatus.PURGED.value:
cls._raise_unavailable()
if batch.status == TestBatchStatus.CLOSED.value:
cls._raise_closed()
if batch.status != TestBatchStatus.ACTIVE.value:
cls._raise_unavailable()
return batch