Prevent code from using email domain to determine realm when subdomains.

Also removes the intermediate step of going through Realm.domain in the
non-subdomains case. Part of a larger project to remove Realm.domain
entirely.
This commit is contained in:
Rishi Gupta 2016-11-08 17:40:54 -08:00 committed by Tim Abbott
parent 411a7b08e0
commit c1713c9659
9 changed files with 46 additions and 41 deletions

View File

@ -14,7 +14,7 @@ from zerver.lib.actions import do_change_password, is_inactive, user_email_is_un
from zerver.lib.name_restrictions import is_reserved_subdomain, is_disposable_domain from zerver.lib.name_restrictions import is_reserved_subdomain, is_disposable_domain
from zerver.lib.utils import get_subdomain, check_subdomain from zerver.lib.utils import get_subdomain, check_subdomain
from zerver.models import Realm, get_user_profile_by_email, UserProfile, \ from zerver.models import Realm, get_user_profile_by_email, UserProfile, \
completely_open, resolve_email_to_domain, get_realm, get_realm_by_string_id, \ completely_open, get_realm, get_realm_by_email_domain, get_realm_by_string_id, \
get_unique_open_realm, split_email_to_domain, email_allowed_for_realm get_unique_open_realm, split_email_to_domain, email_allowed_for_realm
from zproject.backends import password_auth_enabled from zproject.backends import password_auth_enabled
@ -127,7 +127,7 @@ class HomepageForm(forms.Form):
if self.string_id: if self.string_id:
realm = get_realm_by_string_id(self.string_id) realm = get_realm_by_string_id(self.string_id)
elif not settings.REALMS_HAVE_SUBDOMAINS: elif not settings.REALMS_HAVE_SUBDOMAINS:
realm = get_realm(resolve_email_to_domain(email)) realm = get_realm_by_email_domain(email)
if realm is None: if realm is None:
if settings.REALMS_HAVE_SUBDOMAINS: if settings.REALMS_HAVE_SUBDOMAINS:

View File

