Files
minerops/backend/app/repairs/router.py
T

190 lines
5.7 KiB
Python

"""HTTP mapping for explicit repair workflows."""
from typing import Annotated
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, status
from app.identity import require_permission
from app.repairs.dependencies import get_repair_service
from app.repairs.exceptions import (
ControlBoardReplacementActorRequired,
InvalidMacAddress,
RepairActorRequired,
RepairCompletionActorRequired,
RepairConflict,
RepairMinerNotFound,
RepairNotFound,
)
from app.repairs.models import (
BeginRepairRequest,
ControlBoardReplacementRequest,
ControlBoardReplacementResponse,
BeginRepairResponse,
RepairCompleteRequest,
RepairDetailResponse,
RepairTimelineResponse,
)
from app.repairs.service import RepairService
router = APIRouter(prefix="/api/repairs", tags=["repairs"])
control_board_router = APIRouter(prefix="/api/miners", tags=["miners"])
require_repair_create = require_permission("repairs.create")
require_repair_read = require_permission("repairs.read")
require_repair_complete = require_permission("repairs.complete")
require_control_board_replace = require_permission("miners.replace_control_board")
RepairServiceDependency = Annotated[
RepairService,
Depends(get_repair_service),
]
RepairCreateUser = Annotated[dict, Depends(require_repair_create)]
RepairReadUser = Annotated[dict, Depends(require_repair_read)]
RepairCompleteUser = Annotated[dict, Depends(require_repair_complete)]
ControlBoardReplaceUser = Annotated[dict, Depends(require_control_board_replace)]
@control_board_router.post(
"/{miner_id}/replace-control-board",
response_model=ControlBoardReplacementResponse,
)
def replace_control_board(
miner_id: UUID,
request: ControlBoardReplacementRequest,
service: RepairServiceDependency,
current_user: ControlBoardReplaceUser,
) -> ControlBoardReplacementResponse:
try:
result = service.replace_control_board(
miner_id, request,
actor_user_id=UUID(str(current_user["id"])),
)
except RepairMinerNotFound as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Miner not found"
) from exc
except RepairConflict as exc:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail=str(exc)
) from exc
except (InvalidMacAddress, ControlBoardReplacementActorRequired) as exc:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(exc)
) from exc
return ControlBoardReplacementResponse(data=result)
@router.post(
"",
response_model=BeginRepairResponse,
status_code=status.HTTP_201_CREATED,
)
def begin_repair(
request: BeginRepairRequest,
service: RepairServiceDependency,
current_user: RepairCreateUser,
) -> BeginRepairResponse:
try:
repair = service.begin_repair(
request,
actor_user_id=UUID(str(current_user["id"])),
)
except RepairMinerNotFound as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Miner not found",
) from exc
except RepairConflict as exc:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail=str(exc),
) from exc
except RepairActorRequired as exc:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=str(exc),
) from exc
return BeginRepairResponse(data=repair)
@router.post(
"/{repair_id}/complete",
response_model=RepairDetailResponse,
)
def complete_repair(
repair_id: UUID,
request: RepairCompleteRequest,
service: RepairServiceDependency,
current_user: RepairCompleteUser,
) -> RepairDetailResponse:
try:
repair = service.complete_repair(
repair_id,
request,
actor_user_id=UUID(str(current_user["id"])),
)
except RepairNotFound as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Repair not found",
) from exc
except RepairMinerNotFound as exc:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="Repair miner no longer exists",
) from exc
except RepairConflict as exc:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail=str(exc),
) from exc
except RepairCompletionActorRequired as exc:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=str(exc),
) from exc
return RepairDetailResponse(data=repair)
@router.get(
"/{repair_id}",
response_model=RepairDetailResponse,
)
def get_repair(
repair_id: UUID,
service: RepairServiceDependency,
current_user: RepairReadUser,
) -> RepairDetailResponse:
del current_user
try:
repair = service.get_repair(repair_id)
except RepairNotFound as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Repair not found",
) from exc
return RepairDetailResponse(data=repair)
@router.get(
"/{repair_id}/events",
response_model=RepairTimelineResponse,
)
def get_repair_events(
repair_id: UUID,
service: RepairServiceDependency,
current_user: RepairReadUser,
) -> RepairTimelineResponse:
del current_user
try:
timeline = service.get_repair_timeline(repair_id)
except RepairNotFound as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Repair not found",
) from exc
return RepairTimelineResponse(data=timeline)