Spaces:
Running
Running
File size: 3,553 Bytes
09801ca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | """
Developer Models — Webhook integrations, webhook delivery logs, and API call audit metrics.
"""
import uuid
from datetime import datetime
from typing import Optional
from sqlalchemy import String, Boolean, Text, Integer, Index, ForeignKey
from sqlalchemy.dialects.postgresql import UUID, JSONB
from sqlalchemy.orm import Mapped, mapped_column
from app.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin
class WebhookEndpoint(UUIDPrimaryKeyMixin, TimestampMixin, Base):
"""Developer registered HTTP webhook listeners."""
__tablename__ = "webhook_endpoints"
__table_args__ = (
Index("ix_webhook_endpoints_user_id", "user_id"),
)
user_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id", ondelete="CASCADE"),
nullable=False,
)
url: Mapped[str] = mapped_column(Text, nullable=False)
secret_key: Mapped[str] = mapped_column(String(255), nullable=False)
subscribed_events: Mapped[dict] = mapped_column(JSONB, default=list, nullable=False) # ['model.trained', 'dataset.uploaded']
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
def __repr__(self) -> str:
return f"<WebhookEndpoint url={self.url}>"
class WebhookDelivery(UUIDPrimaryKeyMixin, Base):
"""Webhook HTTP dispatch attempt log."""
__tablename__ = "webhook_deliveries"
__table_args__ = (
Index("ix_webhook_deliveries_webhook_id", "webhook_id"),
)
webhook_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("webhook_endpoints.id", ondelete="CASCADE"),
nullable=False,
)
event_type: Mapped[str] = mapped_column(String(100), nullable=False)
payload_json: Mapped[dict] = mapped_column(JSONB, nullable=False)
response_status_code: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
response_body: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
duration_ms: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
is_success: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
delivered_at: Mapped[datetime] = mapped_column(server_default="now()", nullable=False)
def __repr__(self) -> str:
return f"<WebhookDelivery webhook={self.webhook_id} status={self.response_status_code}>"
class APICallLog(UUIDPrimaryKeyMixin, Base):
"""API request metric and rate limit log."""
__tablename__ = "api_call_logs"
__table_args__ = (
Index("ix_api_call_logs_user_id", "user_id"),
Index("ix_api_call_logs_api_key_id", "api_key_id"),
)
user_id: Mapped[Optional[uuid.UUID]] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id", ondelete="CASCADE"),
nullable=True,
)
api_key_id: Mapped[Optional[uuid.UUID]] = mapped_column(
UUID(as_uuid=True),
ForeignKey("api_keys.id", ondelete="SET NULL"),
nullable=True,
)
endpoint: Mapped[str] = mapped_column(String(255), nullable=False)
http_method: Mapped[str] = mapped_column(String(10), nullable=False)
status_code: Mapped[int] = mapped_column(Integer, nullable=False)
response_time_ms: Mapped[int] = mapped_column(Integer, nullable=False)
ip_address: Mapped[Optional[str]] = mapped_column(String(45), nullable=True)
created_at: Mapped[datetime] = mapped_column(server_default="now()", nullable=False)
def __repr__(self) -> str:
return f"<APICallLog endpoint={self.endpoint} status={self.status_code}>"
|