@ -35,7 +35,7 @@ from zerver.models import (
get_realm, get_realm,
get_stream, get_stream,
get_user_profile_by_email, get_user_profile_by_email,
resolve_email_to_domain, get_realm_by_email_domain,
Client, Client,
Message, Message,
Realm, Realm,
@ -339,7 +339,7 @@ class ZulipTestCase(TestCase):
def subscribe_to_stream(self, email, stream_name, realm=None): def subscribe_to_stream(self, email, stream_name, realm=None):
# type: (text_type, text_type, Optional[Realm]) -> None # type: (text_type, text_type, Optional[Realm]) -> None
if realm is None: if realm is None:
realm = get_realm(resolve_email_to_domain(email)) realm = get_realm_by_email_domain(email)
stream = get_stream(stream_name, realm) stream = get_stream(stream_name, realm)
if stream is None: if stream is None:
stream, _ = create_stream_if_needed(realm, stream_name) stream, _ = create_stream_if_needed(realm, stream_name)
@ -462,4 +462,3 @@ class WebhookTestCase(ZulipTestCase):
# type: (Message, Optional[text_type]) -> None # type: (Message, Optional[text_type]) -> None
if expected_message is not None: if expected_message is not None:
self.assertEqual(msg.content, expected_message) self.assertEqual(msg.content, expected_message)

View File

@ -31,7 +31,6 @@ from zerver.models import (
get_realm, get_realm,
get_stream, get_stream,
get_user_profile_by_email, get_user_profile_by_email,
resolve_email_to_domain,
Client, Client,
Message, Message,
Realm, Realm,

View File

@ -319,15 +319,19 @@ def split_email_to_domain(email):
# type: (text_type) -> text_type # type: (text_type) -> text_type
return email.split("@")[-1].lower() return email.split("@")[-1].lower()
# Returns the domain, potentually de-aliased, for the realm class GetRealmByDomainException(Exception):
# that this user's email is in pass
def resolve_email_to_domain(email):
# type: (text_type) -> text_type def get_realm_by_email_domain(email):
domain = split_email_to_domain(email) # type: (text_type) -> Optional[Realm]
alias = alias_for_realm(domain) if settings.REALMS_HAVE_SUBDOMAINS:
if alias is not None: raise GetRealmByDomainException(
domain = alias.realm.domain "Cannot get realm from email domain when settings.REALMS_HAVE_SUBDOMAINS = True")
return domain try:
alias = RealmAlias.objects.select_related('realm').get(domain = split_email_to_domain(email))
return alias.realm
except RealmAlias.DoesNotExist:
return None
# Is a user with the given email address allowed to be in the given realm? # Is a user with the given email address allowed to be in the given realm?
# (This function does not check whether the user has been invited to the realm. # (This function does not check whether the user has been invited to the realm.
@ -340,13 +344,6 @@ def email_allowed_for_realm(email, realm):
domain = split_email_to_domain(email) domain = split_email_to_domain(email)
return RealmAlias.objects.filter(realm = realm, domain = domain).exists() return RealmAlias.objects.filter(realm = realm, domain = domain).exists()
def alias_for_realm(domain):
# type: (text_type) -> Optional[RealmAlias]
try:
return RealmAlias.objects.get(domain=domain)
except RealmAlias.DoesNotExist:
return None
def list_of_domains_for_realm(realm): def list_of_domains_for_realm(realm):
# type: (Realm) -> List[text_type] # type: (Realm) -> List[text_type]
return list(RealmAlias.objects.filter(realm = realm).values_list('domain', flat=True)) return list(RealmAlias.objects.filter(realm = realm).values_list('domain', flat=True))

View File

@ -21,9 +21,9 @@ from zerver.forms import WRONG_SUBDOMAIN_ERROR
from zerver.models import UserProfile, Recipient, \ from zerver.models import UserProfile, Recipient, \
Realm, RealmAlias, UserActivity, \ Realm, RealmAlias, UserActivity, \
get_user_profile_by_email, get_realm, \ get_user_profile_by_email, get_realm, get_realm_by_email_domain, \
get_client, get_stream, Message, get_unique_open_realm, \ get_client, get_stream, Message, get_unique_open_realm, \
completely_open completely_open, GetRealmByDomainException
from zerver.lib.avatar import get_avatar_url from zerver.lib.avatar import get_avatar_url
from zerver.lib.initial_password import initial_password from zerver.lib.initial_password import initial_password
@ -265,6 +265,16 @@ class RealmTest(ZulipTestCase):
self.assertNotEqual(realm.default_language, invalid_lang) self.assertNotEqual(realm.default_language, invalid_lang)
class RealmAliasTest(ZulipTestCase):
def test_get_realm_by_email_domain(self):
# type: () -> None
self.assertEqual(get_realm_by_email_domain('user@zulip.com').string_id, 'zulip')
self.assertEqual(get_realm_by_email_domain('user@fakedomain.com'), None)
with self.settings(REALMS_HAVE_SUBDOMAINS = True), \
self.assertRaises(GetRealmByDomainException):
get_realm_by_email_domain('user@zulip.com')
class PermissionTest(ZulipTestCase): class PermissionTest(ZulipTestCase):
def test_get_admin_users(self): def test_get_admin_users(self):
# type: () -> None # type: () -> None

View File

@ -20,9 +20,9 @@ from zerver.models import Message, UserProfile, Stream, Subscription, Huddle, \
RealmFilter, \ RealmFilter, \
PreregistrationUser, get_client, UserActivity, \ PreregistrationUser, get_client, UserActivity, \
get_stream, UserPresence, get_recipient, name_changes_disabled, \ get_stream, UserPresence, get_recipient, name_changes_disabled, \
split_email_to_domain, resolve_email_to_domain, email_to_username, get_realm, \ split_email_to_domain, email_to_username, get_realm, \
completely_open, get_unique_open_realm, email_allowed_for_realm, \ completely_open, get_unique_open_realm, email_allowed_for_realm, \
get_realm_by_string_id, list_of_domains_for_realm get_realm_by_string_id, get_realm_by_email_domain, list_of_domains_for_realm
from zerver.lib.actions import do_change_password, do_change_full_name, do_change_is_admin, \ from zerver.lib.actions import do_change_password, do_change_full_name, do_change_is_admin, \
do_activate_user, do_create_user, do_create_realm, set_default_streams, \ do_activate_user, do_create_user, do_create_realm, set_default_streams, \
update_user_presence, do_events_register, \ update_user_presence, do_events_register, \
@ -118,7 +118,7 @@ def accounts_register(request):
elif settings.REALMS_HAVE_SUBDOMAINS: elif settings.REALMS_HAVE_SUBDOMAINS:
realm = get_realm_by_string_id(get_subdomain(request)) realm = get_realm_by_string_id(get_subdomain(request))
else: else:
realm = get_realm(resolve_email_to_domain(email)) realm = get_realm_by_email_domain(email)
if realm and not email_allowed_for_realm(email, realm): if realm and not email_allowed_for_realm(email, realm):
return render_to_response("zerver/closed_realm.html", {"closed_domain_name": realm.name}) return render_to_response("zerver/closed_realm.html", {"closed_domain_name": realm.name})

View File

@ -38,10 +38,10 @@ from zerver.lib.utils import statsd
from zerver.lib.validator import \ from zerver.lib.validator import \
check_list, check_int, check_dict, check_string, check_bool check_list, check_int, check_dict, check_string, check_bool
from zerver.models import Message, UserProfile, Stream, Subscription, \ from zerver.models import Message, UserProfile, Stream, Subscription, \
Realm, Recipient, UserMessage, bulk_get_recipients, get_recipient, \ Realm, RealmAlias, Recipient, UserMessage, bulk_get_recipients, get_recipient, \
get_user_profile_by_email, get_stream, \ get_user_profile_by_email, get_stream, \
parse_usermessage_flags, \ parse_usermessage_flags, \
resolve_email_to_domain, get_realm, get_active_streams, \ split_email_to_domain, get_realm, get_active_streams, \
bulk_get_streams, get_user_profile_by_id bulk_get_streams, get_user_profile_by_id
from sqlalchemy import func from sqlalchemy import func
@ -754,9 +754,10 @@ def same_realm_zephyr_user(user_profile, email):
except ValidationError: except ValidationError:
return False return False
domain = resolve_email_to_domain(email) domain = split_email_to_domain(email)
return user_profile.realm.domain == domain and user_profile.realm.is_zephyr_mirror_realm return user_profile.realm.is_zephyr_mirror_realm and \
RealmAlias.objects.filter(realm=user_profile.realm, domain=domain).exists()
def same_realm_irc_user(user_profile, email): def same_realm_irc_user(user_profile, email):
# type: (UserProfile, text_type) -> bool # type: (UserProfile, text_type) -> bool
@ -768,9 +769,9 @@ def same_realm_irc_user(user_profile, email):
except ValidationError: except ValidationError:
return False return False
domain = resolve_email_to_domain(email) domain = split_email_to_domain(email).replace("irc.", "")
return user_profile.realm.domain == domain.replace("irc.", "") return RealmAlias.objects.filter(realm=user_profile.realm, domain=domain).exists()
def same_realm_jabber_user(user_profile, email): def same_realm_jabber_user(user_profile, email):
# type: (UserProfile, text_type) -> bool # type: (UserProfile, text_type) -> bool
@ -779,11 +780,11 @@ def same_realm_jabber_user(user_profile, email):
except ValidationError: except ValidationError:
return False return False
domain = resolve_email_to_domain(email)
# If your Jabber users have a different email domain than the # If your Jabber users have a different email domain than the
# Zulip users, this is where you would do any translation. # Zulip users, this is where you would do any translation.
return user_profile.realm.domain == domain domain = split_email_to_domain(email)
return RealmAlias.objects.filter(realm=user_profile.realm, domain=domain).exists()
# We do not @require_login for send_message_backend, since it is used # We do not @require_login for send_message_backend, since it is used
# both from the API and the web service. Code calling # both from the API and the web service. Code calling

View File

@ -13,7 +13,7 @@ from zerver.lib.actions import internal_send_message
from zerver.lib.redis_utils import get_redis_client from zerver.lib.redis_utils import get_redis_client
from zerver.lib.response import json_success, json_error, json_response from zerver.lib.response import json_success, json_error, json_response
from zerver.lib.validator import check_dict from zerver.lib.validator import check_dict
from zerver.models import get_realm, get_user_profile_by_email, resolve_email_to_domain, \ from zerver.models import get_realm, get_user_profile_by_email, get_realm_by_email_domain, \
UserProfile, Realm UserProfile, Realm
from .error_notify import notify_server_error, notify_browser_error from .error_notify import notify_server_error, notify_browser_error
@ -106,7 +106,7 @@ def realm_for_email(email):
except UserProfile.DoesNotExist: except UserProfile.DoesNotExist:
pass pass
return get_realm(resolve_email_to_domain(email)) return get_realm_by_email_domain(email)
# Requests made to this endpoint are UNAUTHENTICATED # Requests made to this endpoint are UNAUTHENTICATED
@csrf_exempt @csrf_exempt

View File

@ -14,7 +14,7 @@ from zerver.lib.actions import do_create_user
from zerver.models import UserProfile, Realm, get_user_profile_by_id, \ from zerver.models import UserProfile, Realm, get_user_profile_by_id, \
get_user_profile_by_email, remote_user_to_email, email_to_username, \ get_user_profile_by_email, remote_user_to_email, email_to_username, \
resolve_email_to_domain, get_realm get_realm, get_realm_by_email_domain
from apiclient.sample_tools import client as googleapiclient from apiclient.sample_tools import client as googleapiclient
from oauth2client.crypt import AppIdentityError from oauth2client.crypt import AppIdentityError
@ -335,8 +335,7 @@ class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase):
raise ZulipLDAPException("LDAP Authentication is not enabled") raise ZulipLDAPException("LDAP Authentication is not enabled")
return user_profile, False return user_profile, False
except UserProfile.DoesNotExist: except UserProfile.DoesNotExist:
domain = resolve_email_to_domain(username) realm = get_realm_by_email_domain(username)
realm = get_realm(domain)
# No need to check for an inactive user since they don't exist yet # No need to check for an inactive user since they don't exist yet
if realm.deactivated: if realm.deactivated:
raise ZulipLDAPException("Realm has been deactivated") raise ZulipLDAPException("Realm has been deactivated")