"""Threat actor endpoints. Provides listing, detail, coverage analysis, and gap analysis for threat actor profiles imported from MITRE CTI. """ import logging from typing import Optional from fastapi import APIRouter, Depends, Query from sqlalchemy.orm import Session from app.database import get_db from app.dependencies.auth import get_current_user from app.models.user import User from app.services.threat_actor_service import ( get_actor_coverage, get_actor_detail, get_actor_gaps, list_actors, ) logger = logging.getLogger(__name__) router = APIRouter(prefix="/threat-actors", tags=["threat-actors"]) @router.get("") def list_threat_actors( search: Optional[str] = Query(None), country: Optional[str] = Query(None), motivation: Optional[str] = Query(None), sophistication: Optional[str] = Query(None), target_sectors: Optional[str] = Query(None), offset: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=200), db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """List threat actors with optional filters and pagination. **Requires** authentication (any role). """ return list_actors( db, search=search, country=country, motivation=motivation, sophistication=sophistication, target_sectors=target_sectors, offset=offset, limit=limit, ) @router.get("/{actor_id}") def get_threat_actor( actor_id: str, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Get detailed info about a threat actor including techniques. **Requires** authentication (any role). """ return get_actor_detail(db, actor_id) @router.get("/{actor_id}/coverage") def get_threat_actor_coverage( actor_id: str, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Calculate coverage percentage against a specific threat actor. **Requires** authentication (any role). Returns the percentage of the actor's techniques that have been validated or partially validated, along with a breakdown. """ return get_actor_coverage(db, actor_id) @router.get("/{actor_id}/gaps") def get_threat_actor_gaps( actor_id: str, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Identify techniques of this actor that are NOT fully validated. **Requires** authentication (any role). Returns list of gap techniques with available templates. """ return get_actor_gaps(db, actor_id)