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

This commit is contained in:
upstream-mirror
2026-09-15 15:05:30 +05:00
commit 64898b2c79
8999 changed files with 1757358 additions and 0 deletions

View 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,),
),
]

View File

@@ -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"
)
],
},
),
]

View 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"),
),
],
),
]

View 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",),
),
]

View 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(),
),
]

View 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"
),
),
]

View File

@@ -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),
),
]

View 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")},
),
]

View 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,
),
]

View File

@@ -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,
),
]

View File

@@ -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),
),
]

View File

@@ -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),
),
]

View 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"
),
),
]

View 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"
),
),
]

View File

@@ -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"
),
),
]

View 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),
),
]

View File

@@ -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,
),
]

View 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",
),
]

View File