From e603237010c6bb3520ae0b01454876bea443f85b Mon Sep 17 00:00:00 2001 From: Tim Abbott Date: Thu, 6 Dec 2018 15:05:57 -0800 Subject: [PATCH] email: Convert accounts code to use delivery_email. A key part of this is the new helper, get_user_by_delivery_email. Its verbose name is important for clarity; it should help avoid blind copy-pasting of get_user (which we'll also want to rename). Unfortunately, it requires detailed understanding of the context to figure out which one to use; each is used in about half of call sites. Another important note is that this PR doesn't migrate get_user calls in the tests except where not doing so would cause the tests to fail. This probably deserves a follow-up refactor to avoid bugs here. --- analytics/views.py | 16 +++++++-------- docs/subsystems/email.md | 3 +++ zerver/decorator.py | 14 ++++++------- zerver/forms.py | 8 +++++--- zerver/lib/actions.py | 12 +++++------ zerver/lib/cache.py | 2 +- zerver/lib/cache_helpers.py | 3 ++- zerver/lib/management.py | 5 +++-- zerver/lib/notifications.py | 2 +- zerver/lib/users.py | 2 +- .../commands/deliver_scheduled_messages.py | 4 ++-- zerver/models.py | 20 +++++++++++++++++-- zerver/tests/test_subs.py | 4 ++-- zerver/tests/test_users.py | 2 +- zerver/views/email_log.py | 6 +++--- zerver/views/presence.py | 5 +++-- zerver/views/registration.py | 4 ++-- zerver/views/users.py | 6 +++--- zerver/webhooks/jira/view.py | 4 ++-- zerver/webhooks/teamcity/tests.py | 4 ++-- zilencer/management/commands/sync_api_key.py | 4 ++-- zproject/backends.py | 6 +++--- 22 files changed, 80 insertions(+), 56 deletions(-) diff --git a/analytics/views.py b/analytics/views.py index 3b7c28dd78..3cf4307d74 100644 --- a/analytics/views.py +++ b/analytics/views.py @@ -586,15 +586,15 @@ def user_activity_intervals() -> Tuple[mark_safe, Dict[str, float]]: ).only( 'start', 'end', - 'user_profile__email', + 'user_profile__delivery_email', 'user_profile__realm__string_id' ).order_by( 'user_profile__realm__string_id', - 'user_profile__email' + 'user_profile__delivery_email' ) by_string_id = lambda row: row.user_profile.realm.string_id - by_email = lambda row: row.user_profile.email + by_email = lambda row: row.user_profile.delivery_email realm_minutes = {} @@ -879,7 +879,7 @@ def get_activity(request: HttpRequest) -> HttpResponse: def get_user_activity_records_for_realm(realm: str, is_bot: bool) -> QuerySet: fields = [ 'user_profile__full_name', - 'user_profile__email', + 'user_profile__delivery_email', 'query', 'client__name', 'count', @@ -891,7 +891,7 @@ def get_user_activity_records_for_realm(realm: str, is_bot: bool) -> QuerySet: user_profile__is_active=True, user_profile__is_bot=is_bot ) - records = records.order_by("user_profile__email", "-last_visit") + records = records.order_by("user_profile__delivery_email", "-last_visit") records = records.select_related('user_profile', 'client').only(*fields) return records @@ -905,7 +905,7 @@ def get_user_activity_records_for_email(email: str) -> List[QuerySet]: ] records = UserActivity.objects.filter( - user_profile__email=email + user_profile__delivery_email=email ) records = records.order_by("-last_visit") records = records.select_related('user_profile', 'client').only(*fields) @@ -1079,7 +1079,7 @@ def realm_user_summary_table(all_records: List[QuerySet], user_records = {} def by_email(record: QuerySet) -> str: - return record.user_profile.email + return record.user_profile.delivery_email for email, records in itertools.groupby(all_records, by_email): user_records[email] = get_user_activity_summary(list(records)) @@ -1150,7 +1150,7 @@ def get_realm_activity(request: HttpRequest, realm_str: str) -> HttpResponse: except Realm.DoesNotExist: return HttpResponseNotFound("Realm %s does not exist" % (realm_str,)) - admin_emails = {admin.email for admin in admins} + admin_emails = {admin.delivery_email for admin in admins} for is_bot, page_title in [(False, 'Humans'), (True, 'Bots')]: all_records = list(get_user_activity_records_for_realm(realm_str, is_bot)) diff --git a/docs/subsystems/email.md b/docs/subsystems/email.md index 5552c93b44..5377290a34 100644 --- a/docs/subsystems/email.md +++ b/docs/subsystems/email.md @@ -24,6 +24,9 @@ with only a few things you need to know to get started. eventually call the `send_email` function. The most interesting one is `send_future_email`. The `ScheduledEmail` entries are eventually processed by a supervisor job that runs `zerver/management/commands/deliver_email.py`. +* Always use `user_profile.delivery_email`, not `user_profile.email`, + when passing data into the `send_email` library. The + `user_profile.email` field may not always be valid. * A good way to find a bunch of example email pathways is to `git grep` for `zerver/emails` in the `zerver/` directory. diff --git a/zerver/decorator.py b/zerver/decorator.py index 4d3d046011..656d125eb1 100644 --- a/zerver/decorator.py +++ b/zerver/decorator.py @@ -235,7 +235,7 @@ def validate_api_key(request: HttpRequest, role: Optional[str], raise JsonableError(_("This API is not available to incoming webhook bots.")) request.user = user_profile - request._email = user_profile.email + request._email = user_profile.delivery_email process_client(request, user_profile, client_name=client_name) return user_profile @@ -257,7 +257,7 @@ def validate_account_and_subdomain(request: HttpRequest, user_profile: UserProfi request.META["SERVER_NAME"] == "127.0.0.1" and request.META["REMOTE_ADDR"] == "127.0.0.1")): logging.warning("User %s (%s) attempted to access API on wrong subdomain (%s)" % ( - user_profile.email, user_profile.realm.subdomain, get_subdomain(request))) + user_profile.delivery_email, user_profile.realm.subdomain, get_subdomain(request))) raise JsonableError(_("Account is not associated with this subdomain")) def access_user_by_api_key(request: HttpRequest, api_key: str, email: Optional[str]=None) -> UserProfile: @@ -265,7 +265,7 @@ def access_user_by_api_key(request: HttpRequest, api_key: str, email: Optional[s user_profile = get_user_profile_by_api_key(api_key) except UserProfile.DoesNotExist: raise JsonableError(_("Invalid API key")) - if email is not None and email.lower() != user_profile.email.lower(): + if email is not None and email.lower() != user_profile.delivery_email.lower(): # This covers the case that the API key is correct, but for a # different user. We may end up wanting to relaxing this # constraint or give a different error message in the future. @@ -311,7 +311,7 @@ body: {body} """.format( - email=user_profile.email, + email=user_profile.delivery_email, realm=user_profile.realm.string_id, client_name=request.client.name, body=payload, @@ -426,7 +426,7 @@ def do_login(request: HttpRequest, user_profile: UserProfile) -> None: and also adds helpful data needed by our server logs. """ django_login(request, user_profile) - request._email = user_profile.email + request._email = user_profile.delivery_email process_client(request, user_profile, is_browser_view=True) if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: # Login with two factor authentication as well. @@ -442,7 +442,7 @@ def log_view_func(view_func: ViewFuncT) -> ViewFuncT: def add_logging_data(view_func: ViewFuncT) -> ViewFuncT: @wraps(view_func) def _wrapped_view_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: - request._email = request.user.email + request._email = request.user.delivery_email process_client(request, request.user, is_browser_view=True, query=view_func.__name__) return rate_limit()(view_func)(request, *args, **kwargs) @@ -660,7 +660,7 @@ def authenticate_log_and_execute_json(request: HttpRequest, process_client(request, user_profile, is_browser_view=True, query=view_func.__name__) - request._email = user_profile.email + request._email = user_profile.delivery_email return rate_limit()(view_func)(request, user_profile, *args, **kwargs) # Checks if the request is a POST request and that the user is logged diff --git a/zerver/forms.py b/zerver/forms.py index 33d40663a2..449a08ba17 100644 --- a/zerver/forms.py +++ b/zerver/forms.py @@ -24,7 +24,8 @@ from zerver.lib.request import JsonableError from zerver.lib.send_email import send_email, FromAddress from zerver.lib.subdomains import get_subdomain, user_matches_subdomain, is_root_domain_available from zerver.lib.users import check_full_name -from zerver.models import Realm, get_user, UserProfile, get_realm, email_to_domain, \ +from zerver.models import Realm, get_user_by_delivery_email, UserProfile, get_realm, \ + email_to_domain, \ email_allowed_for_realm, DisposableEmailError, DomainNotAllowedForRealmError, \ EmailContainsPlusError from zproject.backends import email_auth_enabled, email_belongs_to_ldap @@ -234,7 +235,7 @@ class ZulipPasswordResetForm(PasswordResetForm): user = None # type: Optional[UserProfile] try: - user = get_user(email, realm) + user = get_user_by_delivery_email(email, realm) except UserProfile.DoesNotExist: pass @@ -256,7 +257,8 @@ class ZulipPasswordResetForm(PasswordResetForm): context=context) else: context['active_account_in_realm'] = False - active_accounts_in_other_realms = UserProfile.objects.filter(email__iexact=email, is_active=True) + active_accounts_in_other_realms = UserProfile.objects.filter( + delivery_email__iexact=email, is_active=True) if active_accounts_in_other_realms: context['active_accounts_in_other_realms'] = active_accounts_in_other_realms send_email('zerver/emails/password_reset', to_emails=[email], diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py index ae22560727..35a092c5f8 100644 --- a/zerver/lib/actions.py +++ b/zerver/lib/actions.py @@ -87,7 +87,7 @@ from zerver.models import Realm, RealmEmoji, Stream, UserProfile, UserActivity, get_user_profile_by_id, PreregistrationUser, get_display_recipient, \ get_realm, bulk_get_recipients, get_stream_recipient, get_stream_recipients, \ email_allowed_for_realm, email_to_username, display_recipient_cache_key, \ - get_user, get_stream_cache_key, active_non_guest_user_ids, \ + get_user_by_delivery_email, get_stream_cache_key, active_non_guest_user_ids, \ UserActivityInterval, active_user_ids, get_active_streams, \ realm_filters_for_realm, RealmFilter, stream_name_in_use, \ get_old_unclaimed_attachments, is_cross_realm_bot_email, \ @@ -364,12 +364,12 @@ def process_new_human_user(user_profile: UserProfile, # inactive so we can keep track of the PreregistrationUser we # actually used for analytics if prereg_user is not None: - PreregistrationUser.objects.filter(email__iexact=user_profile.email).exclude( + PreregistrationUser.objects.filter(email__iexact=user_profile.delivery_email).exclude( id=prereg_user.id).update(status=0) if prereg_user.referred_by is not None: notify_invites_changed(user_profile) else: - PreregistrationUser.objects.filter(email__iexact=user_profile.email).update(status=0) + PreregistrationUser.objects.filter(email__iexact=user_profile.delivery_email).update(status=0) notify_new_user(user_profile) if user_profile.realm.send_welcome_emails: @@ -810,7 +810,7 @@ def compute_jabber_user_fullname(email: str) -> str: def create_mirror_user_if_needed(realm: Realm, email: str, email_to_fullname: Callable[[str], str]) -> UserProfile: try: - return get_user(email, realm) + return get_user_by_delivery_email(email, realm) except UserProfile.DoesNotExist: try: # Forge a user for this person @@ -824,7 +824,7 @@ def create_mirror_user_if_needed(realm: Realm, email: str, is_mirror_dummy=True, ) except IntegrityError: - return get_user(email, realm) + return get_user_by_delivery_email(email, realm) def send_welcome_bot_response(message: MutableMapping[str, Any]) -> None: welcome_bot = get_system_bot(settings.WELCOME_BOT) @@ -4440,7 +4440,7 @@ def validate_email_for_realm(target_realm: Realm, email: str) -> None: email_not_system_bot(email) try: - existing_user_profile = get_user(email, target_realm) + existing_user_profile = get_user_by_delivery_email(email, target_realm) except UserProfile.DoesNotExist: return diff --git a/zerver/lib/cache.py b/zerver/lib/cache.py index cf997ed959..fef31404a7 100644 --- a/zerver/lib/cache.py +++ b/zerver/lib/cache.py @@ -356,7 +356,7 @@ def delete_user_profile_caches(user_profiles: Iterable['UserProfile']) -> None: from zerver.lib.users import get_all_api_keys keys = [] for user_profile in user_profiles: - keys.append(user_profile_by_email_cache_key(user_profile.email)) + keys.append(user_profile_by_email_cache_key(user_profile.delivery_email)) keys.append(user_profile_by_id_cache_key(user_profile.id)) for api_key in get_all_api_keys(user_profile): keys.append(user_profile_by_api_key_cache_key(api_key)) diff --git a/zerver/lib/cache_helpers.py b/zerver/lib/cache_helpers.py index 2aa9063624..e9e2471048 100644 --- a/zerver/lib/cache_helpers.py +++ b/zerver/lib/cache_helpers.py @@ -48,7 +48,8 @@ def user_cache_items(items_for_remote_cache: Dict[str, Tuple[UserProfile]], user_profile: UserProfile) -> None: for api_key in get_all_api_keys(user_profile): items_for_remote_cache[user_profile_by_api_key_cache_key(api_key)] = (user_profile,) - items_for_remote_cache[user_profile_cache_key(user_profile.email, user_profile.realm)] = (user_profile,) + items_for_remote_cache[user_profile_cache_key(user_profile.email, + user_profile.realm)] = (user_profile,) # We have other user_profile caches, but none of them are on the # core serving path for lots of requests. diff --git a/zerver/lib/management.py b/zerver/lib/management.py index 1497bcfb99..15ef2a94d1 100644 --- a/zerver/lib/management.py +++ b/zerver/lib/management.py @@ -110,7 +110,8 @@ You can use the command list_realms to find ID of the realms in this server.""" # throw an error if they don't exist. if realm is not None: try: - return UserProfile.objects.select_related().get(email__iexact=email.strip(), realm=realm) + return UserProfile.objects.select_related().get( + delivery_email__iexact=email.strip(), realm=realm) except UserProfile.DoesNotExist: raise CommandError("The realm '%s' does not contain a user with email '%s'" % (realm, email)) @@ -118,7 +119,7 @@ You can use the command list_realms to find ID of the realms in this server.""" # optimistically try to see if there is exactly one user with # that email; if so, we'll return it. try: - return UserProfile.objects.select_related().get(email__iexact=email.strip()) + return UserProfile.objects.select_related().get(delivery_email__iexact=email.strip()) except MultipleObjectsReturned: raise CommandError("This Zulip server contains multiple users with that email " + "(in different realms); please pass `--realm` " diff --git a/zerver/lib/notifications.py b/zerver/lib/notifications.py index a6461379a2..c089d8f475 100644 --- a/zerver/lib/notifications.py +++ b/zerver/lib/notifications.py @@ -508,7 +508,7 @@ def enqueue_welcome_emails(user: UserProfile, realm_creation: bool=False) -> Non from_address = FromAddress.SUPPORT other_account_count = UserProfile.objects.filter( - email__iexact=user.email).exclude(id=user.id).count() + delivery_email__iexact=user.delivery_email).exclude(id=user.id).count() unsubscribe_link = one_click_unsubscribe_link(user, "welcome") context = common_context(user) context.update({ diff --git a/zerver/lib/users.py b/zerver/lib/users.py index 201996df47..06fd7ec77d 100644 --- a/zerver/lib/users.py +++ b/zerver/lib/users.py @@ -185,7 +185,7 @@ def access_user_by_id(user_profile: UserProfile, user_id: int, def get_accounts_for_email(email: str) -> List[Dict[str, Optional[str]]]: if settings.PRODUCTION: # nocoverage return [] - profiles = UserProfile.objects.select_related('realm').filter(email__iexact=email.strip(), + profiles = UserProfile.objects.select_related('realm').filter(delivery_email__iexact=email.strip(), is_active=True, is_bot=False, realm__deactivated=False) diff --git a/zerver/management/commands/deliver_scheduled_messages.py b/zerver/management/commands/deliver_scheduled_messages.py index 18db7a4f85..9c04e8526c 100644 --- a/zerver/management/commands/deliver_scheduled_messages.py +++ b/zerver/management/commands/deliver_scheduled_messages.py @@ -11,7 +11,7 @@ from django.utils.timezone import now as timezone_now from zerver.lib.context_managers import lockfile from zerver.lib.logging_util import log_to_file from zerver.lib.management import sleep_forever -from zerver.models import ScheduledMessage, Message, get_user +from zerver.models import ScheduledMessage, Message, get_user_by_delivery_email from zerver.lib.actions import do_send_messages from zerver.lib.addressee import Addressee @@ -44,7 +44,7 @@ Usage: ./manage.py deliver_scheduled_messages if delivery_type == ScheduledMessage.SEND_LATER: message.sender = original_sender elif delivery_type == ScheduledMessage.REMIND: - message.sender = get_user(settings.REMINDER_BOT, original_sender.realm) + message.sender = get_user_by_delivery_email(settings.REMINDER_BOT, original_sender.realm) return {'message': message, 'stream': scheduled_message.stream, 'realm': scheduled_message.realm} diff --git a/zerver/models.py b/zerver/models.py index 1fdae452d0..68fc7e7f6d 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -1784,16 +1784,32 @@ def get_user_profile_by_id(uid: int) -> UserProfile: @cache_with_key(user_profile_by_email_cache_key, timeout=3600*24*7) def get_user_profile_by_email(email: str) -> UserProfile: - return UserProfile.objects.select_related().get(email__iexact=email.strip()) + return UserProfile.objects.select_related().get(delivery_email__iexact=email.strip()) @cache_with_key(user_profile_by_api_key_cache_key, timeout=3600*24*7) def get_user_profile_by_api_key(api_key: str) -> UserProfile: return UserProfile.objects.select_related().get(api_key=api_key) +def get_user_by_delivery_email(email: str, realm: Realm) -> UserProfile: + # Fetches users by delivery_email for use in + # authentication/registration contexts. Do not use for user-facing + # views (e.g. Zulip API endpoints); for that, you want get_user. + return UserProfile.objects.select_related().get(delivery_email__iexact=email.strip(), realm=realm) + @cache_with_key(user_profile_cache_key, timeout=3600*24*7) def get_user(email: str, realm: Realm) -> UserProfile: + # Fetches the user by its visible-to-other users username (in the + # `email` field). For use in API contexts; do not use in + # authentication/registration contexts; for that, you need to use + # get_user_by_delivery_email. return UserProfile.objects.select_related().get(email__iexact=email.strip(), realm=realm) +def get_active_user_by_delivery_email(email: str, realm: Realm) -> UserProfile: + user_profile = get_user_by_delivery_email(email, realm) + if not user_profile.is_active: + raise UserProfile.DoesNotExist() + return user_profile + def get_active_user(email: str, realm: Realm) -> UserProfile: user_profile = get_user(email, realm) if not user_profile.is_active: @@ -1858,7 +1874,7 @@ def get_source_profile(email: str, string_id: str) -> Optional[UserProfile]: return None try: - return get_user(email, realm) + return get_user_by_delivery_email(email, realm) except UserProfile.DoesNotExist: return None diff --git a/zerver/tests/test_subs.py b/zerver/tests/test_subs.py index 984a71e3a5..5d2e4125b6 100644 --- a/zerver/tests/test_subs.py +++ b/zerver/tests/test_subs.py @@ -45,7 +45,7 @@ from zerver.models import ( get_display_recipient, Message, Realm, Recipient, Stream, Subscription, DefaultStream, UserProfile, get_user_profile_by_id, active_non_guest_user_ids, get_default_stream_groups, flush_per_request_caches, DefaultStreamGroup, - get_client, + get_client, get_user ) from zerver.lib.actions import ( @@ -53,7 +53,7 @@ from zerver.lib.actions import ( do_create_realm, do_remove_default_stream, bulk_get_subscriber_user_ids, gather_subscriptions_helper, bulk_add_subscriptions, bulk_remove_subscriptions, gather_subscriptions, get_default_streams_for_realm, get_realm, get_stream, - get_user, set_default_streams, check_stream_name, do_get_streams, + set_default_streams, check_stream_name, do_get_streams, create_stream_if_needed, create_streams_if_needed, ensure_stream, do_deactivate_stream, diff --git a/zerver/tests/test_users.py b/zerver/tests/test_users.py index d4e57c509d..02be08a373 100644 --- a/zerver/tests/test_users.py +++ b/zerver/tests/test_users.py @@ -21,7 +21,7 @@ from zerver.models import UserProfile, Recipient, \ Realm, RealmDomain, UserActivity, UserHotspot, \ get_user, get_realm, get_client, get_stream, get_stream_recipient, \ get_source_profile, Message, get_context_for_message, \ - ScheduledEmail, check_valid_user_ids, \ + ScheduledEmail, check_valid_user_ids, get_user, \ get_user_by_id_in_realm_including_cross_realm, CustomProfileField from zerver.lib.avatar import avatar_url diff --git a/zerver/views/email_log.py b/zerver/views/email_log.py index e6b220cada..086b31e8d5 100755 --- a/zerver/views/email_log.py +++ b/zerver/views/email_log.py @@ -4,7 +4,7 @@ from django.shortcuts import render, redirect from django.views.decorators.http import require_GET from django.views.decorators.csrf import csrf_exempt -from zerver.models import get_realm, get_user +from zerver.models import get_realm, get_user_by_delivery_email from zerver.lib.notifications import enqueue_welcome_emails from zerver.lib.response import json_success from zproject.email_backends import ( @@ -94,7 +94,7 @@ def generate_all_emails(request: HttpRequest) -> HttpResponse: # Email change successful key = Confirmation.objects.filter(type=Confirmation.EMAIL_CHANGE).latest('id').confirmation_key url = confirmation_url(key, realm.host, Confirmation.EMAIL_CHANGE) - user_profile = get_user(registered_email, realm) + user_profile = get_user_by_delivery_email(registered_email, realm) result = client.get(url) assert result.status_code == 200 @@ -106,6 +106,6 @@ def generate_all_emails(request: HttpRequest) -> HttpResponse: enqueue_welcome_emails(user_profile) # Follow up day1 day2 emails for admin user - enqueue_welcome_emails(get_user("iago@zulip.com", realm), realm_creation=True) + enqueue_welcome_emails(get_user_by_delivery_email("iago@zulip.com", realm), realm_creation=True) return redirect(email_page) diff --git a/zerver/views/presence.py b/zerver/views/presence.py index e66a1bc017..97a6021f28 100644 --- a/zerver/views/presence.py +++ b/zerver/views/presence.py @@ -15,7 +15,8 @@ from zerver.lib.request import has_request_variables, REQ, JsonableError from zerver.lib.response import json_success, json_error from zerver.lib.timestamp import datetime_to_timestamp from zerver.lib.validator import check_bool -from zerver.models import UserActivity, UserPresence, UserProfile, get_active_user +from zerver.models import UserActivity, UserPresence, UserProfile, \ + get_active_user_by_delivery_email def get_status_list(requesting_user_profile: UserProfile) -> Dict[str, Any]: return {'presences': get_status_dict(requesting_user_profile), @@ -24,7 +25,7 @@ def get_status_list(requesting_user_profile: UserProfile) -> Dict[str, Any]: def get_presence_backend(request: HttpRequest, user_profile: UserProfile, email: str) -> HttpResponse: try: - target = get_active_user(email, user_profile.realm) + target = get_active_user_by_delivery_email(email, user_profile.realm) except UserProfile.DoesNotExist: return json_error(_('No such user')) if target.is_bot: diff --git a/zerver/views/registration.py b/zerver/views/registration.py index fe8ee205f6..b0596769b5 100644 --- a/zerver/views/registration.py +++ b/zerver/views/registration.py @@ -14,7 +14,7 @@ from django.core import validators from zerver.context_processors import get_realm_from_request from zerver.models import UserProfile, Realm, Stream, MultiuseInvite, \ name_changes_disabled, email_to_username, email_allowed_for_realm, \ - get_realm, get_user, get_default_stream_groups, DisposableEmailError, \ + get_realm, get_user_by_delivery_email, get_default_stream_groups, DisposableEmailError, \ DomainNotAllowedForRealmError, get_source_profile, EmailContainsPlusError from zerver.lib.send_email import send_email, FromAddress from zerver.lib.events import do_events_register @@ -219,7 +219,7 @@ def accounts_register(request: HttpRequest) -> HttpResponse: if not realm_creation: try: - existing_user_profile = get_user(email, realm) # type: Optional[UserProfile] + existing_user_profile = get_user_by_delivery_email(email, realm) # type: Optional[UserProfile] except UserProfile.DoesNotExist: existing_user_profile = None else: diff --git a/zerver/views/users.py b/zerver/views/users.py index 14fb3214ce..bb824c2a8a 100644 --- a/zerver/views/users.py +++ b/zerver/views/users.py @@ -36,7 +36,7 @@ from zerver.lib.users import check_valid_bot_type, check_bot_creation_policy, \ validate_user_custom_profile_data from zerver.lib.utils import generate_api_key, generate_random_token from zerver.models import UserProfile, Stream, Message, email_allowed_for_realm, \ - get_user, Service, get_user_including_cross_realm, \ + get_user_by_delivery_email, Service, get_user_including_cross_realm, \ DomainNotAllowedForRealmError, DisposableEmailError, get_user_profile_by_id_in_realm, \ EmailContainsPlusError, get_user_by_id_in_realm_including_cross_realm @@ -284,7 +284,7 @@ def add_bot_backend( # We validate client-side as well return json_error(_('Bad name or username')) try: - get_user(email, user_profile.realm) + get_user_by_delivery_email(email, user_profile.realm) return json_error(_("Username already in use")) except UserProfile.DoesNotExist: pass @@ -471,7 +471,7 @@ def create_user_backend(request: HttpRequest, user_profile: UserProfile, return json_error(_("Email addresses containing + are not allowed.")) try: - get_user(email, user_profile.realm) + get_user_by_delivery_email(email, user_profile.realm) return json_error(_("Email '%s' already in use") % (email,)) except UserProfile.DoesNotExist: pass diff --git a/zerver/webhooks/jira/view.py b/zerver/webhooks/jira/view.py index 5bd3653b75..52b2e2679d 100644 --- a/zerver/webhooks/jira/view.py +++ b/zerver/webhooks/jira/view.py @@ -14,7 +14,7 @@ from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_error, json_success from zerver.lib.webhooks.common import check_send_webhook_message, \ UnexpectedWebhookEventType -from zerver.models import Realm, UserProfile, get_user +from zerver.models import Realm, UserProfile, get_user_by_delivery_email IGNORED_EVENTS = [ 'comment_created', # we handle issue_update event instead @@ -112,7 +112,7 @@ def get_issue_string(payload: Dict[str, Any], issue_id: Optional[str]=None) -> s def get_assignee_mention(assignee_email: str, realm: Realm) -> str: if assignee_email != '': try: - assignee_name = get_user(assignee_email, realm).full_name + assignee_name = get_user_by_delivery_email(assignee_email, realm).full_name except UserProfile.DoesNotExist: assignee_name = assignee_email return u"**{}**".format(assignee_name) diff --git a/zerver/webhooks/teamcity/tests.py b/zerver/webhooks/teamcity/tests.py index 9738130f73..fcbf811065 100644 --- a/zerver/webhooks/teamcity/tests.py +++ b/zerver/webhooks/teamcity/tests.py @@ -3,7 +3,7 @@ import ujson from zerver.lib.test_classes import WebhookTestCase from zerver.lib.send_email import FromAddress -from zerver.models import Recipient, get_user, get_realm +from zerver.models import Recipient, get_user_by_delivery_email, get_realm from zerver.webhooks.teamcity.view import MISCONFIGURED_PAYLOAD_TYPE_ERROR_MESSAGE class TeamcityHookTests(WebhookTestCase): @@ -44,7 +44,7 @@ class TeamcityHookTests(WebhookTestCase): def test_non_generic_payload_ignore_pm_notification(self) -> None: expected_message = MISCONFIGURED_PAYLOAD_TYPE_ERROR_MESSAGE.format( - bot_name=get_user('webhook-bot@zulip.com', get_realm('zulip')).full_name, + bot_name=get_user_by_delivery_email('webhook-bot@zulip.com', get_realm('zulip')).full_name, support_email=FromAddress.SUPPORT ).strip() payload = self.get_body('slack_non_generic_payload') diff --git a/zilencer/management/commands/sync_api_key.py b/zilencer/management/commands/sync_api_key.py index 6706a1b283..c58991c357 100644 --- a/zilencer/management/commands/sync_api_key.py +++ b/zilencer/management/commands/sync_api_key.py @@ -4,7 +4,7 @@ from typing import Any from django.core.management.base import BaseCommand -from zerver.models import UserProfile, get_realm, get_user +from zerver.models import UserProfile, get_realm, get_user_by_delivery_email class Command(BaseCommand): help = """Sync your API key from ~/.zuliprc into your development instance""" @@ -21,7 +21,7 @@ class Command(BaseCommand): try: realm = get_realm("zulip") - user_profile = get_user(email, realm) + user_profile = get_user_by_delivery_email(email, realm) user_profile.api_key = api_key user_profile.save(update_fields=["api_key"]) except UserProfile.DoesNotExist: diff --git a/zproject/backends.py b/zproject/backends.py index ebacd01e30..cbd6befdbc 100644 --- a/zproject/backends.py +++ b/zproject/backends.py @@ -23,7 +23,7 @@ from zerver.lib.request import JsonableError from zerver.lib.subdomains import user_matches_subdomain, get_subdomain from zerver.lib.users import check_full_name from zerver.models import UserProfile, Realm, get_user_profile_by_id, \ - remote_user_to_email, email_to_username, get_realm, get_user + remote_user_to_email, email_to_username, get_realm, get_user_by_delivery_email def pad_method_dict(method_dict: Dict[str, bool]) -> Dict[str, bool]: """Pads an authentication methods dict to contain all auth backends @@ -83,13 +83,13 @@ def require_email_format_usernames(realm: Optional[Realm]=None) -> bool: def common_get_active_user(email: str, realm: Realm, return_data: Optional[Dict[str, Any]]=None) -> Optional[UserProfile]: try: - user_profile = get_user(email, realm) + user_profile = get_user_by_delivery_email(email, realm) except UserProfile.DoesNotExist: # If the user doesn't have an account in the target realm, we # check whether they might have an account in another realm, # and if so, provide a helpful error message via # `invalid_subdomain`. - if not UserProfile.objects.filter(email__iexact=email).exists(): + if not UserProfile.objects.filter(delivery_email__iexact=email).exists(): return None if return_data is not None: return_data['invalid_subdomain'] = True