mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 14:03:30 +00:00 
			
		
		
		
	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.
This commit is contained in:
		@@ -586,15 +586,15 @@ def user_activity_intervals() -> Tuple[mark_safe, Dict[str, float]]:
 | 
				
			|||||||
    ).only(
 | 
					    ).only(
 | 
				
			||||||
        'start',
 | 
					        'start',
 | 
				
			||||||
        'end',
 | 
					        'end',
 | 
				
			||||||
        'user_profile__email',
 | 
					        'user_profile__delivery_email',
 | 
				
			||||||
        'user_profile__realm__string_id'
 | 
					        'user_profile__realm__string_id'
 | 
				
			||||||
    ).order_by(
 | 
					    ).order_by(
 | 
				
			||||||
        'user_profile__realm__string_id',
 | 
					        'user_profile__realm__string_id',
 | 
				
			||||||
        'user_profile__email'
 | 
					        'user_profile__delivery_email'
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    by_string_id = lambda row: row.user_profile.realm.string_id
 | 
					    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 = {}
 | 
					    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:
 | 
					def get_user_activity_records_for_realm(realm: str, is_bot: bool) -> QuerySet:
 | 
				
			||||||
    fields = [
 | 
					    fields = [
 | 
				
			||||||
        'user_profile__full_name',
 | 
					        'user_profile__full_name',
 | 
				
			||||||
        'user_profile__email',
 | 
					        'user_profile__delivery_email',
 | 
				
			||||||
        'query',
 | 
					        'query',
 | 
				
			||||||
        'client__name',
 | 
					        'client__name',
 | 
				
			||||||
        'count',
 | 
					        '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_active=True,
 | 
				
			||||||
        user_profile__is_bot=is_bot
 | 
					        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)
 | 
					    records = records.select_related('user_profile', 'client').only(*fields)
 | 
				
			||||||
    return records
 | 
					    return records
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -905,7 +905,7 @@ def get_user_activity_records_for_email(email: str) -> List[QuerySet]:
 | 
				
			|||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    records = UserActivity.objects.filter(
 | 
					    records = UserActivity.objects.filter(
 | 
				
			||||||
        user_profile__email=email
 | 
					        user_profile__delivery_email=email
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    records = records.order_by("-last_visit")
 | 
					    records = records.order_by("-last_visit")
 | 
				
			||||||
    records = records.select_related('user_profile', 'client').only(*fields)
 | 
					    records = records.select_related('user_profile', 'client').only(*fields)
 | 
				
			||||||
@@ -1079,7 +1079,7 @@ def realm_user_summary_table(all_records: List[QuerySet],
 | 
				
			|||||||
    user_records = {}
 | 
					    user_records = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def by_email(record: QuerySet) -> str:
 | 
					    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):
 | 
					    for email, records in itertools.groupby(all_records, by_email):
 | 
				
			||||||
        user_records[email] = get_user_activity_summary(list(records))
 | 
					        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:
 | 
					    except Realm.DoesNotExist:
 | 
				
			||||||
        return HttpResponseNotFound("Realm %s does not exist" % (realm_str,))
 | 
					        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')]:
 | 
					    for is_bot, page_title in [(False, 'Humans'), (True, 'Bots')]:
 | 
				
			||||||
        all_records = list(get_user_activity_records_for_realm(realm_str, is_bot))
 | 
					        all_records = list(get_user_activity_records_for_realm(realm_str, is_bot))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
					  eventually call the `send_email` function. The most interesting one is
 | 
				
			||||||
  `send_future_email`. The `ScheduledEmail` entries are eventually processed
 | 
					  `send_future_email`. The `ScheduledEmail` entries are eventually processed
 | 
				
			||||||
  by a supervisor job that runs `zerver/management/commands/deliver_email.py`.
 | 
					  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
 | 
					* A good way to find a bunch of example email pathways is to `git grep` for
 | 
				
			||||||
  `zerver/emails` in the `zerver/` directory.
 | 
					  `zerver/emails` in the `zerver/` directory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -235,7 +235,7 @@ def validate_api_key(request: HttpRequest, role: Optional[str],
 | 
				
			|||||||
        raise JsonableError(_("This API is not available to incoming webhook bots."))
 | 
					        raise JsonableError(_("This API is not available to incoming webhook bots."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    request.user = user_profile
 | 
					    request.user = user_profile
 | 
				
			||||||
    request._email = user_profile.email
 | 
					    request._email = user_profile.delivery_email
 | 
				
			||||||
    process_client(request, user_profile, client_name=client_name)
 | 
					    process_client(request, user_profile, client_name=client_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return user_profile
 | 
					    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["SERVER_NAME"] == "127.0.0.1" and
 | 
				
			||||||
             request.META["REMOTE_ADDR"] == "127.0.0.1")):
 | 
					             request.META["REMOTE_ADDR"] == "127.0.0.1")):
 | 
				
			||||||
        logging.warning("User %s (%s) attempted to access API on wrong subdomain (%s)" % (
 | 
					        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"))
 | 
					        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:
 | 
					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)
 | 
					        user_profile = get_user_profile_by_api_key(api_key)
 | 
				
			||||||
    except UserProfile.DoesNotExist:
 | 
					    except UserProfile.DoesNotExist:
 | 
				
			||||||
        raise JsonableError(_("Invalid API key"))
 | 
					        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
 | 
					        # This covers the case that the API key is correct, but for a
 | 
				
			||||||
        # different user.  We may end up wanting to relaxing this
 | 
					        # different user.  We may end up wanting to relaxing this
 | 
				
			||||||
        # constraint or give a different error message in the future.
 | 
					        # constraint or give a different error message in the future.
 | 
				
			||||||
@@ -311,7 +311,7 @@ body:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
{body}
 | 
					{body}
 | 
				
			||||||
    """.format(
 | 
					    """.format(
 | 
				
			||||||
        email=user_profile.email,
 | 
					        email=user_profile.delivery_email,
 | 
				
			||||||
        realm=user_profile.realm.string_id,
 | 
					        realm=user_profile.realm.string_id,
 | 
				
			||||||
        client_name=request.client.name,
 | 
					        client_name=request.client.name,
 | 
				
			||||||
        body=payload,
 | 
					        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.
 | 
					    and also adds helpful data needed by our server logs.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    django_login(request, user_profile)
 | 
					    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)
 | 
					    process_client(request, user_profile, is_browser_view=True)
 | 
				
			||||||
    if settings.TWO_FACTOR_AUTHENTICATION_ENABLED:
 | 
					    if settings.TWO_FACTOR_AUTHENTICATION_ENABLED:
 | 
				
			||||||
        # Login with two factor authentication as well.
 | 
					        # 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:
 | 
					def add_logging_data(view_func: ViewFuncT) -> ViewFuncT:
 | 
				
			||||||
    @wraps(view_func)
 | 
					    @wraps(view_func)
 | 
				
			||||||
    def _wrapped_view_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
 | 
					    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,
 | 
					        process_client(request, request.user, is_browser_view=True,
 | 
				
			||||||
                       query=view_func.__name__)
 | 
					                       query=view_func.__name__)
 | 
				
			||||||
        return rate_limit()(view_func)(request, *args, **kwargs)
 | 
					        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,
 | 
					    process_client(request, user_profile, is_browser_view=True,
 | 
				
			||||||
                   query=view_func.__name__)
 | 
					                   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)
 | 
					    return rate_limit()(view_func)(request, user_profile, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Checks if the request is a POST request and that the user is logged
 | 
					# Checks if the request is a POST request and that the user is logged
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,8 @@ from zerver.lib.request import JsonableError
 | 
				
			|||||||
from zerver.lib.send_email import send_email, FromAddress
 | 
					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.subdomains import get_subdomain, user_matches_subdomain, is_root_domain_available
 | 
				
			||||||
from zerver.lib.users import check_full_name
 | 
					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, \
 | 
					    email_allowed_for_realm, DisposableEmailError, DomainNotAllowedForRealmError, \
 | 
				
			||||||
    EmailContainsPlusError
 | 
					    EmailContainsPlusError
 | 
				
			||||||
from zproject.backends import email_auth_enabled, email_belongs_to_ldap
 | 
					from zproject.backends import email_auth_enabled, email_belongs_to_ldap
 | 
				
			||||||
@@ -234,7 +235,7 @@ class ZulipPasswordResetForm(PasswordResetForm):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        user = None  # type: Optional[UserProfile]
 | 
					        user = None  # type: Optional[UserProfile]
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            user = get_user(email, realm)
 | 
					            user = get_user_by_delivery_email(email, realm)
 | 
				
			||||||
        except UserProfile.DoesNotExist:
 | 
					        except UserProfile.DoesNotExist:
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -256,7 +257,8 @@ class ZulipPasswordResetForm(PasswordResetForm):
 | 
				
			|||||||
                       context=context)
 | 
					                       context=context)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            context['active_account_in_realm'] = False
 | 
					            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:
 | 
					            if active_accounts_in_other_realms:
 | 
				
			||||||
                context['active_accounts_in_other_realms'] = 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],
 | 
					            send_email('zerver/emails/password_reset', to_emails=[email],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,7 +87,7 @@ from zerver.models import Realm, RealmEmoji, Stream, UserProfile, UserActivity,
 | 
				
			|||||||
    get_user_profile_by_id, PreregistrationUser, get_display_recipient, \
 | 
					    get_user_profile_by_id, PreregistrationUser, get_display_recipient, \
 | 
				
			||||||
    get_realm, bulk_get_recipients, get_stream_recipient, get_stream_recipients, \
 | 
					    get_realm, bulk_get_recipients, get_stream_recipient, get_stream_recipients, \
 | 
				
			||||||
    email_allowed_for_realm, email_to_username, display_recipient_cache_key, \
 | 
					    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, \
 | 
					    UserActivityInterval, active_user_ids, get_active_streams, \
 | 
				
			||||||
    realm_filters_for_realm, RealmFilter, stream_name_in_use, \
 | 
					    realm_filters_for_realm, RealmFilter, stream_name_in_use, \
 | 
				
			||||||
    get_old_unclaimed_attachments, is_cross_realm_bot_email, \
 | 
					    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
 | 
					    # inactive so we can keep track of the PreregistrationUser we
 | 
				
			||||||
    # actually used for analytics
 | 
					    # actually used for analytics
 | 
				
			||||||
    if prereg_user is not None:
 | 
					    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)
 | 
					            id=prereg_user.id).update(status=0)
 | 
				
			||||||
        if prereg_user.referred_by is not None:
 | 
					        if prereg_user.referred_by is not None:
 | 
				
			||||||
            notify_invites_changed(user_profile)
 | 
					            notify_invites_changed(user_profile)
 | 
				
			||||||
    else:
 | 
					    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)
 | 
					    notify_new_user(user_profile)
 | 
				
			||||||
    if user_profile.realm.send_welcome_emails:
 | 
					    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,
 | 
					def create_mirror_user_if_needed(realm: Realm, email: str,
 | 
				
			||||||
                                 email_to_fullname: Callable[[str], str]) -> UserProfile:
 | 
					                                 email_to_fullname: Callable[[str], str]) -> UserProfile:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        return get_user(email, realm)
 | 
					        return get_user_by_delivery_email(email, realm)
 | 
				
			||||||
    except UserProfile.DoesNotExist:
 | 
					    except UserProfile.DoesNotExist:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            # Forge a user for this person
 | 
					            # Forge a user for this person
 | 
				
			||||||
