Saas-Base / apps /operations /models /webhook.py
rsnarsna
first commit
667aacd
Raw
History Blame Contribute Delete
2.29 kB
"""
Webhook models — webhooks, webhook_deliveries, idempotency_keys.
Maps to AGENT.md DBML: Lines 690-718.
"""
from django.conf import settings
from django.db import models
from core.models import BaseModel
class Webhook(BaseModel):
"""Org-scoped webhook endpoint configuration."""
org = models.ForeignKey(
"organizations.Organization",
on_delete=models.CASCADE,
related_name="webhooks",
)
url = models.URLField()
secret = models.CharField(max_length=255) # Encrypted HMAC key
events = models.JSONField(default=list, blank=True)
enabled = models.BooleanField(default=True)
class Meta:
db_table = "webhooks"
ordering = ["-created_at"]
def __str__(self) -> str:
return f"Webhook {self.url}"
class WebhookDelivery(BaseModel):
"""Records each webhook delivery attempt."""
class Status(models.TextChoices):
SUCCESS = "success", "Success"
FAILED = "failed", "Failed"
PENDING = "pending", "Pending"
webhook = models.ForeignKey(
Webhook,
on_delete=models.CASCADE,
related_name="deliveries",
)
payload_hash = models.CharField(max_length=64, blank=True, default="")
status = models.CharField(max_length=20, choices=Status.choices, default=Status.PENDING)
response_code = models.PositiveIntegerField(default=0)
attempts = models.PositiveIntegerField(default=0)
next_retry_at = models.DateTimeField(null=True, blank=True)
class Meta:
db_table = "webhook_deliveries"
ordering = ["-created_at"]
def __str__(self) -> str:
return f"Delivery {self.pk}{self.get_status_display()}"
class IdempotencyKey(BaseModel):
"""Prevents duplicate request processing."""
key = models.CharField(max_length=255, unique=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="idempotency_keys",
)
request_hash = models.CharField(max_length=64, blank=True, default="")
response_hash = models.CharField(max_length=64, blank=True, default="")
expires_at = models.DateTimeField(null=True, blank=True)
class Meta:
db_table = "idempotency_keys"
def __str__(self) -> str:
return self.key