Initial curated Unraid-AppOps-Gateway source from 3bd6f6fee310125bfbb4d4650389a817f498724d
This commit is contained in:
commit
1dfbca08a1
528 files changed
+131054
No files matched your search
@@ -0,0 +1,160 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlmodel import Session
|
||||
|
||||
from ..connectors.widefrog import WidefrogConnector
|
||||
from ..db.session import get_session
|
||||
from ..services.approval_service import create_approval
|
||||
from ..services.audit_logger import log_event
|
||||
from ..services.job_runner import complete_job, create_job, set_job_progress, start_job
|
||||
from ..services.policy_engine import evaluate_policy
|
||||
from .connector_runtime import load_connector_runtime
|
||||
|
||||
router = APIRouter(prefix='/api/apps/widefrog', dependencies=[Depends(load_connector_runtime)])
|
||||
|
||||
|
||||
_RETRY_STEPS = [
|
||||
'Validate connector config',
|
||||
'Evaluate policy',
|
||||
'Fetch failed jobs summary',
|
||||
'Call retry endpoint',
|
||||
'Fetch queue/activity summary',
|
||||
'Complete audit/job',
|
||||
]
|
||||
|
||||
_SCAN_STEPS = [
|
||||
'Validate connector config',
|
||||
'Evaluate policy',
|
||||
'Check app health',
|
||||
'Call scan endpoint',
|
||||
'Verify accepted or status',
|
||||
'Complete audit/job',
|
||||
]
|
||||
|
||||
|
||||
@router.get('/health')
|
||||
def health():
|
||||
return WidefrogConnector().health()
|
||||
|
||||
|
||||
@router.get('/queue')
|
||||
def queue():
|
||||
return WidefrogConnector().queue_status()
|
||||
|
||||
|
||||
@router.get('/failed')
|
||||
def failed():
|
||||
return WidefrogConnector().failed_jobs()
|
||||
|
||||
|
||||
@router.get('/activity')
|
||||
def activity():
|
||||
return WidefrogConnector().activity()
|
||||
|
||||
|
||||
@router.get('/download-status')
|
||||
def download_status():
|
||||
return WidefrogConnector().download_status()
|
||||
|
||||
|
||||
@router.post('/retry-failed')
|
||||
def retry_failed(payload: dict | None = None, session: Session = Depends(get_session)):
|
||||
return _execute_widefrog_action(
|
||||
session=session,
|
||||
payload=payload or {},
|
||||
action='widefrog.retry_failed',
|
||||
steps=_RETRY_STEPS,
|
||||
connector_call=lambda connector, body: connector.retry_failed(body),
|
||||
default_success_message='retry_started',
|
||||
)
|
||||
|
||||
|
||||
@router.post('/scan-library')
|
||||
def scan_library(payload: dict | None = None, session: Session = Depends(get_session)):
|
||||
return _execute_widefrog_action(
|
||||
session=session,
|
||||
payload=payload or {},
|
||||
action='widefrog.scan_library',
|
||||
steps=_SCAN_STEPS,
|
||||
connector_call=lambda connector, body: connector.scan_library(body),
|
||||
default_success_message='scan_started',
|
||||
)
|
||||
|
||||
|
||||
def _execute_widefrog_action(
|
||||
*,
|
||||
session: Session,
|
||||
payload: dict[str, Any],
|
||||
action: str,
|
||||
steps: list[str],
|
||||
connector_call: Callable[[WidefrogConnector, dict[str, Any]], dict[str, Any]],
|
||||
default_success_message: str,
|
||||
) -> dict[str, Any]:
|
||||
target = 'widefrog'
|
||||
source = str(payload.get('source', 'manual')).strip() or 'manual'
|
||||
policy = evaluate_policy(session=session, action=action, target=target, source=source)
|
||||
risk = str(policy.get('risk', 'medium'))
|
||||
|
||||
if policy['decision'] == 'blocked':
|
||||
audit = log_event(
|
||||
session,
|
||||
source='action',
|
||||
identity=source,
|
||||
action_id=action,
|
||||
target=target,
|
||||
risk=risk,
|
||||
policy_decision='blocked',
|
||||
reason=policy['reason'],
|
||||
result='blocked',
|
||||
execution_plan={'plan': steps, 'policyReason': policy['reason']},
|
||||
)
|
||||
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=action, target=target, source=source, risk=risk, reason=policy['reason'], requester=source)
|
||||
audit = log_event(
|
||||
session,
|
||||
source='action',
|
||||
identity=source,
|
||||
action_id=action,
|
||||
target=target,
|
||||
risk=risk,
|
||||
policy_decision='approval_required',
|
||||
reason=policy['reason'],
|
||||
result='approval_requested',
|
||||
execution_plan={'plan': steps, 'approvalId': approval.id},
|
||||
redacted_metadata={'approval_id': approval.id},
|
||||
)
|
||||
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}
|
||||
|
||||
job = create_job(session, action_id=action, target=target, source=source, risk=risk, policy_decision='allowed', steps=steps)
|
||||
start_job(session, job)
|
||||
set_job_progress(session, job, 35, 'Policy allowed; calling Widefrog connector.')
|
||||
|
||||
connector_result = connector_call(WidefrogConnector(), payload)
|
||||
success = bool(connector_result.get('success'))
|
||||
message = str(connector_result.get('message', default_success_message if success else 'widefrog_failed'))
|
||||
completed = complete_job(session, job, status='succeeded' if success else 'failed', result_summary=message)
|
||||
audit = log_event(
|
||||
session,
|
||||
source='action',
|
||||
identity=source,
|
||||
action_id=action,
|
||||
target=target,
|
||||
risk=risk,
|
||||
policy_decision='allowed',
|
||||
reason=policy['reason'],
|
||||
result='success' if success else 'failed',
|
||||
execution_plan={'plan': steps, 'jobId': completed.id},
|
||||
after_state={'status': connector_result.get('status'), 'message': message},
|
||||
redacted_metadata={'connector': 'widefrog'},
|
||||
)
|
||||
|
||||
if not success:
|
||||
return {'success': False, 'decision': 'failed', 'status': 'failed', 'policy_decision': 'allowed', 'result': 'failed', 'message': message, 'jobId': completed.id, 'auditId': audit.id, 'data': connector_result.get('data')}
|
||||
|
||||
return {'success': True, 'decision': 'allowed', 'status': 'success', 'policy_decision': 'allowed', 'result': 'success', 'message': message, 'jobId': completed.id, 'auditId': audit.id, 'data': connector_result.get('data', {})}
|
||||
Reference in new issue
Block a user