Files
zulip/zerver/migrations/0439_fix_deleteduser_email.py
Alex Vandiver ed4de6da4a migrations: Add a migration to fix invalid deleted user emails.
208c0c3034 fixed this for new deleted users, but left existing users
with potentially invalid email addresses.  This is problematic if the
realm is ever exported and re-imported, as the addresses will not
validate.

Add a migration which attempts to fix these invalid email addresses.
2023-04-19 10:01:03 -07:00

74 lines
2.5 KiB
Python

# Generated by Django 4.2 on 2023-04-17 18:25
from email.headerregistry import Address
from functools import lru_cache
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
from django.db.models import Q
@lru_cache
def get_fake_email_domain(apps: StateApps, realm_id: int) -> str:
Realm = apps.get_model("zerver", "Realm")
realm = Realm.objects.get(id=realm_id)
# Build out realm.host
subdomain = realm.string_id
if subdomain == "":
host = settings.EXTERNAL_HOST
else:
default_host = f"{subdomain}.{settings.EXTERNAL_HOST}"
host = settings.REALM_HOSTS.get(subdomain, default_host)
# Implement get_fake_email_domain
try:
validate_email(Address(username="bot", domain=host).addr_spec)
return realm.host
except ValidationError:
pass
try:
# Check that the fake email domain can be used to form valid email addresses.
validate_email(Address(username="bot", domain=settings.FAKE_EMAIL_DOMAIN).addr_spec)
return settings.FAKE_EMAIL_DOMAIN
except ValidationError:
raise Exception(
settings.FAKE_EMAIL_DOMAIN + " is not a valid domain. "
"Consider setting the FAKE_EMAIL_DOMAIN setting."
)
def fix_invalid_emails(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
"""Find deleted users prior to the fix in 208c0c303405, which have
invalid delivery_email values; fixing them allows them to survive
an export/import.
"""
UserProfile = apps.get_model("zerver", "UserProfile")
invalid_users = UserProfile.objects.filter(is_active=False).filter(
Q(delivery_email__icontains="@https://") | Q(delivery_email__icontains="@http://")
)
for invalid_user in invalid_users:
local_part = invalid_user.delivery_email.split("@")[0]
invalid_user.delivery_email = (
local_part + "@" + get_fake_email_domain(apps, invalid_user.realm_id)
)
invalid_user.save(update_fields=["delivery_email"])
class Migration(migrations.Migration):
dependencies = [
("zerver", "0438_add_web_mark_read_on_scroll_policy_setting"),
]
operations = [
migrations.RunPython(
fix_invalid_emails, reverse_code=migrations.RunPython.noop, elidable=True
),
]