From 5e33ae8adf5ab2a9d29af91d98cf710d382def28 Mon Sep 17 00:00:00 2001 From: Eeshan Garg Date: Wed, 22 Dec 2021 19:41:41 -0500 Subject: [PATCH] demo-orgs: Create dev environment demo organization without email. To make creation of demo organizations feel lightweight for users, we do not want to require an email address at sign-up. Instead an empty string will used for the new realm owner's email. Currently implements that for new demo organizations in the development environment. Because the user's email address does not exist, we don't enqueue any of the welcome emails upon account/realm creation, and we don't create/send new login emails. This is a part of #19523. Co-authored by: Tim Abbott Co-authored by: Lauryn Menard --- zerver/actions/create_user.py | 2 +- zerver/lib/email_notifications.py | 16 ++++++++++- zerver/signals.py | 10 +++++++ zerver/tests/test_signup.py | 5 ++++ zerver/views/development/registration.py | 6 ++--- zerver/views/registration.py | 34 ++++++++++++++++++------ 6 files changed, 60 insertions(+), 13 deletions(-) diff --git a/zerver/actions/create_user.py b/zerver/actions/create_user.py index 345ae7a59d..9f7b220123 100644 --- a/zerver/actions/create_user.py +++ b/zerver/actions/create_user.py @@ -280,7 +280,7 @@ def process_new_human_user( # from being sent after the user is created. clear_scheduled_invitation_emails(user_profile.delivery_email) if realm.send_welcome_emails: - enqueue_welcome_emails(user_profile) + enqueue_welcome_emails(user_profile, realm_creation) # Schedule an initial email with the user's # new account details and log-in information. diff --git a/zerver/lib/email_notifications.py b/zerver/lib/email_notifications.py index 9b07570c9e..fa645b3d51 100644 --- a/zerver/lib/email_notifications.py +++ b/zerver/lib/email_notifications.py @@ -767,6 +767,13 @@ def send_account_registered_email(user: UserProfile, realm_creation: bool = Fals # Imported here to avoid import cycles. from zerver.context_processors import common_context + if user.delivery_email == "": + # Do not attempt to enqueue welcome emails for users without an email address. + # The assertions here are to help document the only circumstance under which + # this condition should be possible. + assert user.realm.demo_organization_scheduled_deletion_date is not None and realm_creation + return + from_name, from_address = welcome_sender_information() realm_url = user.realm.uri @@ -811,10 +818,17 @@ def send_account_registered_email(user: UserProfile, realm_creation: bool = Fals ) -def enqueue_welcome_emails(user: UserProfile) -> None: +def enqueue_welcome_emails(user: UserProfile, realm_creation: bool = False) -> None: # Imported here to avoid import cycles. from zerver.context_processors import common_context + if user.delivery_email == "": + # Do not attempt to enqueue welcome emails for users without an email address. + # The assertions here are to help document the only circumstance under which + # this condition should be possible. + assert user.realm.demo_organization_scheduled_deletion_date is not None and realm_creation + return + from_name, from_address = welcome_sender_information() other_account_count = ( UserProfile.objects.filter(delivery_email__iexact=user.delivery_email) diff --git a/zerver/signals.py b/zerver/signals.py index 6efcf23729..f3bb1c73ab 100644 --- a/zerver/signals.py +++ b/zerver/signals.py @@ -67,6 +67,16 @@ def get_device_os(user_agent: str) -> Optional[str]: def email_on_new_login(sender: Any, user: UserProfile, request: Any, **kwargs: Any) -> None: if not user.enable_login_emails: return + + if user.delivery_email == "": + # Do not attempt to send new login emails for users without an email address. + # The assertions here are to help document the only circumstance under which + # this condition should be possible. + assert ( + user.realm.demo_organization_scheduled_deletion_date is not None and user.is_realm_owner + ) + return + # We import here to minimize the dependencies of this module, # since it runs as part of `manage.py` initialization from zerver.context_processors import common_context diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index 5787ebabcc..5d075e0cf6 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -3952,6 +3952,11 @@ class UserSignUpTest(ZulipTestCase): assert user_profile is not None self.assert_logged_in_user_id(user_profile.id) + # Demo organizations are created without setting an email address for the owner. + self.assertEqual(user_profile.delivery_email, "") + scheduled_email = ScheduledEmail.objects.filter(users=user_profile).last() + assert scheduled_email is None + expected_deletion_date = realm.date_created + datetime.timedelta( days=settings.DEMO_ORG_DEADLINE_DAYS ) diff --git a/zerver/views/development/registration.py b/zerver/views/development/registration.py index 44f3323b60..5968e1e42c 100644 --- a/zerver/views/development/registration.py +++ b/zerver/views/development/registration.py @@ -88,9 +88,9 @@ def register_development_realm(request: HttpRequest) -> HttpResponse: @csrf_exempt def register_demo_development_realm(request: HttpRequest) -> HttpResponse: - count = UserProfile.objects.count() - name = f"user-{count}" - email = f"{name}@zulip.com" + # Demo organization owners are not required to provide a name or email. + name = "Your name" + email = "" realm_name = generate_demo_realm_name() realm_type = Realm.ORG_TYPES["business"]["id"] realm_subdomain = realm_name diff --git a/zerver/views/registration.py b/zerver/views/registration.py index 3bffdcbeba..62b4b9d648 100644 --- a/zerver/views/registration.py +++ b/zerver/views/registration.py @@ -213,6 +213,7 @@ def registration_helper( source_realm_id: Optional[int] = REQ( default=None, converter=to_converted_or_fallback(to_non_negative_int, None) ), + form_is_demo_organization: Optional[str] = REQ("is_demo_organization", default=None), ) -> HttpResponse: try: prereg_object, realm_creation = check_prereg_key(request, key) @@ -233,12 +234,29 @@ def registration_helper( password_required = prereg_object.password_required role = prereg_object.invited_as - try: - validators.validate_email(email) - except ValidationError: - return TemplateResponse( - request, "zerver/invalid_email.html", context={"invalid_email": True} - ) + if form_is_demo_organization is None: + demo_organization_creation = False + else: + # Check the explicit strings that return false + # in django.forms.BooleanField.to_python. + false_strings = ("false", "0") + demo_organization_creation = form_is_demo_organization.strip().lower() not in false_strings + + if email == "": + # Do not attempt to validate email for users without an email address. + # The assertions here are to help document the only circumstance under which + # this condition should be possible. + assert realm_creation and demo_organization_creation + # TODO: Remove settings.DEVELOPMENT when demo organization feature ready + # to be fully implemented. + assert settings.DEVELOPMENT + else: + try: + validators.validate_email(email) + except ValidationError: + return TemplateResponse( + request, "zerver/invalid_email.html", context={"invalid_email": True} + ) if realm_creation: # For creating a new realm, there is no existing realm or domain @@ -419,12 +437,12 @@ def registration_helper( string_id = form.cleaned_data["realm_subdomain"] realm_name = form.cleaned_data["realm_name"] realm_type = form.cleaned_data["realm_type"] - is_demo_org = form.cleaned_data["is_demo_organization"] + is_demo_organization = form.cleaned_data["is_demo_organization"] realm = do_create_realm( string_id, realm_name, org_type=realm_type, - is_demo_organization=is_demo_org, + is_demo_organization=is_demo_organization, prereg_realm=prereg_realm, ) assert realm is not None