@@ -824,7 +824,7 @@ def create_mirror_user_if_needed(realm: Realm, email: str,
 | 
				
			|||||||
                is_mirror_dummy=True,
 | 
					                is_mirror_dummy=True,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        except IntegrityError:
 | 
					        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:
 | 
					def send_welcome_bot_response(message: MutableMapping[str, Any]) -> None:
 | 
				
			||||||
    welcome_bot = get_system_bot(settings.WELCOME_BOT)
 | 
					    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)
 | 
					    email_not_system_bot(email)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        existing_user_profile = get_user(email, target_realm)
 | 
					        existing_user_profile = get_user_by_delivery_email(email, target_realm)
 | 
				
			||||||
    except UserProfile.DoesNotExist:
 | 
					    except UserProfile.DoesNotExist:
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -356,7 +356,7 @@ def delete_user_profile_caches(user_profiles: Iterable['UserProfile']) -> None:
 | 
				
			|||||||
    from zerver.lib.users import get_all_api_keys
 | 
					    from zerver.lib.users import get_all_api_keys
 | 
				
			||||||
    keys = []
 | 
					    keys = []
 | 
				
			||||||
    for user_profile in user_profiles:
 | 
					    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))
 | 
					        keys.append(user_profile_by_id_cache_key(user_profile.id))
 | 
				
			||||||
        for api_key in get_all_api_keys(user_profile):
 | 
					        for api_key in get_all_api_keys(user_profile):
 | 
				
			||||||
            keys.append(user_profile_by_api_key_cache_key(api_key))
 | 
					            keys.append(user_profile_by_api_key_cache_key(api_key))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,7 +48,8 @@ def user_cache_items(items_for_remote_cache: Dict[str, Tuple[UserProfile]],
 | 
				
			|||||||
                     user_profile: UserProfile) -> None:
 | 
					                     user_profile: UserProfile) -> None:
 | 
				
			||||||
    for api_key in get_all_api_keys(user_profile):
 | 
					    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_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
 | 
					    # We have other user_profile caches, but none of them are on the
 | 
				
			||||||
    # core serving path for lots of requests.
 | 
					    # core serving path for lots of requests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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.
 | 
					        # throw an error if they don't exist.
 | 
				
			||||||
        if realm is not None:
 | 
					        if realm is not None:
 | 
				
			||||||
            try:
 | 
					            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:
 | 
					            except UserProfile.DoesNotExist:
 | 
				
			||||||
                raise CommandError("The realm '%s' does not contain a user with email '%s'" % (realm, email))
 | 
					                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
 | 
					        # optimistically try to see if there is exactly one user with
 | 
				
			||||||
        # that email; if so, we'll return it.
 | 
					        # that email; if so, we'll return it.
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            return UserProfile.objects.select_related().get(email__iexact=email.strip())
 | 
					            return UserProfile.objects.select_related().get(delivery_email__iexact=email.strip())
 | 
				
			||||||
        except MultipleObjectsReturned:
 | 
					        except MultipleObjectsReturned:
 | 
				
			||||||
            raise CommandError("This Zulip server contains multiple users with that email " +
 | 
					            raise CommandError("This Zulip server contains multiple users with that email " +
 | 
				
			||||||
                               "(in different realms); please pass `--realm` "
 | 
					                               "(in different realms); please pass `--realm` "
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -508,7 +508,7 @@ def enqueue_welcome_emails(user: UserProfile, realm_creation: bool=False) -> Non
 | 
				
			|||||||
        from_address = FromAddress.SUPPORT
 | 
					        from_address = FromAddress.SUPPORT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    other_account_count = UserProfile.objects.filter(
 | 
					    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")
 | 
					    unsubscribe_link = one_click_unsubscribe_link(user, "welcome")
 | 
				
			||||||
    context = common_context(user)
 | 
					    context = common_context(user)
 | 
				
			||||||
    context.update({
 | 
					    context.update({
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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]]]:
 | 
					def get_accounts_for_email(email: str) -> List[Dict[str, Optional[str]]]:
 | 
				
			||||||
    if settings.PRODUCTION:  # nocoverage
 | 
					    if settings.PRODUCTION:  # nocoverage
 | 
				
			||||||
        return []
 | 
					        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_active=True,
 | 
				
			||||||
                                                                  is_bot=False,
 | 
					                                                                  is_bot=False,
 | 
				
			||||||
                                                                  realm__deactivated=False)
 | 
					                                                                  realm__deactivated=False)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@ from django.utils.timezone import now as timezone_now
 | 
				
			|||||||
from zerver.lib.context_managers import lockfile
 | 
					from zerver.lib.context_managers import lockfile
 | 
				
			||||||
from zerver.lib.logging_util import log_to_file
 | 
					from zerver.lib.logging_util import log_to_file
 | 
				
			||||||
from zerver.lib.management import sleep_forever
 | 
					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.actions import do_send_messages
 | 
				
			||||||
from zerver.lib.addressee import Addressee
 | 
					from zerver.lib.addressee import Addressee
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -44,7 +44,7 @@ Usage: ./manage.py deliver_scheduled_messages
 | 
				
			|||||||
        if delivery_type == ScheduledMessage.SEND_LATER:
 | 
					        if delivery_type == ScheduledMessage.SEND_LATER:
 | 
				
			||||||
            message.sender = original_sender
 | 
					            message.sender = original_sender
 | 
				
			||||||
        elif delivery_type == ScheduledMessage.REMIND:
 | 
					        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,
 | 
					        return {'message': message, 'stream': scheduled_message.stream,
 | 
				
			||||||
                'realm': scheduled_message.realm}
 | 
					                'realm': scheduled_message.realm}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
					@cache_with_key(user_profile_by_email_cache_key, timeout=3600*24*7)
 | 
				
			||||||
def get_user_profile_by_email(email: str) -> UserProfile:
 | 
					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)
 | 
					@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:
 | 
					def get_user_profile_by_api_key(api_key: str) -> UserProfile:
 | 
				
			||||||
    return UserProfile.objects.select_related().get(api_key=api_key)
 | 
					    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)
 | 
					@cache_with_key(user_profile_cache_key, timeout=3600*24*7)
 | 
				
			||||||
