- Implement comprehensive tests for the ticket board provider to validate kanban and pipeline modes, including ticket movement and error handling. - Create tests for ticket status settable to ensure proper status selection logic. - Enhance web form model tests to cover ticket-specific fields and submission behavior. - Introduce CSV import sheet tests to verify file handling and error reporting. - Add deal aging badge tests to confirm correct display of aging statuses. - Implement tickets selection tests to ensure UI responsiveness and functionality at various screen sizes.
256 lines
9 KiB
Python
256 lines
9 KiB
Python
# Generated by Django 6.1.1 on 2026-09-26 08:16
|
|
|
|
import uuid
|
|
|
|
import django.db.models.deletion
|
|
from django.conf import settings
|
|
from django.db import connection, migrations, models
|
|
|
|
import webhooks.models
|
|
from common.rls import get_disable_policy_sql, get_enable_policy_sql
|
|
|
|
# Registered in common/rls/__init__.py:ORG_SCOPED_TABLES. One list here so the
|
|
# enable and disable directions cannot drift apart.
|
|
WEBHOOK_TABLES = ["webhook_endpoint", "webhook_delivery"]
|
|
|
|
|
|
def enable_rls(apps, schema_editor):
|
|
if connection.vendor != "postgresql":
|
|
return
|
|
with connection.cursor() as cursor:
|
|
for table in WEBHOOK_TABLES:
|
|
cursor.execute(get_enable_policy_sql(table))
|
|
|
|
|
|
def disable_rls(apps, schema_editor):
|
|
if connection.vendor != "postgresql":
|
|
return
|
|
with connection.cursor() as cursor:
|
|
for table in WEBHOOK_TABLES:
|
|
cursor.execute(get_disable_policy_sql(table))
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
initial = True
|
|
|
|
# RLS policy creation cannot run inside an atomic block.
|
|
atomic = False
|
|
|
|
dependencies = [
|
|
# 0042, not the newest: nothing here needs a later common migration.
|
|
("common", "0042_recompute_tag_slugs"),
|
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
]
|
|
|
|
operations = [
|
|
migrations.CreateModel(
|
|
name="WebhookEndpoint",
|
|
fields=[
|
|
(
|
|
"created_at",
|
|
models.DateTimeField(auto_now_add=True, verbose_name="Created At"),
|
|
),
|
|
(
|
|
"updated_at",
|
|
models.DateTimeField(
|
|
auto_now=True, verbose_name="Last Modified At"
|
|
),
|
|
),
|
|
(
|
|
"id",
|
|
models.UUIDField(
|
|
db_index=True,
|
|
default=uuid.uuid4,
|
|
editable=False,
|
|
primary_key=True,
|
|
serialize=False,
|
|
unique=True,
|
|
),
|
|
),
|
|
("url", models.URLField(max_length=500)),
|
|
(
|
|
"description",
|
|
models.CharField(blank=True, default="", max_length=255),
|
|
),
|
|
("events", models.JSONField(default=list)),
|
|
(
|
|
"format",
|
|
models.CharField(
|
|
choices=[
|
|
("json", "Signed JSON"),
|
|
("slack", "Slack incoming webhook"),
|
|
],
|
|
default="json",
|
|
max_length=10,
|
|
),
|
|
),
|
|
("is_active", models.BooleanField(default=True)),
|
|
(
|
|
"disabled_reason",
|
|
models.CharField(blank=True, default="", max_length=255),
|
|
),
|
|
(
|
|
"secret",
|
|
models.CharField(
|
|
default=webhooks.models.generate_secret,
|
|
editable=False,
|
|
max_length=100,
|
|
),
|
|
),
|
|
(
|
|
"created_by",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.SET_NULL,
|
|
related_name="%(class)s_created_by",
|
|
to=settings.AUTH_USER_MODEL,
|
|
verbose_name="Created By",
|
|
),
|
|
),
|
|
(
|
|
"org",
|
|
models.ForeignKey(
|
|
help_text="Organization this record belongs to",
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="%(class)s_set",
|
|
to="common.org",
|
|
),
|
|
),
|
|
(
|
|
"updated_by",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.SET_NULL,
|
|
related_name="%(class)s_updated_by",
|
|
to=settings.AUTH_USER_MODEL,
|
|
verbose_name="Last Modified By",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"db_table": "webhook_endpoint",
|
|
"ordering": ("-created_at",),
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="WebhookDelivery",
|
|
fields=[
|
|
(
|
|
"created_at",
|
|
models.DateTimeField(auto_now_add=True, verbose_name="Created At"),
|
|
),
|
|
(
|
|
"updated_at",
|
|
models.DateTimeField(
|
|
auto_now=True, verbose_name="Last Modified At"
|
|
),
|
|
),
|
|
(
|
|
"id",
|
|
models.UUIDField(
|
|
db_index=True,
|
|
default=uuid.uuid4,
|
|
editable=False,
|
|
primary_key=True,
|
|
serialize=False,
|
|
unique=True,
|
|
),
|
|
),
|
|
("event", models.CharField(max_length=64)),
|
|
("event_id", models.UUIDField()),
|
|
("payload", models.JSONField()),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("pending", "Pending"),
|
|
("succeeded", "Succeeded"),
|
|
("failed", "Failed"),
|
|
],
|
|
default="pending",
|
|
max_length=10,
|
|
),
|
|
),
|
|
("attempts", models.PositiveSmallIntegerField(default=0)),
|
|
(
|
|
"response_status",
|
|
models.PositiveSmallIntegerField(blank=True, null=True),
|
|
),
|
|
("error", models.CharField(blank=True, default="", max_length=255)),
|
|
("next_attempt_at", models.DateTimeField(blank=True, null=True)),
|
|
("last_attempt_at", models.DateTimeField(blank=True, null=True)),
|
|
(
|
|
"created_by",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.SET_NULL,
|
|
related_name="%(class)s_created_by",
|
|
to=settings.AUTH_USER_MODEL,
|
|
verbose_name="Created By",
|
|
),
|
|
),
|
|
(
|
|
"org",
|
|
models.ForeignKey(
|
|
help_text="Organization this record belongs to",
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="%(class)s_set",
|
|
to="common.org",
|
|
),
|
|
),
|
|
(
|
|
"updated_by",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.SET_NULL,
|
|
related_name="%(class)s_updated_by",
|
|
to=settings.AUTH_USER_MODEL,
|
|
verbose_name="Last Modified By",
|
|
),
|
|
),
|
|
(
|
|
"endpoint",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="deliveries",
|
|
to="webhooks.webhookendpoint",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"db_table": "webhook_delivery",
|
|
"ordering": ("-created_at",),
|
|
},
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="webhookendpoint",
|
|
index=models.Index(
|
|
fields=["org", "-created_at"], name="webhook_end_org_id_6f4e49_idx"
|
|
),
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="webhookdelivery",
|
|
index=models.Index(
|
|
fields=["org", "-created_at"], name="webhook_del_org_id_9dcdff_idx"
|
|
),
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="webhookdelivery",
|
|
index=models.Index(
|
|
fields=["endpoint", "-created_at"],
|
|
name="webhook_del_endpoin_de9b03_idx",
|
|
),
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="webhookdelivery",
|
|
index=models.Index(
|
|
fields=["status", "next_attempt_at"],
|
|
name="webhook_del_status_f9cf36_idx",
|
|
),
|
|
),
|
|
migrations.RunPython(enable_rls, reverse_code=disable_rls),
|
|
]
|