Files
SmartUp/backend/app/routers/webhooks.py
T
2026-05-12 17:51:53 +08:00

111 lines
3.4 KiB
Python

"""Webhook configuration CRUD + test notification."""
from __future__ import annotations
import json
from datetime import datetime, timezone
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.database import get_db
from app.models.webhook_config import WebhookConfig
from app.schemas.webhook import WebhookCreate, WebhookUpdate, WebhookResponse
from app.services.webhook_service import send_test_notification
from app.utils.auth import get_current_user
router = APIRouter(prefix="/api/webhooks", tags=["webhooks"])
MASK = "***"
def _to_response(w: WebhookConfig) -> WebhookResponse:
return WebhookResponse(
id=w.id,
name=w.name,
type=w.type,
url=w.url,
secret_masked=MASK if w.secret else "",
enabled=w.enabled,
events=json.loads(w.events_json or "[]"),
created_at=w.created_at,
updated_at=w.updated_at,
)
@router.get("", response_model=List[WebhookResponse])
def list_webhooks(db: Session = Depends(get_db), _=Depends(get_current_user)):
return [_to_response(w) for w in db.query(WebhookConfig).order_by(WebhookConfig.id).all()]
@router.post("", response_model=WebhookResponse, status_code=201)
def create_webhook(
body: WebhookCreate,
db: Session = Depends(get_db),
_=Depends(get_current_user),
):
w = WebhookConfig(
name=body.name,
type=body.type,
url=body.url,
secret=body.secret,
enabled=body.enabled,
events_json=json.dumps(body.events, ensure_ascii=False),
)
db.add(w)
db.commit()
db.refresh(w)
return _to_response(w)
@router.get("/{wid}", response_model=WebhookResponse)
def get_webhook(wid: int, db: Session = Depends(get_db), _=Depends(get_current_user)):
w = db.query(WebhookConfig).filter(WebhookConfig.id == wid).first()
if not w:
raise HTTPException(404, "webhook not found")
return _to_response(w)
@router.put("/{wid}", response_model=WebhookResponse)
def update_webhook(
wid: int,
body: WebhookUpdate,
db: Session = Depends(get_db),
_=Depends(get_current_user),
):
w = db.query(WebhookConfig).filter(WebhookConfig.id == wid).first()
if not w:
raise HTTPException(404, "webhook not found")
data = body.model_dump(exclude_none=True)
if "events" in data:
w.events_json = json.dumps(data.pop("events"), ensure_ascii=False)
if "secret" in data:
if data["secret"] != MASK: # only update if not mask placeholder
w.secret = data.pop("secret")
else:
data.pop("secret")
for k, v in data.items():
setattr(w, k, v)
w.updated_at = datetime.now(timezone.utc)
db.commit()
db.refresh(w)
return _to_response(w)
@router.delete("/{wid}", status_code=204)
def delete_webhook(wid: int, db: Session = Depends(get_db), _=Depends(get_current_user)):
w = db.query(WebhookConfig).filter(WebhookConfig.id == wid).first()
if not w:
raise HTTPException(404, "webhook not found")
db.delete(w)
db.commit()
@router.post("/{wid}/test")
def test_webhook(wid: int, db: Session = Depends(get_db), _=Depends(get_current_user)):
w = db.query(WebhookConfig).filter(WebhookConfig.id == wid).first()
if not w:
raise HTTPException(404, "webhook not found")
ok, msg = send_test_notification(db, w)
return {"success": ok, "message": msg}