# Generated by hand on 2025-12-29 # Creates APIToken and OutboundWebhook tables using raw SQL from django.db import migrations, models import django.db.models.deletion import django.utils.timezone from django.conf import settings from archivebox.uuid_compat import uuid7 from archivebox.base_models.models import get_or_create_system_user_pk import archivebox.api.models import signal_webhooks.fields import signal_webhooks.utils class Migration(migrations.Migration): initial = True dependencies = [ ("auth", "0012_alter_user_first_name_max_length"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.SeparateDatabaseAndState( database_operations=[ migrations.RunSQL( sql=""" -- Create api_apitoken table CREATE TABLE IF NOT EXISTS api_apitoken ( id TEXT PRIMARY KEY NOT NULL, created_at DATETIME NOT NULL, modified_at DATETIME NOT NULL, token VARCHAR(32) NOT NULL UNIQUE, expires DATETIME, created_by_id INTEGER NOT NULL, FOREIGN KEY (created_by_id) REFERENCES auth_user(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS api_apitoken_created_by_id_idx ON api_apitoken(created_by_id); CREATE INDEX IF NOT EXISTS api_apitoken_created_at_idx ON api_apitoken(created_at); CREATE INDEX IF NOT EXISTS api_apitoken_token_idx ON api_apitoken(token); -- Create api_outboundwebhook table CREATE TABLE IF NOT EXISTS api_outboundwebhook ( id TEXT PRIMARY KEY NOT NULL, created_at DATETIME NOT NULL, modified_at DATETIME NOT NULL, name VARCHAR(255) NOT NULL UNIQUE, signal VARCHAR(255) NOT NULL, ref VARCHAR(1024) NOT NULL, endpoint VARCHAR(2048) NOT NULL, headers TEXT NOT NULL DEFAULT '{}', auth_token TEXT NOT NULL DEFAULT '', enabled BOOLEAN NOT NULL DEFAULT 1, keep_last_response BOOLEAN NOT NULL DEFAULT 0, created DATETIME NOT NULL, updated DATETIME NOT NULL, last_response TEXT NOT NULL DEFAULT '', last_success DATETIME, last_failure DATETIME, created_by_id INTEGER NOT NULL, FOREIGN KEY (created_by_id) REFERENCES auth_user(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS api_outboundwebhook_created_by_id_idx ON api_outboundwebhook(created_by_id); CREATE INDEX IF NOT EXISTS api_outboundwebhook_created_at_idx ON api_outboundwebhook(created_at); CREATE INDEX IF NOT EXISTS api_outboundwebhook_name_idx ON api_outboundwebhook(name); CREATE INDEX IF NOT EXISTS api_outboundwebhook_ref_idx ON api_outboundwebhook(ref); """, reverse_sql=""" DROP TABLE IF EXISTS api_outboundwebhook; DROP TABLE IF EXISTS api_apitoken; """, ), ], state_operations=[ migrations.CreateModel( name="APIToken", fields=[ ("id", models.UUIDField(default=uuid7, editable=False, primary_key=True, serialize=False, unique=True)), ("created_at", models.DateTimeField(db_index=True, default=django.utils.timezone.now)), ("modified_at", models.DateTimeField(auto_now=True)), ("token", models.CharField(default=archivebox.api.models.generate_secret_token, max_length=32, unique=True)), ("expires", models.DateTimeField(blank=True, null=True)), ( "created_by", models.ForeignKey( default=get_or_create_system_user_pk, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, ), ), ], options={ "verbose_name": "API Key", "verbose_name_plural": "API Keys", "app_label": "api", }, ), migrations.CreateModel( name="OutboundWebhook", fields=[ ("id", models.UUIDField(default=uuid7, editable=False, primary_key=True, serialize=False, unique=True)), ("created_at", models.DateTimeField(db_index=True, default=django.utils.timezone.now)), ("modified_at", models.DateTimeField(auto_now=True)), ( "name", models.CharField(db_index=True, help_text="Webhook name.", max_length=255, unique=True, verbose_name="name"), ), ( "signal", models.CharField( choices=[ ("CREATE", "Create"), ("UPDATE", "Update"), ("DELETE", "Delete"), ("M2M", "M2M changed"), ("CREATE_OR_UPDATE", "Create or Update"), ("CREATE_OR_DELETE", "Create or Delete"), ("CREATE_OR_M2M", "Create or M2M changed"), ("UPDATE_OR_DELETE", "Update or Delete"), ("UPDATE_OR_M2M", "Update or M2M changed"), ("DELETE_OR_M2M", "Delete or M2M changed"), ("CREATE_UPDATE_OR_DELETE", "Create, Update or Delete"), ("CREATE_UPDATE_OR_M2M", "Create, Update or M2M changed"), ("CREATE_DELETE_OR_M2M", "Create, Delete or M2M changed"), ("UPDATE_DELETE_OR_M2M", "Update, Delete or M2M changed"), ("CREATE_UPDATE_DELETE_OR_M2M", "Create, Update or Delete, or M2M changed"), ], help_text="Signal the webhook fires to.", max_length=255, verbose_name="signal", ), ), ( "ref", models.CharField( db_index=True, help_text="Dot import notation to the model the webhook is for.", max_length=1023, validators=[signal_webhooks.utils.model_from_reference], verbose_name="referenced model", ), ), ( "endpoint", models.URLField(help_text="Target endpoint for this webhook.", max_length=2047, verbose_name="endpoint"), ), ( "headers", models.JSONField( blank=True, default=dict, help_text="Headers to send with the webhook request.", validators=[signal_webhooks.utils.is_dict], verbose_name="headers", ), ), ( "auth_token", signal_webhooks.fields.TokenField( blank=True, default="", help_text="Authentication token to use in an Authorization header.", max_length=8000, validators=[signal_webhooks.utils.decode_cipher_key], verbose_name="authentication token", ), ), ("enabled", models.BooleanField(default=True, help_text="Is this webhook enabled?", verbose_name="enabled")), ( "keep_last_response", models.BooleanField( default=False, help_text="Should the webhook keep a log of the latest response it got?", verbose_name="keep last response", ), ), ( "created", models.DateTimeField(auto_now_add=True, help_text="When the webhook was created.", verbose_name="created"), ), ( "updated", models.DateTimeField(auto_now=True, help_text="When the webhook was last updated.", verbose_name="updated"), ), ( "last_response", models.CharField( blank=True, default="", help_text="Latest response to this webhook.", max_length=8000, verbose_name="last response", ), ), ( "last_success", models.DateTimeField( default=None, help_text="When the webhook last succeeded.", null=True, verbose_name="last success", ), ), ( "last_failure", models.DateTimeField( default=None, help_text="When the webhook last failed.", null=True, verbose_name="last failure", ), ), ( "created_by", models.ForeignKey( default=get_or_create_system_user_pk, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, ), ), ], options={ "verbose_name": "API Outbound Webhook", "app_label": "api", }, ), migrations.AddConstraint( model_name="outboundwebhook", constraint=models.UniqueConstraint(fields=["ref", "endpoint"], name="prevent_duplicate_hooks_api_outboundwebhook"), ), ], ), ]