This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BreakPilot Dev 19855efacc
Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
feat: BreakPilot PWA - Full codebase (clean push without large binaries)
All services: admin-v2, studio-v2, website, ai-compliance-sdk,
consent-service, klausur-service, voice-service, and infrastructure.
Large PDFs and compiled binaries excluded via .gitignore.
2026-02-11 13:25:58 +01:00

136 lines
4.1 KiB
Python

"""
Webhook Action für Alerts Agent.
Sendet HTTP-Webhooks für Alerts.
"""
import logging
from typing import Dict, Any, List
import httpx
from .base import ActionHandler, ActionResult, ActionType, AlertContext
logger = logging.getLogger(__name__)
class WebhookAction(ActionHandler):
"""
Webhook-Benachrichtigungen für Alerts.
Konfiguration:
- url: Webhook-URL
- method: HTTP-Methode (default: POST)
- headers: Zusätzliche Headers
- include_full_context: Vollen Alert-Kontext senden (default: true)
"""
@property
def action_type(self) -> ActionType:
return ActionType.WEBHOOK
def get_required_config_fields(self) -> List[str]:
return ["url"]
def validate_config(self, config: Dict[str, Any]) -> bool:
url = config.get("url", "")
return url.startswith("http://") or url.startswith("https://")
async def execute(
self,
context: AlertContext,
config: Dict[str, Any],
) -> ActionResult:
"""
Sendet einen Webhook.
Args:
context: Alert-Kontext
config: Webhook-Konfiguration (url, method, headers)
Returns:
ActionResult
"""
try:
url = config.get("url")
method = config.get("method", "POST").upper()
headers = config.get("headers", {})
timeout = config.get("timeout", 30)
# Payload erstellen
payload = self._build_payload(context, config)
# Standard-Headers
headers.setdefault("Content-Type", "application/json")
headers.setdefault("User-Agent", "BreakPilot-AlertsAgent/1.0")
# Request senden
async with httpx.AsyncClient(timeout=timeout) as client:
if method == "POST":
response = await client.post(url, json=payload, headers=headers)
elif method == "PUT":
response = await client.put(url, json=payload, headers=headers)
else:
response = await client.get(url, params=payload, headers=headers)
# Erfolg prüfen
success = 200 <= response.status_code < 300
return ActionResult(
success=success,
action_type=self.action_type,
message=f"Webhook {method} {url} - Status {response.status_code}",
details={
"url": url,
"method": method,
"status_code": response.status_code,
"response_length": len(response.text),
},
error=None if success else f"HTTP {response.status_code}",
)
except httpx.TimeoutException:
logger.error(f"Webhook timeout: {config.get('url')}")
return ActionResult(
success=False,
action_type=self.action_type,
message="Webhook Timeout",
error="Request timed out",
)
except Exception as e:
logger.error(f"Webhook error: {e}")
return ActionResult(
success=False,
action_type=self.action_type,
message="Webhook-Fehler",
error=str(e),
)
def _build_payload(
self,
context: AlertContext,
config: Dict[str, Any],
) -> Dict[str, Any]:
"""Erstellt den Webhook-Payload."""
if config.get("include_full_context", True):
# Voller Kontext
return {
"event": "alert.matched",
"alert": context.to_dict(),
"timestamp": self._get_timestamp(),
}
else:
# Minimal-Payload
return {
"event": "alert.matched",
"alert_id": context.alert_id,
"title": context.title,
"url": context.url,
"timestamp": self._get_timestamp(),
}
def _get_timestamp(self) -> str:
"""Gibt aktuellen ISO-Timestamp zurück."""
from datetime import datetime
return datetime.utcnow().isoformat() + "Z"