registration: Add code to set email_address_visibility during signup.

This commit adds backend code to set email_address_visibility when
registering a new user. The realm-level default and the value of
source profile gets overridden by the value user selected during
signup.
This commit is contained in:
Sahil Batra 2023-02-13 22:10:16 +05:30 committed by Tim Abbott
parent 0620d2ac1b
commit 36584a3571
7 changed files with 81 additions and 12 deletions

View File

@ -390,6 +390,7 @@ def do_create_user(
*,
acting_user: Optional[UserProfile],
enable_marketing_emails: bool = True,
email_address_visibility: Optional[int] = None,
) -> UserProfile:
with transaction.atomic():
user_profile = create_user(
@ -409,6 +410,7 @@ def do_create_user(
default_all_public_streams=default_all_public_streams,
source_profile=source_profile,
enable_marketing_emails=enable_marketing_emails,
email_address_visibility=email_address_visibility,
)
event_time = user_profile.date_joined

View File

@ -115,6 +115,15 @@ class RegistrationForm(forms.Form):
realm_type = forms.IntegerField(required=False)
is_demo_organization = forms.BooleanField(required=False)
enable_marketing_emails = forms.BooleanField(required=False)
email_address_visibility = forms.TypedChoiceField(
required=False,
coerce=int,
empty_value=None,
choices=[
(value, name)
for value, name in UserProfile.EMAIL_ADDRESS_VISIBILITY_ID_TO_NAME_MAP.items()
],
)
def __init__(self, *args: Any, **kwargs: Any) -> None:
# Since the superclass doesn't except random extra kwargs, we

View File

@ -36,6 +36,12 @@ def copy_default_settings(
settings_source, RealmUserDefault
):
continue
if settings_name == "email_address_visibility":
# For email_address_visibility, the value selected in registration form
# is preferred over the realm-level default value and value of source
# profile.
continue
value = getattr(settings_source, settings_name)
setattr(target_profile, settings_name, value)
@ -156,14 +162,18 @@ def create_user(
force_id: Optional[int] = None,
force_date_joined: Optional[datetime] = None,
enable_marketing_emails: Optional[bool] = None,
email_address_visibility: Optional[int] = None,
) -> UserProfile:
realm_user_default = RealmUserDefault.objects.get(realm=realm)
if bot_type is None:
email_address_visibility = realm_user_default.email_address_visibility
if email_address_visibility is not None:
user_email_address_visibility = email_address_visibility
else:
user_email_address_visibility = realm_user_default.email_address_visibility
else:
# There is no privacy motivation for limiting access to bot email addresses,
# so we hardcode them to EMAIL_ADDRESS_VISIBILITY_EVERYONE.
email_address_visibility = UserProfile.EMAIL_ADDRESS_VISIBILITY_EVERYONE
user_email_address_visibility = UserProfile.EMAIL_ADDRESS_VISIBILITY_EVERYONE
user_profile = create_user_profile(
realm,
@ -179,7 +189,7 @@ def create_user(
default_language,
force_id=force_id,
force_date_joined=force_date_joined,
email_address_visibility=email_address_visibility,
email_address_visibility=user_email_address_visibility,
)
user_profile.avatar_source = avatar_source
user_profile.timezone = timezone

View File

@ -755,6 +755,7 @@ Output:
key: Optional[str] = None,
realm_type: int = Realm.ORG_TYPES["business"]["id"],
enable_marketing_emails: Optional[bool] = None,
email_address_visibility: Optional[int] = None,
is_demo_organization: bool = False,
**extra: str,
) -> "TestHttpResponse":
@ -783,6 +784,8 @@ Output:
}
if enable_marketing_emails is not None:
payload["enable_marketing_emails"] = enable_marketing_emails
if email_address_visibility is not None:
payload["email_address_visibility"] = email_address_visibility
if password is not None:
payload["password"] = password
if realm_in_root_domain is not None:

View File

