diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py index 42a2fc3b52..201c223d12 100644 --- a/zerver/lib/actions.py +++ b/zerver/lib/actions.py @@ -24,7 +24,7 @@ from zerver.lib.message import ( message_to_dict, render_markdown, ) -from zerver.models import Realm, RealmEmoji, Stream, UserProfile, UserActivity, \ +from zerver.models import Realm, RealmEmoji, Stream, UserProfile, UserActivity, RealmAlias, \ Subscription, Recipient, Message, Attachment, UserMessage, valid_stream_name, \ Client, DefaultStream, UserPresence, Referral, PushDeviceToken, MAX_SUBJECT_LENGTH, \ MAX_MESSAGE_LENGTH, get_client, get_stream, get_recipient, get_huddle, \ @@ -1976,6 +1976,7 @@ def get_realm_creation_defaults(org_type=None, restricted_to_domain=None, invite def do_create_realm(domain, name, subdomain=None, restricted_to_domain=None, invite_required=None, org_type=None): # type: (text_type, text_type, Optional[text_type], Optional[bool], Optional[bool], Optional[int]) -> Tuple[Realm, bool] + domain = domain.lower() realm = get_realm(domain) created = not realm if created: @@ -1989,6 +1990,9 @@ def do_create_realm(domain, name, subdomain=None, restricted_to_domain=None, restricted_to_domain=restricted_to_domain, invite_required=invite_required) realm.save() + realmalias = RealmAlias(realm=realm, domain=domain) + realmalias.save() + # Create stream once Realm object has been saved notifications_stream, _ = create_stream_if_needed(realm, Realm.DEFAULT_NOTIFICATION_STREAM_NAME) realm.notifications_stream = notifications_stream diff --git a/zerver/migrations/0033_migrate_domain_to_realmalias.py b/zerver/migrations/0033_migrate_domain_to_realmalias.py new file mode 100644 index 0000000000..d9430fd92d --- /dev/null +++ b/zerver/migrations/0033_migrate_domain_to_realmalias.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations +from django.db.backends.postgresql_psycopg2.schema import DatabaseSchemaEditor +from django.db.migrations.state import StateApps + +def add_domain_to_realm_alias_if_needed(apps, schema_editor): + # type: (StateApps, DatabaseSchemaEditor) -> None + Realm = apps.get_model('zerver', 'Realm') + RealmAlias = apps.get_model('zerver', 'RealmAlias') + + for realm in Realm.objects.all(): + # if realm.domain already exists in RealmAlias, assume it is correct + if not RealmAlias.objects.filter(domain=realm.domain).exists(): + RealmAlias.objects.create(realm=realm, domain=realm.domain) + +class Migration(migrations.Migration): + + dependencies = [ + ('zerver', '0032_verify_all_medium_avatar_images'), + ] + + operations = [ + migrations.RunPython(add_domain_to_realm_alias_if_needed) + ] diff --git a/zerver/models.py b/zerver/models.py index 2744ef9f8f..98f333cacc 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -240,6 +240,7 @@ post_save.connect(flush_realm, sender=Realm) class RealmAlias(models.Model): realm = models.ForeignKey(Realm, null=True) # type: Optional[Realm] + # should always be stored lowercase domain = models.CharField(max_length=80, db_index=True, unique=True) # type: text_type # These functions should only be used on email addresses that have diff --git a/zerver/tests/test_messages.py b/zerver/tests/test_messages.py index 45133c29d0..4caae0ea4d 100644 --- a/zerver/tests/test_messages.py +++ b/zerver/tests/test_messages.py @@ -26,7 +26,7 @@ from zerver.lib.test_helpers import ( from zerver.models import ( MAX_MESSAGE_LENGTH, MAX_SUBJECT_LENGTH, - Message, Realm, Recipient, Stream, UserMessage, UserProfile, Attachment, + Message, Realm, Recipient, Stream, UserMessage, UserProfile, Attachment, RealmAlias, get_realm, get_stream, get_user_profile_by_email, ) @@ -50,6 +50,12 @@ from six.moves import range from typing import Any, Optional class TestCrossRealmPMs(ZulipTestCase): + def make_realm(self, domain): + # type: (text_type) -> Realm + realm = Realm.objects.create(domain=domain) + RealmAlias.objects.create(realm=realm, domain=domain) + return realm + def setUp(self): # type: () -> None settings.CROSS_REALM_BOT_EMAILS.add('test-og-bot@zulip.com') @@ -71,7 +77,7 @@ class TestCrossRealmPMs(ZulipTestCase): def test_same_realm(self): # type: () -> None """Users on the same realm can PM each other""" - r1 = Realm.objects.create(domain='1.example.com') + r1 = self.make_realm('1.example.com') deployment = Deployment.objects.filter()[0] deployment.realms.add(r1) @@ -89,8 +95,8 @@ class TestCrossRealmPMs(ZulipTestCase): def test_different_realms(self): # type: () -> None """Users on the different realms can not PM each other""" - r1 = Realm.objects.create(domain='1.example.com') - r2 = Realm.objects.create(domain='2.example.com') + r1 = self.make_realm('1.example.com') + r2 = self.make_realm('2.example.com') deployment = Deployment.objects.filter()[0] deployment.realms.add(r1) deployment.realms.add(r2) @@ -107,9 +113,9 @@ class TestCrossRealmPMs(ZulipTestCase): def test_three_different_realms(self): # type: () -> None """Users on three different realms can not PM each other""" - r1 = Realm.objects.create(domain='1.example.com') - r2 = Realm.objects.create(domain='2.example.com') - r3 = Realm.objects.create(domain='3.example.com') + r1 = self.make_realm('1.example.com') + r2 = self.make_realm('2.example.com') + r3 = self.make_realm('3.example.com') deployment = Deployment.objects.filter()[0] deployment.realms.add(r1) deployment.realms.add(r2) @@ -129,7 +135,7 @@ class TestCrossRealmPMs(ZulipTestCase): def test_from_zulip_realm(self): # type: () -> None """OG Users in the zulip.com realm can PM any realm""" - r1 = Realm.objects.create(domain='1.example.com') + r1 = self.make_realm('1.example.com') deployment = Deployment.objects.filter()[0] deployment.realms.add(r1) @@ -147,7 +153,7 @@ class TestCrossRealmPMs(ZulipTestCase): def test_to_zulip_realm(self): # type: () -> None """All users can PM users in the zulip.com realm""" - r1 = Realm.objects.create(domain='1.example.com') + r1 = self.make_realm('1.example.com') deployment = Deployment.objects.filter()[0] deployment.realms.add(r1) @@ -165,8 +171,8 @@ class TestCrossRealmPMs(ZulipTestCase): def test_zulip_realm_can_not_join_realms(self): # type: () -> None """Adding a zulip.com user to a PM will not let you cross realms""" - r1 = Realm.objects.create(domain='1.example.com') - r2 = Realm.objects.create(domain='2.example.com') + r1 = self.make_realm('1.example.com') + r2 = self.make_realm('2.example.com') deployment = Deployment.objects.filter()[0] deployment.realms.add(r1) deployment.realms.add(r2) diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index 60134016f6..1e6110530c 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -10,7 +10,7 @@ from zerver.views import do_change_password from zerver.views.invite import get_invitee_emails_set from zerver.models import ( get_realm, get_prereg_user_by_email, get_user_profile_by_email, - PreregistrationUser, Realm, Recipient, ScheduledJob, UserProfile, UserMessage, + PreregistrationUser, Realm, RealmAlias, Recipient, ScheduledJob, UserProfile, UserMessage, ) from zerver.lib.actions import ( @@ -632,6 +632,10 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(realm.domain, domain) self.assertEqual(get_user_profile_by_email(email).realm, realm) + # Make sure the RealmAlias is created + realmalias = RealmAlias.objects.get(domain = domain) + self.assertEqual(realmalias.realm, realm) + # Check defaults self.assertEquals(realm.org_type, Realm.COMMUNITY) self.assertEquals(realm.restricted_to_domain, False) diff --git a/zilencer/management/commands/populate_db.py b/zilencer/management/commands/populate_db.py index 80ae182b6c..537456d652 100644 --- a/zilencer/management/commands/populate_db.py +++ b/zilencer/management/commands/populate_db.py @@ -7,7 +7,7 @@ from django.utils.timezone import now from django.contrib.sites.models import Site from zerver.models import Message, UserProfile, Stream, Recipient, Client, \ - Subscription, Huddle, get_huddle, Realm, UserMessage, \ + Subscription, Huddle, get_huddle, Realm, UserMessage, RealmAlias, \ get_huddle_hash, clear_database, get_client, get_user_profile_by_id, \ split_email_to_domain, email_to_username from zerver.lib.actions import STREAM_ASSIGNMENT_COLORS, do_send_message, set_default_streams, \ @@ -123,9 +123,13 @@ class Command(BaseCommand): clear_database() # Create our two default realms + # Could in theory be done via zerver.lib.actions.do_create_realm, but + # welcome-bot (needed for do_create_realm) hasn't been created yet zulip_realm = Realm.objects.create(domain="zulip.com", name="Zulip Dev", subdomain="zulip") + RealmAlias.objects.create(realm=zulip_realm, domain="zulip.com") if options["test_suite"]: - Realm.objects.create(domain="mit.edu") + mit_realm = Realm.objects.create(domain="mit.edu", name="MIT", subdomain="mit") + RealmAlias.objects.create(realm=mit_realm, domain="mit.edu") realms = {} # type: Dict[text_type, Realm] for realm in Realm.objects.all(): realms[realm.domain] = realm