mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
confirmation: Replace RealmCreationKey - use Confirmation instead.
Fixes #20028. There's no reason to have a special `RealmCreationKey` class - the `Confirmation` system already does this job. This is somewhat complicated by the need to write a migration for `RealmCreationKey`->`Confirmation` for pre-existing, valid objects, to avoid breaking realm creation links that haven't been used yet.
This commit is contained in:
committed by
Tim Abbott
parent
072f234269
commit
40b1f6eb4e
@@ -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", "0743_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",
|
||||
),
|
||||
]
|
Reference in New Issue
Block a user