snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
This commit is contained in:
39
confirmation/migrations/0001_initial.py
Normal file
39
confirmation/migrations/0001_initial.py
Normal file
@@ -0,0 +1,39 @@
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("contenttypes", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Confirmation",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
verbose_name="ID", serialize=False, auto_created=True, primary_key=True
|
||||
),
|
||||
),
|
||||
("object_id", models.PositiveIntegerField()),
|
||||
("date_sent", models.DateTimeField(verbose_name="sent")),
|
||||
(
|
||||
"confirmation_key",
|
||||
models.CharField(max_length=40, verbose_name="activation key"),
|
||||
),
|
||||
(
|
||||
"content_type",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="contenttypes.ContentType"
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "confirmation email",
|
||||
"verbose_name_plural": "confirmation emails",
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,90 @@
|
||||
# Generated by Django 5.0.7 on 2024-08-13 19:41
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [
|
||||
("confirmation", "0001_initial"),
|
||||
("confirmation", "0002_realmcreationkey"),
|
||||
("confirmation", "0003_emailchangeconfirmation"),
|
||||
("confirmation", "0004_remove_confirmationmanager"),
|
||||
("confirmation", "0005_confirmation_realm"),
|
||||
("confirmation", "0006_realmcreationkey_presume_email_valid"),
|
||||
("confirmation", "0007_add_indexes"),
|
||||
("confirmation", "0008_confirmation_expiry_date"),
|
||||
("confirmation", "0009_confirmation_expiry_date_backfill"),
|
||||
("confirmation", "0010_alter_confirmation_expiry_date"),
|
||||
("confirmation", "0011_alter_confirmation_expiry_date"),
|
||||
("confirmation", "0012_alter_confirmation_id"),
|
||||
("confirmation", "0013_alter_realmcreationkey_id"),
|
||||
("confirmation", "0014_confirmation_confirmatio_content_80155a_idx"),
|
||||
]
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
("contenttypes", "0001_initial"),
|
||||
("zerver", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="RealmCreationKey",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
(
|
||||
"creation_key",
|
||||
models.CharField(db_index=True, max_length=40, verbose_name="activation key"),
|
||||
),
|
||||
(
|
||||
"date_created",
|
||||
models.DateTimeField(default=django.utils.timezone.now, verbose_name="created"),
|
||||
),
|
||||
("presume_email_valid", models.BooleanField(default=False)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Confirmation",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
("object_id", models.PositiveIntegerField(db_index=True)),
|
||||
("date_sent", models.DateTimeField(db_index=True)),
|
||||
("confirmation_key", models.CharField(db_index=True, max_length=40)),
|
||||
(
|
||||
"content_type",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="contenttypes.contenttype"
|
||||
),
|
||||
),
|
||||
("type", models.PositiveSmallIntegerField()),
|
||||
(
|
||||
"realm",
|
||||
models.ForeignKey(
|
||||
null=True, on_delete=django.db.models.deletion.CASCADE, to="zerver.realm"
|
||||
),
|
||||
),
|
||||
("expiry_date", models.DateTimeField(db_index=True, null=True)),
|
||||
],
|
||||
options={
|
||||
"unique_together": {("type", "confirmation_key")},
|
||||
"indexes": [
|
||||
models.Index(
|
||||
fields=["content_type", "object_id"], name="confirmatio_content_80155a_idx"
|
||||
)
|
||||
],
|
||||
},
|
||||
),
|
||||
]
|
||||
27
confirmation/migrations/0002_realmcreationkey.py
Normal file
27
confirmation/migrations/0002_realmcreationkey.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="RealmCreationKey",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
verbose_name="ID", serialize=False, auto_created=True, primary_key=True
|
||||
),
|
||||
),
|
||||
("creation_key", models.CharField(max_length=40, verbose_name="activation key")),
|
||||
(
|
||||
"date_created",
|
||||
models.DateTimeField(default=django.utils.timezone.now, verbose_name="created"),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
19
confirmation/migrations/0003_emailchangeconfirmation.py
Normal file
19
confirmation/migrations/0003_emailchangeconfirmation.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 1.10.4 on 2017-01-17 09:16
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0002_realmcreationkey"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="EmailChangeConfirmation",
|
||||
fields=[],
|
||||
options={
|
||||
"proxy": True,
|
||||
},
|
||||
bases=("confirmation.confirmation",),
|
||||
),
|
||||
]
|
||||
34
confirmation/migrations/0004_remove_confirmationmanager.py
Normal file
34
confirmation/migrations/0004_remove_confirmationmanager.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# Generated by Django 1.11.2 on 2017-07-08 04:23
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0003_emailchangeconfirmation"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name="EmailChangeConfirmation",
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name="confirmation",
|
||||
options={},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="confirmation",
|
||||
name="type",
|
||||
field=models.PositiveSmallIntegerField(default=1),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="confirmation",
|
||||
name="confirmation_key",
|
||||
field=models.CharField(max_length=40),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="confirmation",
|
||||
name="date_sent",
|
||||
field=models.DateTimeField(),
|
||||
),
|
||||
]
|
||||
20
confirmation/migrations/0005_confirmation_realm.py
Normal file
20
confirmation/migrations/0005_confirmation_realm.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# Generated by Django 1.11.6 on 2017-11-30 00:13
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("zerver", "0001_initial"),
|
||||
("confirmation", "0004_remove_confirmationmanager"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="confirmation",
|
||||
name="realm",
|
||||
field=models.ForeignKey(
|
||||
null=True, on_delete=django.db.models.deletion.CASCADE, to="zerver.Realm"
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 1.11.6 on 2018-01-29 18:39
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0005_confirmation_realm"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="realmcreationkey",
|
||||
name="presume_email_valid",
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
||||
36
confirmation/migrations/0007_add_indexes.py
Normal file
36
confirmation/migrations/0007_add_indexes.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# Generated by Django 2.2.10 on 2020-03-27 09:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0006_realmcreationkey_presume_email_valid"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="confirmation",
|
||||
name="confirmation_key",
|
||||
field=models.CharField(db_index=True, max_length=40),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="confirmation",
|
||||
name="date_sent",
|
||||
field=models.DateTimeField(db_index=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="confirmation",
|
||||
name="object_id",
|
||||
field=models.PositiveIntegerField(db_index=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="realmcreationkey",
|
||||
name="creation_key",
|
||||
field=models.CharField(db_index=True, max_length=40, verbose_name="activation key"),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name="confirmation",
|
||||
unique_together={("type", "confirmation_key")},
|
||||
),
|
||||
]
|
||||
16
confirmation/migrations/0008_confirmation_expiry_date.py
Normal file
16
confirmation/migrations/0008_confirmation_expiry_date.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0007_add_indexes"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="confirmation",
|
||||
name="expiry_date",
|
||||
field=models.DateTimeField(db_index=True, null=True),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,70 @@
|
||||
# Generated by Django 3.1.7 on 2021-03-31 20:47
|
||||
|
||||
import time
|
||||
from datetime import timedelta
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, transaction
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
from django.db.migrations.state import StateApps
|
||||
|
||||
|
||||
def set_expiry_date_for_existing_confirmations(
|
||||
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
|
||||
) -> None:
|
||||
Confirmation = apps.get_model("confirmation", "Confirmation")
|
||||
if not Confirmation.objects.exists():
|
||||
return
|
||||
|
||||
# The values at the time of this migration
|
||||
INVITATION = 2
|
||||
UNSUBSCRIBE = 4
|
||||
MULTIUSE_INVITE = 6
|
||||
|
||||
@transaction.atomic
|
||||
def backfill_confirmations_between(lower_bound: int, upper_bound: int) -> None:
|
||||
confirmations = Confirmation.objects.filter(id__gte=lower_bound, id__lte=upper_bound)
|
||||
for confirmation in confirmations:
|
||||
if confirmation.type in (INVITATION, MULTIUSE_INVITE):
|
||||
confirmation.expiry_date = confirmation.date_sent + timedelta(
|
||||
days=settings.INVITATION_LINK_VALIDITY_DAYS
|
||||
)
|
||||
elif confirmation.type == UNSUBSCRIBE:
|
||||
# Unsubscribe links never expire, which we apparently implement as in 1M days.
|
||||
confirmation.expiry_date = confirmation.date_sent + timedelta(days=1000000)
|
||||
else:
|
||||
confirmation.expiry_date = confirmation.date_sent + timedelta(
|
||||
days=settings.CONFIRMATION_LINK_DEFAULT_VALIDITY_DAYS
|
||||
)
|
||||
Confirmation.objects.bulk_update(confirmations, ["expiry_date"])
|
||||
|
||||
# Because the ranges in this code are inclusive, subtracting 1 offers round numbers.
|
||||
BATCH_SIZE = 1000 - 1
|
||||
|
||||
first_id = Confirmation.objects.earliest("id").id
|
||||
last_id = Confirmation.objects.latest("id").id
|
||||
|
||||
id_range_lower_bound = first_id
|
||||
id_range_upper_bound = first_id + BATCH_SIZE
|
||||
while id_range_lower_bound <= last_id:
|
||||
print(f"Processed {id_range_lower_bound} / {last_id}")
|
||||
backfill_confirmations_between(id_range_lower_bound, id_range_upper_bound)
|
||||
id_range_lower_bound = id_range_upper_bound + 1
|
||||
id_range_upper_bound = id_range_lower_bound + BATCH_SIZE
|
||||
time.sleep(0.1)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
atomic = False
|
||||
|
||||
dependencies = [
|
||||
("confirmation", "0008_confirmation_expiry_date"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
set_expiry_date_for_existing_confirmations,
|
||||
reverse_code=migrations.RunPython.noop,
|
||||
elidable=True,
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 3.2.5 on 2021-08-02 19:03
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0009_confirmation_expiry_date_backfill"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="confirmation",
|
||||
name="expiry_date",
|
||||
field=models.DateTimeField(db_index=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 3.2.9 on 2021-11-30 17:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0010_alter_confirmation_expiry_date"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="confirmation",
|
||||
name="expiry_date",
|
||||
field=models.DateTimeField(db_index=True, null=True),
|
||||
),
|
||||
]
|
||||
17
confirmation/migrations/0012_alter_confirmation_id.py
Normal file
17
confirmation/migrations/0012_alter_confirmation_id.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0011_alter_confirmation_expiry_date"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="confirmation",
|
||||
name="id",
|
||||
field=models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
]
|
||||
17
confirmation/migrations/0013_alter_realmcreationkey_id.py
Normal file
17
confirmation/migrations/0013_alter_realmcreationkey_id.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0012_alter_confirmation_id"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="realmcreationkey",
|
||||
name="id",
|
||||
field=models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
from django.contrib.postgres.operations import AddIndexConcurrently
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
atomic = False
|
||||
|
||||
dependencies = [
|
||||
("confirmation", "0013_alter_realmcreationkey_id"),
|
||||
("contenttypes", "0002_remove_content_type_name"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
AddIndexConcurrently(
|
||||
model_name="confirmation",
|
||||
index=models.Index(
|
||||
fields=["content_type", "object_id"], name="confirmatio_content_80155a_idx"
|
||||
),
|
||||
),
|
||||
]
|
||||
17
confirmation/migrations/0015_alter_confirmation_object_id.py
Normal file
17
confirmation/migrations/0015_alter_confirmation_object_id.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0014_confirmation_confirmatio_content_80155a_idx"),
|
||||
# We want to be linking to tables that are already bigints
|
||||
("zerver", "0531_convert_most_ids_to_bigints"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="confirmation",
|
||||
name="object_id",
|
||||
field=models.PositiveBigIntegerField(db_index=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,112 @@
|
||||
# Generated by Django 5.2.3 on 2025-07-04 20:33
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, transaction
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
from django.db.migrations.state import StateApps
|
||||
from django.db.models import Max
|
||||
|
||||
|
||||
def migrate_realmcreationkey_to_realmcreationstatus(
|
||||
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
|
||||
) -> None:
|
||||
"""
|
||||
This migration is for switching from using a separate RealmCreationKey class
|
||||
for realm creation keys to just using the Confirmation system.
|
||||
|
||||
The aim is to iterate through all the existing RealmCreationKey and create
|
||||
a corresponding Confirmation+RealmCreationStatus.
|
||||
|
||||
For validity of these objects, we only need to worry about RealmCreationKeys
|
||||
expired due to time. This is taken care of by making sure we set expiry_date
|
||||
on the Confirmation we're creating.
|
||||
The way the RealmCreationKey system worked was to .delete() the RealmCreationKey
|
||||
objects when they were used - so those simply no longer exist and we don't need to
|
||||
worry about this case.
|
||||
"""
|
||||
CAN_CREATE_REALM = 11
|
||||
|
||||
Confirmation = apps.get_model("confirmation", "Confirmation")
|
||||
ContentType = apps.get_model("contenttypes", "ContentType")
|
||||
RealmCreationKey = apps.get_model("confirmation", "RealmCreationKey")
|
||||
RealmCreationStatus = apps.get_model("zerver", "RealmCreationStatus")
|
||||
realm_creation_status_content_type, _created = ContentType.objects.get_or_create(
|
||||
model="realmcreationstatus", app_label="zerver"
|
||||
)
|
||||
|
||||
BATCH_SIZE = 10000
|
||||
max_id = RealmCreationKey.objects.aggregate(Max("id"))["id__max"]
|
||||
if max_id is None:
|
||||
# Nothing to do.
|
||||
return
|
||||
|
||||
lower_bound = 1
|
||||
while lower_bound <= max_id + (BATCH_SIZE / 2):
|
||||
upper_bound = lower_bound + BATCH_SIZE - 1
|
||||
creation_keys = RealmCreationKey.objects.filter(id__range=(lower_bound, upper_bound))
|
||||
creation_statuses_to_create = []
|
||||
confirmations_to_create = []
|
||||
for creation_key in creation_keys:
|
||||
# These keys were generated in the same way as keys for Confirmation objects,
|
||||
# so we can copy them over without breaking anything.
|
||||
key = creation_key.creation_key
|
||||
date_created = creation_key.date_created
|
||||
presume_email_valid = creation_key.presume_email_valid
|
||||
|
||||
creation_status = RealmCreationStatus(
|
||||
status=0, date_created=date_created, presume_email_valid=presume_email_valid
|
||||
)
|
||||
confirmation = Confirmation(
|
||||
content_type=realm_creation_status_content_type,
|
||||
type=CAN_CREATE_REALM,
|
||||
confirmation_key=key,
|
||||
date_sent=date_created,
|
||||
expiry_date=date_created
|
||||
+ timedelta(days=settings.CAN_CREATE_REALM_LINK_VALIDITY_DAYS),
|
||||
)
|
||||
|
||||
# To attach the Confirmations to RealmCreationStatus objects we need to set the
|
||||
# confirmation.object_id to their respective ids. But we haven't saved
|
||||
# the RealmCreationStatus objs to the database yet - so we don't have ids.
|
||||
#
|
||||
# After we .bulk_create() them, their .id attributes will be populated.
|
||||
# So for now we just link the RealmCreationStatus to the Confirmation
|
||||
# via a temporary ._object attribute - which we'll use later to set
|
||||
# the .object_id as intended.
|
||||
confirmation._object = creation_status
|
||||
|
||||
creation_statuses_to_create.append(creation_status)
|
||||
confirmations_to_create.append(confirmation)
|
||||
with transaction.atomic():
|
||||
RealmCreationStatus.objects.bulk_create(creation_statuses_to_create)
|
||||
|
||||
# Now the objects in creation_statuses_to_create have had their .id
|
||||
# attrs populated. For every confirmation, confirmation._object
|
||||
# points to its corresponding RealmCreationStatus - so now we can
|
||||
# set the confirmation.object_id values and clear out the temporary
|
||||
# ._object attr.
|
||||
for confirmation in confirmations_to_create:
|
||||
confirmation.object_id = confirmation._object.id
|
||||
delattr(confirmation, "_object")
|
||||
Confirmation.objects.bulk_create(confirmations_to_create)
|
||||
|
||||
lower_bound += BATCH_SIZE
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
atomic = False
|
||||
|
||||
dependencies = [
|
||||
("confirmation", "0015_alter_confirmation_object_id"),
|
||||
("zerver", "0747_realmcreationstatus"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
migrate_realmcreationkey_to_realmcreationstatus,
|
||||
reverse_code=migrations.RunPython.noop,
|
||||
elidable=True,
|
||||
),
|
||||
]
|
||||
15
confirmation/migrations/0017_delete_realmcreationkey.py
Normal file
15
confirmation/migrations/0017_delete_realmcreationkey.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# Generated by Django 5.2.3 on 2025-07-04 19:08
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("confirmation", "0016_realmcreationkey_to_realmcreationstatus"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name="RealmCreationKey",
|
||||
),
|
||||
]
|
||||
0
confirmation/migrations/__init__.py
Normal file
0
confirmation/migrations/__init__.py
Normal file
Reference in New Issue
Block a user