def get_user(email: str, realm: Realm) -> UserProfile:
 | 
					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)
 | 
					    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:
 | 
					def get_active_user(email: str, realm: Realm) -> UserProfile:
 | 
				
			||||||
    user_profile = get_user(email, realm)
 | 
					    user_profile = get_user(email, realm)
 | 
				
			||||||
    if not user_profile.is_active:
 | 
					    if not user_profile.is_active:
 | 
				
			||||||
@@ -1858,7 +1874,7 @@ def get_source_profile(email: str, string_id: str) -> Optional[UserProfile]:
 | 
				
			|||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        return get_user(email, realm)
 | 
					        return get_user_by_delivery_email(email, realm)
 | 
				
			||||||
    except UserProfile.DoesNotExist:
 | 
					    except UserProfile.DoesNotExist:
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,7 +45,7 @@ from zerver.models import (
 | 
				
			|||||||
    get_display_recipient, Message, Realm, Recipient, Stream, Subscription,
 | 
					    get_display_recipient, Message, Realm, Recipient, Stream, Subscription,
 | 
				
			||||||
    DefaultStream, UserProfile, get_user_profile_by_id, active_non_guest_user_ids,
 | 
					    DefaultStream, UserProfile, get_user_profile_by_id, active_non_guest_user_ids,
 | 
				
			||||||
    get_default_stream_groups, flush_per_request_caches, DefaultStreamGroup,
 | 
					    get_default_stream_groups, flush_per_request_caches, DefaultStreamGroup,
 | 
				
			||||||
    get_client,
 | 
					    get_client, get_user
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from zerver.lib.actions import (
 | 
					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,
 | 
					    do_create_realm, do_remove_default_stream, bulk_get_subscriber_user_ids,
 | 
				
			||||||
    gather_subscriptions_helper, bulk_add_subscriptions, bulk_remove_subscriptions,
 | 
					    gather_subscriptions_helper, bulk_add_subscriptions, bulk_remove_subscriptions,
 | 
				
			||||||
    gather_subscriptions, get_default_streams_for_realm, get_realm, get_stream,
 | 
					    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,
 | 
					    create_stream_if_needed, create_streams_if_needed,
 | 
				
			||||||
    ensure_stream,
 | 
					    ensure_stream,
 | 
				
			||||||
    do_deactivate_stream,
 | 
					    do_deactivate_stream,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ from zerver.models import UserProfile, Recipient, \
 | 
				
			|||||||
    Realm, RealmDomain, UserActivity, UserHotspot, \
 | 
					    Realm, RealmDomain, UserActivity, UserHotspot, \
 | 
				
			||||||
    get_user, get_realm, get_client, get_stream, get_stream_recipient, \
 | 
					    get_user, get_realm, get_client, get_stream, get_stream_recipient, \
 | 
				
			||||||
    get_source_profile, Message, get_context_for_message, \
 | 
					    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
 | 
					    get_user_by_id_in_realm_including_cross_realm, CustomProfileField
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from zerver.lib.avatar import avatar_url
 | 
					from zerver.lib.avatar import avatar_url
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ from django.shortcuts import render, redirect
 | 
				
			|||||||
from django.views.decorators.http import require_GET
 | 
					from django.views.decorators.http import require_GET
 | 
				
			||||||
from django.views.decorators.csrf import csrf_exempt
 | 
					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.notifications import enqueue_welcome_emails
 | 
				
			||||||
from zerver.lib.response import json_success
 | 
					from zerver.lib.response import json_success
 | 
				
			||||||
from zproject.email_backends import (
 | 
					from zproject.email_backends import (
 | 
				
			||||||
@@ -94,7 +94,7 @@ def generate_all_emails(request: HttpRequest) -> HttpResponse:
 | 
				
			|||||||
    # Email change successful
 | 
					    # Email change successful
 | 
				
			||||||
    key = Confirmation.objects.filter(type=Confirmation.EMAIL_CHANGE).latest('id').confirmation_key
 | 
					    key = Confirmation.objects.filter(type=Confirmation.EMAIL_CHANGE).latest('id').confirmation_key
 | 
				
			||||||
    url = confirmation_url(key, realm.host, Confirmation.EMAIL_CHANGE)
 | 
					    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)
 | 
					    result = client.get(url)
 | 
				
			||||||
    assert result.status_code == 200
 | 
					    assert result.status_code == 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -106,6 +106,6 @@ def generate_all_emails(request: HttpRequest) -> HttpResponse:
 | 
				
			|||||||
    enqueue_welcome_emails(user_profile)
 | 
					    enqueue_welcome_emails(user_profile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Follow up day1 day2 emails for admin user
 | 
					    # 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)
 | 
					    return redirect(email_page)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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.response import json_success, json_error
 | 
				
			||||||
from zerver.lib.timestamp import datetime_to_timestamp
 | 
					from zerver.lib.timestamp import datetime_to_timestamp
 | 
				
			||||||
from zerver.lib.validator import check_bool
 | 
					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]:
 | 
					def get_status_list(requesting_user_profile: UserProfile) -> Dict[str, Any]:
 | 
				
			||||||
    return {'presences': get_status_dict(requesting_user_profile),
 | 
					    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,
 | 
					def get_presence_backend(request: HttpRequest, user_profile: UserProfile,
 | 
				
			||||||
                         email: str) -> HttpResponse:
 | 
					                         email: str) -> HttpResponse:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        target = get_active_user(email, user_profile.realm)
 | 
					        target = get_active_user_by_delivery_email(email, user_profile.realm)
 | 
				
			||||||
    except UserProfile.DoesNotExist:
 | 
					    except UserProfile.DoesNotExist:
 | 
				
			||||||
        return json_error(_('No such user'))
 | 
					        return json_error(_('No such user'))
 | 
				
			||||||
    if target.is_bot:
 | 
					    if target.is_bot:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,7 @@ from django.core import validators
 | 
				
			|||||||
from zerver.context_processors import get_realm_from_request
 | 
					from zerver.context_processors import get_realm_from_request
 | 
				
			||||||
from zerver.models import UserProfile, Realm, Stream, MultiuseInvite, \
 | 
					from zerver.models import UserProfile, Realm, Stream, MultiuseInvite, \
 | 
				
			||||||
    name_changes_disabled, email_to_username, email_allowed_for_realm, \
 | 
					    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
 | 
					    DomainNotAllowedForRealmError, get_source_profile, EmailContainsPlusError
 | 
				
			||||||
from zerver.lib.send_email import send_email, FromAddress
 | 
					from zerver.lib.send_email import send_email, FromAddress
 | 
				
			||||||
from zerver.lib.events import do_events_register
 | 
					from zerver.lib.events import do_events_register
 | 
				
			||||||
@@ -219,7 +219,7 @@ def accounts_register(request: HttpRequest) -> HttpResponse:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if not realm_creation:
 | 
					        if not realm_creation:
 | 
				
			||||||
            try:
 | 
					            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:
 | 
					            except UserProfile.DoesNotExist:
 | 
				
			||||||
                existing_user_profile = None
 | 
					                existing_user_profile = None
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,7 @@ from zerver.lib.users import check_valid_bot_type, check_bot_creation_policy, \
 | 
				
			|||||||
    validate_user_custom_profile_data
 | 
					    validate_user_custom_profile_data
 | 
				
			||||||
from zerver.lib.utils import generate_api_key, generate_random_token
 | 
					from zerver.lib.utils import generate_api_key, generate_random_token
 | 
				
			||||||
from zerver.models import UserProfile, Stream, Message, email_allowed_for_realm, \
 | 
					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, \
 | 
					    DomainNotAllowedForRealmError, DisposableEmailError, get_user_profile_by_id_in_realm, \
 | 
				
			||||||
    EmailContainsPlusError, get_user_by_id_in_realm_including_cross_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
 | 
					        # We validate client-side as well
 | 
				
			||||||
        return json_error(_('Bad name or username'))
 | 
					        return json_error(_('Bad name or username'))
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        get_user(email, user_profile.realm)
 | 
					        get_user_by_delivery_email(email, user_profile.realm)
 | 
				
			||||||
        return json_error(_("Username already in use"))
 | 
					        return json_error(_("Username already in use"))
 | 
				
			||||||
    except UserProfile.DoesNotExist:
 | 
					    except UserProfile.DoesNotExist:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
@@ -471,7 +471,7 @@ def create_user_backend(request: HttpRequest, user_profile: UserProfile,
 | 
				
			|||||||
        return json_error(_("Email addresses containing + are not allowed."))
 | 
					        return json_error(_("Email addresses containing + are not allowed."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    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,))
 | 
					        return json_error(_("Email '%s' already in use") % (email,))
 | 
				
			||||||
    except UserProfile.DoesNotExist:
 | 
					    except UserProfile.DoesNotExist:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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.response import json_error, json_success
 | 
				
			||||||
from zerver.lib.webhooks.common import check_send_webhook_message, \
 | 
					from zerver.lib.webhooks.common import check_send_webhook_message, \
 | 
				
			||||||
    UnexpectedWebhookEventType
 | 
					    UnexpectedWebhookEventType
 | 
				
			||||||
from zerver.models import Realm, UserProfile, get_user
 | 
					from zerver.models import Realm, UserProfile, get_user_by_delivery_email
 | 
				
			||||||
 | 
					
 | 
				
			||||||
IGNORED_EVENTS = [
 | 
					IGNORED_EVENTS = [
 | 
				
			||||||
    'comment_created',  # we handle issue_update event instead
 | 
					    '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:
 | 
					def get_assignee_mention(assignee_email: str, realm: Realm) -> str:
 | 
				
			||||||
    if assignee_email != '':
 | 
					    if assignee_email != '':
 | 
				
			||||||
        try:
 | 
					        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:
 | 
					        except UserProfile.DoesNotExist:
 | 
				
			||||||
            assignee_name = assignee_email
 | 
					            assignee_name = assignee_email
 | 
				
			||||||
        return u"**{}**".format(assignee_name)
 | 
					        return u"**{}**".format(assignee_name)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ import ujson
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from zerver.lib.test_classes import WebhookTestCase
 | 
					from zerver.lib.test_classes import WebhookTestCase
 | 
				
			||||||
from zerver.lib.send_email import FromAddress
 | 
					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
 | 
					from zerver.webhooks.teamcity.view import MISCONFIGURED_PAYLOAD_TYPE_ERROR_MESSAGE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TeamcityHookTests(WebhookTestCase):
 | 
					class TeamcityHookTests(WebhookTestCase):
 | 
				
			||||||
@@ -44,7 +44,7 @@ class TeamcityHookTests(WebhookTestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def test_non_generic_payload_ignore_pm_notification(self) -> None:
 | 
					    def test_non_generic_payload_ignore_pm_notification(self) -> None:
 | 
				
			||||||
        expected_message = MISCONFIGURED_PAYLOAD_TYPE_ERROR_MESSAGE.format(
 | 
					        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
 | 
					            support_email=FromAddress.SUPPORT
 | 
				
			||||||
        ).strip()
 | 
					        ).strip()
 | 
				
			||||||
        payload = self.get_body('slack_non_generic_payload')
 | 
					        payload = self.get_body('slack_non_generic_payload')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ from typing import Any
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from django.core.management.base import BaseCommand
 | 
					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):
 | 
					class Command(BaseCommand):
 | 
				
			||||||
    help = """Sync your API key from ~/.zuliprc into your development instance"""
 | 
					    help = """Sync your API key from ~/.zuliprc into your development instance"""
 | 
				
			||||||
@@ -21,7 +21,7 @@ class Command(BaseCommand):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            realm = get_realm("zulip")
 | 
					            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.api_key = api_key
 | 
				
			||||||
            user_profile.save(update_fields=["api_key"])
 | 
					            user_profile.save(update_fields=["api_key"])
 | 
				
			||||||
        except UserProfile.DoesNotExist:
 | 
					        except UserProfile.DoesNotExist:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@ from zerver.lib.request import JsonableError
 | 
				
			|||||||
from zerver.lib.subdomains import user_matches_subdomain, get_subdomain
 | 
					from zerver.lib.subdomains import user_matches_subdomain, get_subdomain
 | 
				
			||||||
from zerver.lib.users import check_full_name
 | 
					from zerver.lib.users import check_full_name
 | 
				
			||||||
from zerver.models import UserProfile, Realm, get_user_profile_by_id, \
 | 
					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]:
 | 
					def pad_method_dict(method_dict: Dict[str, bool]) -> Dict[str, bool]:
 | 
				
			||||||
    """Pads an authentication methods dict to contain all auth backends
 | 
					    """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,
 | 
					def common_get_active_user(email: str, realm: Realm,
 | 
				
			||||||
                           return_data: Optional[Dict[str, Any]]=None) -> Optional[UserProfile]:
 | 
					                           return_data: Optional[Dict[str, Any]]=None) -> Optional[UserProfile]:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        user_profile = get_user(email, realm)
 | 
					        user_profile = get_user_by_delivery_email(email, realm)
 | 
				
			||||||
    except UserProfile.DoesNotExist:
 | 
					    except UserProfile.DoesNotExist:
 | 
				
			||||||
        # If the user doesn't have an account in the target realm, we
 | 
					        # If the user doesn't have an account in the target realm, we
 | 
				
			||||||
        # check whether they might have an account in another realm,
 | 
					        # check whether they might have an account in another realm,
 | 
				
			||||||
        # and if so, provide a helpful error message via
 | 
					        # and if so, provide a helpful error message via
 | 
				
			||||||
        # `invalid_subdomain`.
 | 
					        # `invalid_subdomain`.
 | 
				
			||||||
        if not UserProfile.objects.filter(email__iexact=email).exists():
 | 
					        if not UserProfile.objects.filter(delivery_email__iexact=email).exists():
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
        if return_data is not None:
 | 
					        if return_data is not None:
 | 
				
			||||||
            return_data['invalid_subdomain'] = True
 | 
					            return_data['invalid_subdomain'] = True
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user