change_subdomain: Create a deactivated realm on updating subdomain.

When changing the subdomain of a realm, create a deactivated realm with
the old subdomain of the realm, and set its deactivated_redirect to the
new subdomain.
Doing this will help us to do the following:
- When a user visits the old subdomain of a realm, we can tell the user
that the realm has been moved.
- During the registration process, we can assure that the old subdomain
of the realm is not used to create a new realm.

If the subdomain is changed multiple times, the deactivated_redirect
fields of all the deactivated realms are updated to point to the new
uri.
This commit is contained in:
Siddharth Asthana 2020-12-19 00:47:20 +05:30 committed by Alex Vandiver
parent 42dfd98607
commit 6c888977a6
4 changed files with 64 additions and 4 deletions

View File

@ -745,7 +745,8 @@ class TestSupportEndpoint(ZulipTestCase):
realm_id = lear_realm.id
lear_realm = get_realm('new-name')
self.assertEqual(lear_realm.id, realm_id)
self.assertFalse(Realm.objects.filter(string_id='lear').exists())
self.assertTrue(Realm.objects.filter(string_id='lear').exists())
self.assertTrue(Realm.objects.filter(string_id='lear')[0].deactivated)
result = self.client_post("/activity/support", {"realm_id": f"{lear_realm.id}", "new_subdomain": "new-name"})
self.assert_in_success_response(["Subdomain unavailable. Please choose a different one."], result)
@ -753,6 +754,9 @@ class TestSupportEndpoint(ZulipTestCase):
result = self.client_post("/activity/support", {"realm_id": f"{lear_realm.id}", "new_subdomain": "zulip"})
self.assert_in_success_response(["Subdomain unavailable. Please choose a different one."], result)
result = self.client_post("/activity/support", {"realm_id": f"{lear_realm.id}", "new_subdomain": "lear"})
self.assert_in_success_response(["Subdomain unavailable. Please choose a different one."], result)
def test_downgrade_realm(self) -> None:
cordelia = self.example_user('cordelia')
self.login_user(cordelia)

View File

@ -856,9 +856,26 @@ def do_reactivate_realm(realm: Realm) -> None:
}).decode())
def do_change_realm_subdomain(realm: Realm, new_subdomain: str) -> None:
old_subdomain = realm.subdomain
old_uri = realm.uri
realm.string_id = new_subdomain
realm.save(update_fields=["string_id"])
# If a realm if being renamed multiple times, we should find all the placeholder
# realms and reset their deactivated_redirect field to point to the new realm uri
placeholder_realms = Realm.objects.filter(deactivated_redirect=old_uri,
deactivated=True)
for placeholder_realm in placeholder_realms:
do_add_deactivated_redirect(placeholder_realm, realm.uri)
# When we change a realm's subdomain the realm with old subdomain is basically
# deactivated. We are creating a deactivated realm using old subdomain and setting
# it's deactivated redirect to new_subdomain so that we can tell the users that
# the realm has been moved to a new subdomain.
placeholder_realm = do_create_realm(old_subdomain, "placeholder-realm")
do_deactivate_realm(placeholder_realm)
do_add_deactivated_redirect(placeholder_realm, realm.uri)
def do_add_deactivated_redirect(realm: Realm, redirect_url: str) -> None:
realm.deactivated_redirect = redirect_url
realm.save(update_fields=["deactivated_redirect"])

View File

@ -184,9 +184,10 @@ class RealmTest(ZulipTestCase):
do_change_realm_subdomain(realm, "newzulip")
user = get_user_profile_by_email('hamlet@zulip.com')
self.assertEqual(user.realm.string_id, "newzulip")
# This doesn't use a cache right now, but may later.
with self.assertRaises(Realm.DoesNotExist):
get_realm("zulip")
placeholder_realm = get_realm("zulip")
self.assertTrue(placeholder_realm.deactivated)
self.assertEqual(placeholder_realm.deactivated_redirect, user.realm.uri)
def test_do_deactivate_realm_clears_scheduled_jobs(self) -> None:
user = self.example_user('hamlet')

View File

@ -35,6 +35,7 @@ from zerver.lib.actions import (
add_new_user_history,
do_add_default_stream,
do_change_full_name,
do_change_realm_subdomain,
do_change_user_role,
do_create_default_stream_group,
do_create_realm,
@ -182,6 +183,25 @@ class DeactivationNoticeTestCase(ZulipTestCase):
result = self.client_get('/accounts/deactivated/')
self.assertIn('It has moved to <a href="http://example.zulipchat.com">http://example.zulipchat.com</a>.', result.content.decode())
def test_deactivation_notice_when_realm_subdomain_is_changed(self) -> None:
realm = get_realm("zulip")
do_change_realm_subdomain(realm, "new-subdomain-name")
result = self.client_get('/accounts/deactivated/')
self.assertIn('It has moved to <a href="http://new-subdomain-name.testserver">http://new-subdomain-name.testserver</a>.', result.content.decode())
def test_deactivated_redirect_field_of_placeholder_realms_are_modified_on_changing_subdomain_multiple_times(self) -> None:
realm = get_realm('zulip')
do_change_realm_subdomain(realm, 'new-name-1')
result = self.client_get('/accounts/deactivated/')
self.assertIn('It has moved to <a href="http://new-name-1.testserver">http://new-name-1.testserver</a>.', result.content.decode())
realm = get_realm('new-name-1')
do_change_realm_subdomain(realm, 'new-name-2')
result = self.client_get('/accounts/deactivated/')
self.assertIn('It has moved to <a href="http://new-name-2.testserver">http://new-name-2.testserver</a>.', result.content.decode())
class AddNewUserHistoryTest(ZulipTestCase):
def test_add_new_user_history_race(self) -> None:
"""Sends a message during user creation"""
@ -2523,6 +2543,24 @@ class RealmCreationTest(ZulipTestCase):
self.assertEqual(result.status_code, 302)
self.assertTrue(result.url.startswith('http://a-0.testserver/accounts/login/subdomain/'))
@override_settings(OPEN_REALM_CREATION=True)
def test_create_realm_using_old_subdomain_of_a_realm(self) -> None:
realm = get_realm("zulip")
do_change_realm_subdomain(realm, "new-name")
password = "test"
email = "user1@test.com"
realm_name = "Test"
result = self.client_post('/new/', {'email': email})
self.client_get(result["Location"])
confirmation_url = self.get_confirmation_url_from_outbox(email)
self.client_get(confirmation_url)
result = self.submit_reg_form_for_user(email, password,
realm_subdomain = "zulip",
realm_name = realm_name)
self.assert_in_response("Subdomain unavailable. Please choose a different one.", result)
@override_settings(OPEN_REALM_CREATION=True)
def test_subdomain_restrictions_root_domain(self) -> None:
password = "test"