From 54771cfe947f580f4db47553d5f2fa04684acc74 Mon Sep 17 00:00:00 2001 From: Sahil Batra Date: Fri, 3 Mar 2023 16:28:00 +0530 Subject: [PATCH] registration: Create PreregistrationRealm object when creating realm. This commit adds code to create PreregistrationRealm object when creating realm and set it to the content_object field of Confirmation object. --- analytics/tests/test_support_views.py | 10 +- analytics/views/support.py | 12 +- confirmation/models.py | 9 +- zerver/tests/test_external.py | 22 +- zerver/tests/test_management_commands.py | 20 +- zerver/tests/test_signup.py | 283 ++++++++++++++++++----- zerver/views/auth.py | 15 ++ zerver/views/registration.py | 32 ++- 8 files changed, 324 insertions(+), 79 deletions(-) diff --git a/analytics/tests/test_support_views.py b/analytics/tests/test_support_views.py index 072ca7ec5a..11fac2de3d 100644 --- a/analytics/tests/test_support_views.py +++ b/analytics/tests/test_support_views.py @@ -302,7 +302,15 @@ class TestSupportEndpoint(ZulipTestCase): check_zulip_realm_query_result(result) email = self.nonreg_email("alice") - self.client_post("/new/", {"email": email}) + self.client_post( + "/new/", + { + "email": email, + "realm_name": "Zulip test", + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": "zuliptest", + }, + ) result = get_check_query_result(email, 1) check_realm_creation_query_result(result, email) diff --git a/analytics/views/support.py b/analytics/views/support.py index 33bfcdc93f..06ccd64cc6 100644 --- a/analytics/views/support.py +++ b/analytics/views/support.py @@ -35,6 +35,7 @@ from zerver.lib.subdomains import get_subdomain_from_hostname from zerver.lib.validator import check_bool, check_string_in, to_decimal, to_non_negative_int from zerver.models import ( MultiuseInvite, + PreregistrationRealm, PreregistrationUser, Realm, RealmReactivationStatus, @@ -303,11 +304,20 @@ def support( user.id for user in PreregistrationUser.objects.filter(email__in=key_words) ] confirmations += get_confirmations( - [Confirmation.USER_REGISTRATION, Confirmation.INVITATION, Confirmation.REALM_CREATION], + [Confirmation.USER_REGISTRATION, Confirmation.INVITATION], preregistration_user_ids, hostname=request.get_host(), ) + preregistration_realm_ids = [ + user.id for user in PreregistrationRealm.objects.filter(email__in=key_words) + ] + confirmations += get_confirmations( + [Confirmation.REALM_CREATION], + preregistration_realm_ids, + hostname=request.get_host(), + ) + multiuse_invite_ids = [ invite.id for invite in MultiuseInvite.objects.filter(realm__in=realms) ] diff --git a/confirmation/models.py b/confirmation/models.py index d1a43b70b9..be907bd153 100644 --- a/confirmation/models.py +++ b/confirmation/models.py @@ -22,6 +22,7 @@ from zerver.lib.types import UnspecifiedValue from zerver.models import ( EmailChangeStatus, MultiuseInvite, + PreregistrationRealm, PreregistrationUser, Realm, RealmReactivationStatus, @@ -56,6 +57,7 @@ def generate_key() -> str: ConfirmationObjT = Union[ MultiuseInvite, + PreregistrationRealm, PreregistrationUser, EmailChangeStatus, UserProfile, @@ -114,12 +116,17 @@ def create_confirmation_link( *, validity_in_minutes: Union[Optional[int], UnspecifiedValue] = UnspecifiedValue(), url_args: Mapping[str, str] = {}, + realm_creation: bool = False, ) -> str: # validity_in_minutes is an override for the default values which are # determined by the confirmation_type - its main purpose is for use # in tests which may want to have control over the exact expiration time. key = generate_key() - realm = obj.realm + if realm_creation: + realm = None + else: + assert not isinstance(obj, PreregistrationRealm) + realm = obj.realm current_time = timezone_now() expiry_date = None diff --git a/zerver/tests/test_external.py b/zerver/tests/test_external.py index 4049cdf81b..1f35de2ea9 100644 --- a/zerver/tests/test_external.py +++ b/zerver/tests/test_external.py @@ -24,7 +24,7 @@ from zerver.lib.rate_limiter import ( ) from zerver.lib.test_classes import ZulipTestCase from zerver.lib.zephyr import compute_mit_user_fullname -from zerver.models import PushDeviceToken, UserProfile +from zerver.models import PushDeviceToken, Realm, UserProfile if settings.ZILENCER_ENABLED: from zilencer.models import RateLimitedRemoteZulipServer, RemoteZulipServer @@ -223,7 +223,15 @@ class RateLimitTests(ZulipTestCase): def test_create_realm_rate_limiting(self) -> None: with self.settings(OPEN_REALM_CREATION=True): self.do_test_hit_ratelimits( - lambda: self.client_post("/new/", {"email": "new@zulip.com"}), + lambda: self.client_post( + "/new/", + { + "email": "new@zulip.com", + "realm_name": "Zulip test", + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": "zuliptest", + }, + ), is_json=False, ) @@ -288,7 +296,15 @@ class RateLimitTests(ZulipTestCase): nonlocal request_count request_count += 1 if request_count % 2 == 1: - return self.client_post("/new/", {"email": "new@zulip.com"}) + return self.client_post( + "/new/", + { + "email": "new@zulip.com", + "realm_name": "Zulip test", + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": "zuliptest", + }, + ) else: return self.client_post("/accounts/find/", {"emails": "new@zulip.com"}) diff --git a/zerver/tests/test_management_commands.py b/zerver/tests/test_management_commands.py index d31dcd6ef8..73c6c18827 100644 --- a/zerver/tests/test_management_commands.py +++ b/zerver/tests/test_management_commands.py @@ -300,7 +300,15 @@ class TestGenerateRealmCreationLink(ZulipTestCase): # Enter email with self.assertRaises(Realm.DoesNotExist): get_realm("test") - result = self.client_post(generated_link, {"email": email}) + result = self.client_post( + generated_link, + { + "email": email, + "realm_name": "Zulip test", + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": "zuliptest", + }, + ) self.assertEqual(result.status_code, 302) self.assertTrue(re.search(r"/accounts/do_confirm/\w+$", result["Location"])) @@ -317,7 +325,15 @@ class TestGenerateRealmCreationLink(ZulipTestCase): email = "user1@test.com" generated_link = generate_realm_creation_url(by_admin=False) - result = self.client_post(generated_link, {"email": email}) + result = self.client_post( + generated_link, + { + "email": email, + "realm_name": "Zulip test", + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": "zuliptest", + }, + ) self.assertEqual(result.status_code, 302) self.assertEqual( f"/accounts/new/send_confirm/?email={urllib.parse.quote(email)}", result["Location"] diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index e86891d3e0..2acffc1223 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -1257,7 +1257,15 @@ class RealmCreationTest(ZulipTestCase): get_realm(string_id) # Create new realm with the email - result = self.client_post("/new/", {"email": email}) + result = self.client_post( + "/new/", + { + "email": email, + "realm_name": org_name, + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": string_id, + }, + ) self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( @@ -1266,6 +1274,10 @@ class RealmCreationTest(ZulipTestCase): ) result = self.client_get(result["Location"]) self.assert_in_response("Check your email", result) + prereg_realm = PreregistrationRealm.objects.get(email=email) + self.assertEqual(prereg_realm.name, "Zulip Test") + self.assertEqual(prereg_realm.org_type, Realm.ORG_TYPES["business"]["id"]) + self.assertEqual(prereg_realm.string_id, string_id) # Check confirmation email has the correct subject and body, extract # confirmation link and visit it @@ -1347,7 +1359,15 @@ class RealmCreationTest(ZulipTestCase): ) def test_create_realm_as_system_bot(self) -> None: - result = self.client_post("/new/", {"email": "notification-bot@zulip.com"}) + result = self.client_post( + "/new/", + { + "email": "notification-bot@zulip.com", + "realm_name": "Zulip test", + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": "zuliptest", + }, + ) self.assertEqual(result.status_code, 200) self.assert_in_response("notification-bot@zulip.com is reserved for system bots", result) @@ -1360,7 +1380,15 @@ class RealmCreationTest(ZulipTestCase): with self.settings(OPEN_REALM_CREATION=False): # Create new realm with the email, but no creation key. - result = self.client_post("/new/", {"email": email}) + result = self.client_post( + "/new/", + { + "email": email, + "realm_name": "Zulip test", + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": "zuliptest", + }, + ) self.assertEqual(result.status_code, 200) self.assert_in_response("Organization creation link required", result) @@ -1376,7 +1404,15 @@ class RealmCreationTest(ZulipTestCase): get_realm(string_id) # Create new realm with the email - result = self.client_post("/new/", {"email": email}) + result = self.client_post( + "/new/", + { + "email": email, + "realm_name": realm_name, + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": string_id, + }, + ) self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( @@ -1420,7 +1456,15 @@ class RealmCreationTest(ZulipTestCase): get_realm(string_id) # Create new realm with the email - result = self.client_post("/new/", {"email": email}) + result = self.client_post( + "/new/", + { + "email": email, + "realm_name": realm_name, + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": string_id, + }, + ) self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( @@ -1467,7 +1511,15 @@ class RealmCreationTest(ZulipTestCase): get_realm(string_id) # Create new realm with the email - result = self.client_post("/new/", {"email": email}) + result = self.client_post( + "/new/", + { + "email": email, + "realm_name": realm_name, + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": string_id, + }, + ) self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( @@ -1525,7 +1577,15 @@ class RealmCreationTest(ZulipTestCase): get_realm(string_id) # Create new realm with the email - result = self.client_post("/new/", {"email": email}) + result = self.client_post( + "/new/", + { + "email": email, + "realm_name": "Zulip test", + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": string_id, + }, + ) self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( @@ -1568,7 +1628,15 @@ class RealmCreationTest(ZulipTestCase): realm_name = "Test" # Create new realm with the email - result = self.client_post("/new/", {"email": email}) + result = self.client_post( + "/new/", + { + "email": email, + "realm_name": realm_name, + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": string_id, + }, + ) self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( @@ -1607,7 +1675,15 @@ class RealmCreationTest(ZulipTestCase): realm_name = "Test" # Create new realm with the email - result = self.client_post("/new/", {"email": email}) + result = self.client_post( + "/new/", + { + "email": email, + "realm_name": realm_name, + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": string_id, + }, + ) self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( @@ -1649,7 +1725,15 @@ class RealmCreationTest(ZulipTestCase): with self.assertRaises(Realm.DoesNotExist): get_realm(string_id) - result = self.client_post("/new/", {"email": email}) + result = self.client_post( + "/new/", + { + "email": email, + "realm_name": realm_name, + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": string_id, + }, + ) self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( @@ -1701,7 +1785,15 @@ class RealmCreationTest(ZulipTestCase): get_realm(second_string_id) # Now we pre-generate two realm creation links - result = self.client_post("/new/", {"email": email}) + result = self.client_post( + "/new/", + { + "email": email, + "realm_name": first_realm_name, + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": first_string_id, + }, + ) self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( @@ -1714,7 +1806,15 @@ class RealmCreationTest(ZulipTestCase): self.assertEqual(PreregistrationUser.objects.filter(email=email, status=0).count(), 1) # Get a second realm creation link. - result = self.client_post("/new/", {"email": email}) + result = self.client_post( + "/new/", + { + "email": email, + "realm_name": second_realm_name, + "realm_type": Realm.ORG_TYPES["business"]["id"], + "realm_subdomain": second_string_id, + }, + ) self.assertEqual(result.status_code, 302) self.assertTrue( result["Location"].endswith( @@ -1768,10 +1868,26 @@ class RealmCreationTest(ZulipTestCase): @override_settings(OPEN_REALM_CREATION=True) def test_invalid_email_signup(self) -> None: - result = self.client_post("/new/", {"email": " PreregistrationRealm: + return PreregistrationRealm.objects.create( + email=email, + name=name, + string_id=string_id, + org_type=org_type, + ) + + def maybe_send_to_registration( request: HttpRequest, email: str, diff --git a/zerver/views/registration.py b/zerver/views/registration.py index 009b218021..debf6851a6 100644 --- a/zerver/views/registration.py +++ b/zerver/views/registration.py @@ -77,6 +77,7 @@ from zerver.models import ( name_changes_disabled, ) from zerver.views.auth import ( + create_preregistration_realm, create_preregistration_user, finish_desktop_flow, finish_mobile_flow, @@ -586,7 +587,6 @@ def prepare_activation_url( session: SessionBase, *, realm: Optional[Realm], - realm_creation: bool = False, streams: Optional[Iterable[Stream]] = None, invited_as: Optional[int] = None, multiuse_invite: Optional[MultiuseInvite] = None, @@ -595,9 +595,7 @@ def prepare_activation_url( Send an email with a confirmation link to the provided e-mail so the user can complete their registration. """ - prereg_user = create_preregistration_user( - email, realm, realm_creation, multiuse_invite=multiuse_invite - ) + prereg_user = create_preregistration_user(email, realm, multiuse_invite=multiuse_invite) if streams is not None: prereg_user.streams.set(streams) @@ -607,11 +605,24 @@ def prepare_activation_url( prereg_user.save() confirmation_type = Confirmation.USER_REGISTRATION - if realm_creation: - confirmation_type = Confirmation.REALM_CREATION activation_url = create_confirmation_link(prereg_user, confirmation_type) - if settings.DEVELOPMENT and realm_creation: + return activation_url + + +def prepare_realm_activation_url( + email: str, + session: SessionBase, + realm_name: str, + string_id: str, + org_type: int, +) -> str: + prereg_realm = create_preregistration_realm(email, realm_name, string_id, org_type) + activation_url = create_confirmation_link( + prereg_realm, Confirmation.REALM_CREATION, realm_creation=True + ) + + if settings.DEVELOPMENT: session["confirmation_key"] = {"confirmation_key": activation_url.split("/")[-1]} return activation_url @@ -677,8 +688,11 @@ def create_realm(request: HttpRequest, creation_key: Optional[str] = None) -> Ht ) email = form.cleaned_data["email"] - activation_url = prepare_activation_url( - email, request.session, realm=None, realm_creation=True + realm_name = form.cleaned_data["realm_name"] + realm_type = form.cleaned_data["realm_type"] + realm_subdomain = form.cleaned_data["realm_subdomain"] + activation_url = prepare_realm_activation_url( + email, request.session, realm_name, realm_subdomain, realm_type ) if key_record is not None and key_record.presume_email_valid: # The user has a token created from the server command line;