99 lines
3.5 KiB
Python
99 lines
3.5 KiB
Python
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Depends
|
|
from sqlmodel import Session
|
|
|
|
from ..connectors.prowlarr import ProwlarrConnector
|
|
from ..db.session import get_session
|
|
from ..services.approval_service import create_approval
|
|
from ..services.audit_logger import log_event
|
|
from ..services.policy_engine import evaluate_policy
|
|
from .connector_runtime import load_connector_runtime
|
|
|
|
router = APIRouter(prefix='/api/apps/prowlarr', dependencies=[Depends(load_connector_runtime)])
|
|
|
|
|
|
@router.get('/health')
|
|
def health():
|
|
return ProwlarrConnector().health()
|
|
|
|
|
|
@router.get('/indexers')
|
|
def indexers():
|
|
return ProwlarrConnector().indexer_status()
|
|
|
|
|
|
@router.get('/applications')
|
|
def applications():
|
|
return ProwlarrConnector().application_status()
|
|
|
|
|
|
@router.get('/indexer-health')
|
|
def indexer_health():
|
|
return ProwlarrConnector().indexer_health()
|
|
|
|
|
|
@router.get('/sync-status')
|
|
def sync_status():
|
|
return ProwlarrConnector().sync_status()
|
|
|
|
|
|
@router.get('/search-test')
|
|
def search_test(q: str = '', source: str = 'manual', session: Session = Depends(get_session)):
|
|
query = q.strip()
|
|
if not query:
|
|
return {'success': False, 'status': 'error', 'message': 'query_required', 'total': 0, 'items': []}
|
|
|
|
identity = source.strip() or 'manual'
|
|
policy = evaluate_policy(session=session, action='prowlarr.search_test', target='prowlarr', source=identity)
|
|
risk = str(policy.get('risk', 'medium'))
|
|
|
|
if policy['decision'] == 'blocked':
|
|
audit = log_event(
|
|
session,
|
|
source='action',
|
|
identity=identity,
|
|
action_id='prowlarr.search_test',
|
|
target='prowlarr',
|
|
risk=risk,
|
|
policy_decision='blocked',
|
|
reason=policy['reason'],
|
|
result='blocked',
|
|
redacted_metadata={'query': query, 'downloadAllowed': False},
|
|
)
|
|
return {'success': False, 'decision': 'blocked', 'status': 'failed', 'policy_decision': 'blocked', 'result': 'blocked', 'message': policy['reason'], 'auditId': audit.id}
|
|
|
|
if policy['decision'] == 'approval_required':
|
|
approval = create_approval(session, action='prowlarr.search_test', target='prowlarr', source=identity, risk=risk, reason=policy['reason'], requester=identity)
|
|
audit = log_event(
|
|
session,
|
|
source='action',
|
|
identity=identity,
|
|
action_id='prowlarr.search_test',
|
|
target='prowlarr',
|
|
risk=risk,
|
|
policy_decision='approval_required',
|
|
reason=policy['reason'],
|
|
result='approval_requested',
|
|
redacted_metadata={'query': query, 'approval_id': approval.id, 'downloadAllowed': False},
|
|
)
|
|
return {'success': False, 'decision': 'approval_required', 'status': 'failed', 'policy_decision': 'approval_required', 'result': 'approval_required', 'message': 'Action requires approval before execution.', 'approvalId': approval.id, 'auditId': audit.id}
|
|
|
|
result = ProwlarrConnector().search_test(query)
|
|
success = bool(result.get('success'))
|
|
audit = log_event(
|
|
session,
|
|
source='action',
|
|
identity=identity,
|
|
action_id='prowlarr.search_test',
|
|
target='prowlarr',
|
|
risk=risk,
|
|
policy_decision='allowed',
|
|
reason=policy['reason'],
|
|
result='success' if success else 'failed',
|
|
redacted_metadata={'query': query, 'resultCount': int(result.get('total', 0)), 'downloadAllowed': False},
|
|
)
|
|
result['auditId'] = audit.id
|
|
result['downloadAllowed'] = False
|
|
return result
|