@ -1612,13 +1612,16 @@ class UserBaseSettings(models.Model):
email_address_visibility = models.PositiveSmallIntegerField(
default=EMAIL_ADDRESS_VISIBILITY_EVERYONE,
)
EMAIL_ADDRESS_VISIBILITY_TYPES = [
EMAIL_ADDRESS_VISIBILITY_EVERYONE,
EMAIL_ADDRESS_VISIBILITY_MEMBERS,
EMAIL_ADDRESS_VISIBILITY_ADMINS,
EMAIL_ADDRESS_VISIBILITY_NOBODY,
EMAIL_ADDRESS_VISIBILITY_MODERATORS,
]
EMAIL_ADDRESS_VISIBILITY_ID_TO_NAME_MAP = {
EMAIL_ADDRESS_VISIBILITY_EVERYONE: gettext_lazy("Admins, moderators, members and guests"),
EMAIL_ADDRESS_VISIBILITY_MEMBERS: gettext_lazy("Admins, moderators and members"),
EMAIL_ADDRESS_VISIBILITY_MODERATORS: gettext_lazy("Admins and moderators"),
EMAIL_ADDRESS_VISIBILITY_ADMINS: gettext_lazy("Admins only"),
EMAIL_ADDRESS_VISIBILITY_NOBODY: gettext_lazy("Nobody"),
}
EMAIL_ADDRESS_VISIBILITY_TYPES = list(EMAIL_ADDRESS_VISIBILITY_ID_TO_NAME_MAP.keys())
display_settings_legacy = dict(
# Don't add anything new to this legacy dict.

View File

@ -4291,6 +4291,45 @@ class UserSignUpTest(InviteUserBase):
user_profile.twenty_four_hour_time, realm_user_default.twenty_four_hour_time
)
def test_email_address_visibility_for_new_user(self) -> None:
email = self.nonreg_email("newguy")
password = "newpassword"
realm = get_realm("zulip")
realm_user_default = RealmUserDefault.objects.get(realm=realm)
self.assertEqual(
realm_user_default.email_address_visibility, UserProfile.EMAIL_ADDRESS_VISIBILITY_ADMINS
)
result = self.client_post("/accounts/home/", {"email": email})
self.assertEqual(result.status_code, 302)
self.assertTrue(
result["Location"].endswith(
f"/accounts/send_confirm/?email={urllib.parse.quote(email)}"
)
)
result = self.client_get(result["Location"])
self.assert_in_response("Check your email", result)
# Visit the confirmation link.
confirmation_url = self.get_confirmation_url_from_outbox(email)
result = self.client_get(confirmation_url)
self.assertEqual(result.status_code, 200)
# Pick a password and agree to the ToS.
result = self.submit_reg_form_for_user(
email, password, email_address_visibility=UserProfile.EMAIL_ADDRESS_VISIBILITY_NOBODY
)
self.assertEqual(result.status_code, 302)
# Realm-level default is overridden by the value passed during signup.
user_profile = self.nonreg_user("newguy")
self.assertEqual(
user_profile.email_address_visibility, UserProfile.EMAIL_ADDRESS_VISIBILITY_NOBODY
)
from django.core.mail import outbox
outbox.pop()
def test_signup_already_active(self) -> None:
"""
Check if signing up with an active email redirects to a login page.
@ -4668,9 +4707,10 @@ class UserSignUpTest(InviteUserBase):
password,
source_realm_id=str(hamlet_in_zulip.realm.id),
HTTP_HOST=subdomain + ".testserver",
email_address_visibility=UserProfile.EMAIL_ADDRESS_VISIBILITY_NOBODY,
)
hamlet_in_lear = get_user(email, lear_realm)
hamlet_in_lear = get_user_by_delivery_email(email, lear_realm)
self.assertEqual(hamlet_in_lear.left_side_userlist, True)
self.assertEqual(hamlet_in_lear.default_language, "de")
self.assertEqual(hamlet_in_lear.emojiset, "twitter")
@ -4679,7 +4719,7 @@ class UserSignUpTest(InviteUserBase):
self.assertEqual(hamlet_in_lear.enable_stream_audible_notifications, False)
self.assertEqual(hamlet_in_lear.tutorial_status, UserProfile.TUTORIAL_FINISHED)
self.assertEqual(
hamlet_in_lear.email_address_visibility, UserProfile.EMAIL_ADDRESS_VISIBILITY_EVERYONE
hamlet_in_lear.email_address_visibility, UserProfile.EMAIL_ADDRESS_VISIBILITY_NOBODY
)
zulip_path_id = avatar_disk_path(hamlet_in_zulip)

View File

@ -350,6 +350,7 @@ def accounts_register(
full_name = form.cleaned_data["full_name"]
enable_marketing_emails = form.cleaned_data["enable_marketing_emails"]
email_address_visibility = form.cleaned_data["email_address_visibility"]
default_stream_group_names = request.POST.getlist("default_stream_group")
default_stream_groups = lookup_default_stream_groups(default_stream_group_names, realm)
@ -464,6 +465,7 @@ def accounts_register(
realm_creation=realm_creation,
acting_user=None,
enable_marketing_emails=enable_marketing_emails,
email_address_visibility=email_address_visibility,
)
if realm_creation: