|
5 | 5 | from fastapi import APIRouter, Depends, HTTPException, Query |
6 | 6 | from sqlalchemy import func, select |
7 | 7 | from sqlalchemy.ext.asyncio import AsyncSession |
| 8 | +from sqlalchemy.orm import selectinload |
8 | 9 |
|
9 | 10 | from backend.database import get_db |
10 | 11 | from backend.models import ( |
@@ -64,16 +65,23 @@ async def create_channel( |
64 | 65 | try: |
65 | 66 | channel_type = ChannelType(data.channel_type) |
66 | 67 | except ValueError: |
| 68 | + valid = ", ".join(f"'{t.value}'" for t in ChannelType) |
67 | 69 | raise HTTPException( |
68 | 70 | 400, |
69 | | - f"Invalid channel_type: {data.channel_type}. Must be 'slack' or 'email'", |
| 71 | + f"Invalid channel_type: {data.channel_type}. Must be one of: {valid}", |
70 | 72 | ) |
71 | 73 |
|
72 | 74 | # Validate config based on type |
73 | 75 | if channel_type == ChannelType.SLACK and not data.config.get("webhook_url"): |
74 | 76 | raise HTTPException(400, "Slack channels require 'webhook_url' in config") |
75 | 77 | if channel_type == ChannelType.EMAIL and not data.config.get("recipients"): |
76 | 78 | raise HTTPException(400, "Email channels require 'recipients' list in config") |
| 79 | + if channel_type == ChannelType.TEAMS and not data.config.get("webhook_url"): |
| 80 | + raise HTTPException(400, "Teams channels require 'webhook_url' in config") |
| 81 | + if channel_type == ChannelType.WEBHOOK and not data.config.get("webhook_url"): |
| 82 | + raise HTTPException(400, "Webhook channels require 'webhook_url' in config") |
| 83 | + if channel_type == ChannelType.PAGERDUTY and not data.config.get("routing_key"): |
| 84 | + raise HTTPException(400, "PagerDuty channels require 'routing_key' in config") |
77 | 85 |
|
78 | 86 | channel = NotificationChannel( |
79 | 87 | name=data.name, |
@@ -153,25 +161,25 @@ async def test_channel( |
153 | 161 | if not channel: |
154 | 162 | raise HTTPException(404, "Channel not found") |
155 | 163 |
|
156 | | - # Find a recent incident to use as test data, or create a mock |
| 164 | + # Find a recent incident to use as test data, eagerly load alerts |
157 | 165 | stmt = ( |
158 | 166 | select(Incident) |
| 167 | + .options(selectinload(Incident.alerts)) |
159 | 168 | .order_by(Incident.created_at.desc()) |
160 | 169 | .limit(1) |
161 | 170 | ) |
162 | 171 | result = await db.execute(stmt) |
163 | | - incident = result.scalar_one_or_none() |
| 172 | + incident = result.unique().scalar_one_or_none() |
164 | 173 |
|
165 | 174 | if not incident: |
166 | 175 | return {"status": "error", "message": "No incidents available for test notification"} |
167 | 176 |
|
168 | 177 | try: |
169 | | - if channel.channel_type == ChannelType.SLACK: |
170 | | - from backend.core.notifications import _send_slack |
171 | | - await _send_slack(channel, incident, "incident_created") |
172 | | - elif channel.channel_type == ChannelType.EMAIL: |
173 | | - from backend.core.notifications import _send_email |
174 | | - await _send_email(channel, incident, "incident_created") |
| 178 | + from backend.core.notifications import _SENDERS |
| 179 | + sender = _SENDERS.get(channel.channel_type) |
| 180 | + if not sender: |
| 181 | + return {"status": "error", "message": f"Unknown channel type: {channel.channel_type}"} |
| 182 | + await sender(channel, incident, "incident_created") |
175 | 183 | return {"status": "sent"} |
176 | 184 | except Exception as e: |
177 | 185 | return {"status": "error", "message": str(e)} |
|
0 commit comments