mirror of
https://github.com/zulip/zulip.git
synced 2025-11-04 14:03:30 +00:00
performance: Optimize get_realm_email_validator.
We now query RealmDomain objects up front. This change is minor in most circumstances--it sometimes saves a round trip to the database; other times, it actually brings back slightly more data (optimistically). The big win will come in a subsequent commit, where we avoid running these queries in a loop for every callback. Note that I'm not sure if we intentionally omitted checks for emails with "+" in them for some circumstances, but I just preserved the behavior.
This commit is contained in:
@@ -575,28 +575,69 @@ class EmailContainsPlusError(Exception):
|
|||||||
# So for invite-only realms, this is the test for whether a user can be invited,
|
# So for invite-only realms, this is the test for whether a user can be invited,
|
||||||
# not whether the user can sign up currently.)
|
# not whether the user can sign up currently.)
|
||||||
def email_allowed_for_realm(email: str, realm: Realm) -> None:
|
def email_allowed_for_realm(email: str, realm: Realm) -> None:
|
||||||
|
'''
|
||||||
|
Avoid calling this in a loop!
|
||||||
|
Instead, call get_realm_email_validator()
|
||||||
|
outside of the loop.
|
||||||
|
'''
|
||||||
get_realm_email_validator(realm)(email)
|
get_realm_email_validator(realm)(email)
|
||||||
|
|
||||||
|
def validate_disposable(email: str) -> None:
|
||||||
|
if is_disposable_domain(email_to_domain(email)):
|
||||||
|
raise DisposableEmailError
|
||||||
|
|
||||||
def get_realm_email_validator(realm: Realm) -> Callable[[str], None]:
|
def get_realm_email_validator(realm: Realm) -> Callable[[str], None]:
|
||||||
|
if not realm.emails_restricted_to_domains:
|
||||||
|
# Should we also do '+' check for non-resticted realms?
|
||||||
|
if realm.disallow_disposable_email_addresses:
|
||||||
|
return validate_disposable
|
||||||
|
|
||||||
|
# allow any email through
|
||||||
|
return lambda email: None
|
||||||
|
|
||||||
|
'''
|
||||||
|
RESTRICTIVE REALMS:
|
||||||
|
|
||||||
|
Some realms only allow emails within a set
|
||||||
|
of domains that are configured in RealmDomain.
|
||||||
|
|
||||||
|
We get the set of domains up front so that
|
||||||
|
folks can validate multiple emails without
|
||||||
|
multiple round trips to the database.
|
||||||
|
'''
|
||||||
|
|
||||||
|
query = RealmDomain.objects.filter(realm=realm)
|
||||||
|
rows = list(query.values('allow_subdomains', 'domain'))
|
||||||
|
|
||||||
|
allowed_domains = {
|
||||||
|
r['domain'] for r in rows
|
||||||
|
}
|
||||||
|
|
||||||
|
allowed_subdomains = {
|
||||||
|
r['domain'] for r in rows
|
||||||
|
if r['allow_subdomains']
|
||||||
|
}
|
||||||
|
|
||||||
def validate(email: str) -> None:
|
def validate(email: str) -> None:
|
||||||
if not realm.emails_restricted_to_domains:
|
'''
|
||||||
if realm.disallow_disposable_email_addresses and \
|
We don't have to do a "disposable" check for restricted
|
||||||
is_disposable_domain(email_to_domain(email)):
|
domains, since the realm is already giving us
|
||||||
raise DisposableEmailError
|
a small whitelist.
|
||||||
return
|
'''
|
||||||
elif '+' in email_to_username(email):
|
|
||||||
|
if '+' in email_to_username(email):
|
||||||
raise EmailContainsPlusError
|
raise EmailContainsPlusError
|
||||||
|
|
||||||
domain = email_to_domain(email)
|
domain = email_to_domain(email)
|
||||||
query = RealmDomain.objects.filter(realm=realm)
|
|
||||||
if query.filter(domain=domain).exists():
|
if domain in allowed_domains:
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
query = query.filter(allow_subdomains=True)
|
while len(domain) > 0:
|
||||||
while len(domain) > 0:
|
subdomain, sep, domain = domain.partition('.')
|
||||||
subdomain, sep, domain = domain.partition('.')
|
if domain in allowed_subdomains:
|
||||||
if query.filter(domain=domain).exists():
|
return
|
||||||
return
|
|
||||||
raise DomainNotAllowedForRealmError
|
raise DomainNotAllowedForRealmError
|
||||||
|
|
||||||
return validate
|
return validate
|
||||||
|
|||||||
Reference in New Issue
Block a user