mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-03 21:43:21 +00:00 
			
		
		
		
	If the `deactivated_redirect` belongs to the same domain as `EXTERNAL_HOST`, automatically redirect, otherwise just point user to the new URL.
		
			
				
	
	
		
			96 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import re
 | 
						|
from urllib.parse import urlsplit
 | 
						|
 | 
						|
from django.conf import settings
 | 
						|
from django.http import HttpRequest
 | 
						|
 | 
						|
from zerver.lib.upload import get_public_upload_root_url
 | 
						|
from zerver.models import Realm, UserProfile
 | 
						|
 | 
						|
 | 
						|
def get_subdomain(request: HttpRequest) -> str:
 | 
						|
    # The HTTP spec allows, but doesn't require, a client to omit the
 | 
						|
    # port in the `Host` header if it's "the default port for the
 | 
						|
    # service requested", i.e. typically either 443 or 80; and
 | 
						|
    # whatever Django gets there, or from proxies reporting that via
 | 
						|
    # X-Forwarded-Host, it passes right through the same way.  So our
 | 
						|
    # logic is a bit complicated to allow for that variation.
 | 
						|
    #
 | 
						|
    # For both EXTERNAL_HOST and REALM_HOSTS, we take a missing port
 | 
						|
    # to mean that any port should be accepted in Host.  It's not
 | 
						|
    # totally clear that's the right behavior, but it keeps
 | 
						|
    # compatibility with older versions of Zulip, so that's a start.
 | 
						|
 | 
						|
    host = request.get_host().lower()
 | 
						|
    subdomain = get_subdomain_from_hostname(host)
 | 
						|
    assert subdomain is not None
 | 
						|
    return subdomain
 | 
						|
 | 
						|
 | 
						|
def get_subdomain_from_hostname(
 | 
						|
    host: str, default_subdomain: str | None = Realm.SUBDOMAIN_FOR_ROOT_DOMAIN
 | 
						|
) -> str | None:
 | 
						|
    # Set `default_subdomain` as None to check if a valid subdomain was found.
 | 
						|
    m = re.search(rf"\.{settings.EXTERNAL_HOST}(:\d+)?$", host)
 | 
						|
    if m:
 | 
						|
        subdomain = host[: m.start()]
 | 
						|
        if subdomain in settings.ROOT_SUBDOMAIN_ALIASES:
 | 
						|
            return default_subdomain
 | 
						|
        return subdomain
 | 
						|
 | 
						|
    for subdomain, realm_host in settings.REALM_HOSTS.items():
 | 
						|
        if re.search(rf"^{realm_host}(:\d+)?$", host):
 | 
						|
            return subdomain
 | 
						|
 | 
						|
    return default_subdomain
 | 
						|
 | 
						|
 | 
						|
def is_subdomain_root_or_alias(request: HttpRequest) -> bool:
 | 
						|
    return get_subdomain(request) == Realm.SUBDOMAIN_FOR_ROOT_DOMAIN
 | 
						|
 | 
						|
 | 
						|
def user_matches_subdomain(realm_subdomain: str, user_profile: UserProfile) -> bool:
 | 
						|
    return user_profile.realm.subdomain == realm_subdomain
 | 
						|
 | 
						|
 | 
						|
def is_root_domain_available() -> bool:
 | 
						|
    if settings.ROOT_DOMAIN_LANDING_PAGE:
 | 
						|
        return False
 | 
						|
    return not Realm.objects.filter(string_id=Realm.SUBDOMAIN_FOR_ROOT_DOMAIN).exists()
 | 
						|
 | 
						|
 | 
						|
def is_static_or_current_realm_url(url: str, realm: Realm | None) -> bool:
 | 
						|
    assert settings.STATIC_URL is not None
 | 
						|
    split_url = urlsplit(url)
 | 
						|
    split_static_url = urlsplit(settings.STATIC_URL)
 | 
						|
 | 
						|
    # The netloc check here is important to correctness if STATIC_URL
 | 
						|
    # does not contain a `/`; see the tests for why.
 | 
						|
    if split_url.netloc == split_static_url.netloc and url.startswith(settings.STATIC_URL):
 | 
						|
        return True
 | 
						|
 | 
						|
    # HTTPS access to this Zulip organization's domain; our existing
 | 
						|
    # HTTPS protects this request, and there's no privacy benefit to
 | 
						|
    # using camo in front of the Zulip server itself.
 | 
						|
    if (
 | 
						|
        realm is not None
 | 
						|
        and split_url.netloc == realm.host
 | 
						|
        and f"{split_url.scheme}://" == settings.EXTERNAL_URI_SCHEME
 | 
						|
    ):
 | 
						|
        return True
 | 
						|
 | 
						|
    # Relative URLs will be processed by the browser the same way as the above.
 | 
						|
    if split_url.netloc == "" and split_url.scheme == "":
 | 
						|
        return True
 | 
						|
 | 
						|
    # S3 storage we control, if used, is also static and thus exempt
 | 
						|
    if settings.LOCAL_UPLOADS_DIR is None:
 | 
						|
        # The startswith check is correct here because the public
 | 
						|
        # upload base URL is guaranteed to end with /.
 | 
						|
        public_upload_root_url = get_public_upload_root_url()
 | 
						|
        assert public_upload_root_url.endswith("/")
 | 
						|
        if url.startswith(public_upload_root_url):
 | 
						|
            return True
 | 
						|
 | 
						|
    return False
 |