mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	The naming `uri` is deprecated while `url` should be used in order to satisfy URL standards. For this reason, four endpoints are affected: * The response content of three endpoints `/server_settings`, `/register` and `/realm` that contain a field `realm_uri` is changed to `realm_url`. * In one of the common fields for all mobile push notifications payloads, `realm_url` field is now added as an alias to `realm_uri`. For backwards compatibility, we keep the field `realm_uri` and add an alias `realm_url`. Co-authored-by: Junyao Chen <junyao.chen@socitydao.org>
		
			
				
	
	
		
			289 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			289 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from typing import Any, Dict, Mapping, Optional
 | 
						|
from urllib.parse import urljoin
 | 
						|
 | 
						|
from django.conf import settings
 | 
						|
from django.http import HttpRequest
 | 
						|
from django.utils.html import escape
 | 
						|
from django.utils.safestring import SafeString
 | 
						|
from django.utils.translation import get_language
 | 
						|
 | 
						|
from version import (
 | 
						|
    LATEST_MAJOR_VERSION,
 | 
						|
    LATEST_RELEASE_ANNOUNCEMENT,
 | 
						|
    LATEST_RELEASE_VERSION,
 | 
						|
    ZULIP_VERSION,
 | 
						|
)
 | 
						|
from zerver.lib.exceptions import InvalidSubdomainError
 | 
						|
from zerver.lib.i18n import get_language_list
 | 
						|
from zerver.lib.realm_description import get_realm_rendered_description, get_realm_text_description
 | 
						|
from zerver.lib.realm_icon import get_realm_icon_url
 | 
						|
from zerver.lib.request import RequestNotes
 | 
						|
from zerver.lib.send_email import FromAddress
 | 
						|
from zerver.lib.subdomains import get_subdomain, is_root_domain_available
 | 
						|
from zerver.models import Realm, UserProfile
 | 
						|
from zerver.models.realms import get_realm
 | 
						|
from zproject.backends import (
 | 
						|
    AUTH_BACKEND_NAME_MAP,
 | 
						|
    auth_enabled_helper,
 | 
						|
    get_external_method_dicts,
 | 
						|
    password_auth_enabled,
 | 
						|
    require_email_format_usernames,
 | 
						|
)
 | 
						|
from zproject.config import get_config
 | 
						|
 | 
						|
DEFAULT_PAGE_PARAMS: Mapping[str, Any] = {
 | 
						|
    "page_type": "default",
 | 
						|
    "development_environment": settings.DEVELOPMENT,
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
def common_context(user: UserProfile) -> Dict[str, Any]:
 | 
						|
    """Common context used for things like outgoing emails that don't
 | 
						|
    have a request.
 | 
						|
    """
 | 
						|
    return {
 | 
						|
        "realm_uri": user.realm.url,
 | 
						|
        "realm_name": user.realm.name,
 | 
						|
        "root_domain_url": settings.ROOT_DOMAIN_URI,
 | 
						|
        "external_url_scheme": settings.EXTERNAL_URI_SCHEME,
 | 
						|
        "external_host": settings.EXTERNAL_HOST,
 | 
						|
        "user_name": user.full_name,
 | 
						|
        "corporate_enabled": settings.CORPORATE_ENABLED,
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
def get_realm_from_request(request: HttpRequest) -> Optional[Realm]:
 | 
						|
    request_notes = RequestNotes.get_notes(request)
 | 
						|
    if request.user.is_authenticated:
 | 
						|
        return request.user.realm
 | 
						|
    if not request_notes.has_fetched_realm:
 | 
						|
        # We cache the realm object from this function on the request data,
 | 
						|
        # so that functions that call get_realm_from_request don't
 | 
						|
        # need to do duplicate queries on the same realm while
 | 
						|
        # processing a single request.
 | 
						|
        subdomain = get_subdomain(request)
 | 
						|
        request_notes = RequestNotes.get_notes(request)
 | 
						|
        try:
 | 
						|
            request_notes.realm = get_realm(subdomain)
 | 
						|
        except Realm.DoesNotExist:
 | 
						|
            request_notes.realm = None
 | 
						|
        request_notes.has_fetched_realm = True
 | 
						|
    return request_notes.realm
 | 
						|
 | 
						|
 | 
						|
def get_valid_realm_from_request(request: HttpRequest) -> Realm:
 | 
						|
    realm = get_realm_from_request(request)
 | 
						|
    if realm is None:
 | 
						|
        raise InvalidSubdomainError
 | 
						|
    return realm
 | 
						|
 | 
						|
 | 
						|
def get_apps_page_url() -> str:
 | 
						|
    if settings.CORPORATE_ENABLED:
 | 
						|
        return "/apps/"
 | 
						|
    return "https://zulip.com/apps/"
 | 
						|
 | 
						|
 | 
						|
def is_isolated_page(request: HttpRequest) -> bool:
 | 
						|
    """Accept a GET param `?nav=no` to render an isolated, navless page."""
 | 
						|
    return request.GET.get("nav") == "no"
 | 
						|
 | 
						|
 | 
						|
def zulip_default_corporate_context(request: HttpRequest) -> Dict[str, Any]:
 | 
						|
    from corporate.lib.decorator import is_self_hosting_management_subdomain
 | 
						|
 | 
						|
    # Check if view function is in corporate app.
 | 
						|
    if request.resolver_match is not None and not request.resolver_match.func.__module__.startswith(
 | 
						|
        "corporate"
 | 
						|
    ):
 | 
						|
        return {
 | 
						|
            "is_self_hosting_management_page": False,
 | 
						|
        }
 | 
						|
 | 
						|
    # Add common context variables that are only used on the corporate site.
 | 
						|
    return {
 | 
						|
        "is_self_hosting_management_page": is_self_hosting_management_subdomain(request),
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
def zulip_default_context(request: HttpRequest) -> Dict[str, Any]:
 | 
						|
    """Context available to all Zulip Jinja2 templates that have a request
 | 
						|
    passed in.  Designed to provide the long list of variables at the
 | 
						|
    bottom of this function in a wide range of situations: logged-in
 | 
						|
    or logged-out, subdomains or not, etc.
 | 
						|
 | 
						|
    The main variable in the below is whether we know what realm the
 | 
						|
    user is trying to interact with.
 | 
						|
    """
 | 
						|
    realm = get_realm_from_request(request)
 | 
						|
 | 
						|
    if realm is None:
 | 
						|
        realm_uri = settings.ROOT_DOMAIN_URI
 | 
						|
        realm_name = None
 | 
						|
        realm_icon = None
 | 
						|
    else:
 | 
						|
        realm_uri = realm.url
 | 
						|
        realm_name = realm.name
 | 
						|
        realm_icon = get_realm_icon_url(realm)
 | 
						|
 | 
						|
    skip_footer = False
 | 
						|
    register_link_disabled = settings.REGISTER_LINK_DISABLED
 | 
						|
    login_link_disabled = settings.LOGIN_LINK_DISABLED
 | 
						|
    find_team_link_disabled = settings.FIND_TEAM_LINK_DISABLED
 | 
						|
    allow_search_engine_indexing = False
 | 
						|
 | 
						|
    if (
 | 
						|
        settings.ROOT_DOMAIN_LANDING_PAGE
 | 
						|
        and get_subdomain(request) == Realm.SUBDOMAIN_FOR_ROOT_DOMAIN
 | 
						|
    ):
 | 
						|
        register_link_disabled = True
 | 
						|
        login_link_disabled = True
 | 
						|
        find_team_link_disabled = False
 | 
						|
        allow_search_engine_indexing = True
 | 
						|
    elif realm is None:
 | 
						|
        register_link_disabled = True
 | 
						|
        login_link_disabled = True
 | 
						|
        find_team_link_disabled = False
 | 
						|
        skip_footer = True
 | 
						|
 | 
						|
    apps_page_web = settings.ROOT_DOMAIN_URI + "/accounts/go/"
 | 
						|
 | 
						|
    if settings.DEVELOPMENT:
 | 
						|
        secrets_path = "zproject/dev-secrets.conf"
 | 
						|
        settings_path = "zproject/dev_settings.py"
 | 
						|
        settings_comments_path = "zproject/prod_settings_template.py"
 | 
						|
    else:
 | 
						|
        secrets_path = "/etc/zulip/zulip-secrets.conf"
 | 
						|
        settings_path = "/etc/zulip/settings.py"
 | 
						|
        settings_comments_path = "/etc/zulip/settings.py"
 | 
						|
 | 
						|
    # Used to remove links to Zulip docs and landing page from footer of self-hosted pages.
 | 
						|
    corporate_enabled = settings.CORPORATE_ENABLED
 | 
						|
 | 
						|
    support_email = FromAddress.SUPPORT
 | 
						|
    support_email_html_tag = SafeString(
 | 
						|
        f'<a href="mailto:{escape(support_email)}">{escape(support_email)}</a>'
 | 
						|
    )
 | 
						|
 | 
						|
    # Sync this with default_params_schema in base_page_params.ts.
 | 
						|
    default_page_params: Dict[str, Any] = {
 | 
						|
        **DEFAULT_PAGE_PARAMS,
 | 
						|
        "server_sentry_dsn": settings.SENTRY_FRONTEND_DSN,
 | 
						|
        "request_language": get_language(),
 | 
						|
    }
 | 
						|
    if settings.SENTRY_FRONTEND_DSN is not None:
 | 
						|
        if realm is not None:
 | 
						|
            default_page_params["realm_sentry_key"] = realm.string_id
 | 
						|
        default_page_params["server_sentry_environment"] = get_config(
 | 
						|
            "machine", "deploy_type", "development"
 | 
						|
        )
 | 
						|
        default_page_params["server_sentry_sample_rate"] = settings.SENTRY_FRONTEND_SAMPLE_RATE
 | 
						|
        default_page_params["server_sentry_trace_rate"] = settings.SENTRY_FRONTEND_TRACE_RATE
 | 
						|
 | 
						|
    context = {
 | 
						|
        "root_domain_landing_page": settings.ROOT_DOMAIN_LANDING_PAGE,
 | 
						|
        "custom_logo_url": settings.CUSTOM_LOGO_URL,
 | 
						|
        "register_link_disabled": register_link_disabled,
 | 
						|
        "login_link_disabled": login_link_disabled,
 | 
						|
        "terms_of_service": settings.TERMS_OF_SERVICE_VERSION is not None,
 | 
						|
        "login_url": settings.HOME_NOT_LOGGED_IN,
 | 
						|
        "only_sso": settings.ONLY_SSO,
 | 
						|
        "external_host": settings.EXTERNAL_HOST,
 | 
						|
        "external_url_scheme": settings.EXTERNAL_URI_SCHEME,
 | 
						|
        "realm_uri": realm_uri,
 | 
						|
        "realm_url": realm_uri,
 | 
						|
        "realm_name": realm_name,
 | 
						|
        "realm_icon": realm_icon,
 | 
						|
        "root_domain_url": settings.ROOT_DOMAIN_URI,
 | 
						|
        "apps_page_url": get_apps_page_url(),
 | 
						|
        "apps_page_web": apps_page_web,
 | 
						|
        "open_realm_creation": settings.OPEN_REALM_CREATION,
 | 
						|
        "development_environment": settings.DEVELOPMENT,
 | 
						|
        "support_email": support_email,
 | 
						|
        "support_email_html_tag": support_email_html_tag,
 | 
						|
        "find_team_link_disabled": find_team_link_disabled,
 | 
						|
        "password_min_length": settings.PASSWORD_MIN_LENGTH,
 | 
						|
        "password_min_guesses": settings.PASSWORD_MIN_GUESSES,
 | 
						|
        "zulip_version": ZULIP_VERSION,
 | 
						|
        "user_is_authenticated": request.user.is_authenticated,
 | 
						|
        "settings_path": settings_path,
 | 
						|
        "secrets_path": secrets_path,
 | 
						|
        "settings_comments_path": settings_comments_path,
 | 
						|
        "platform": RequestNotes.get_notes(request).client_name,
 | 
						|
        "allow_search_engine_indexing": allow_search_engine_indexing,
 | 
						|
        "landing_page_navbar_message": settings.LANDING_PAGE_NAVBAR_MESSAGE,
 | 
						|
        "is_isolated_page": is_isolated_page(request),
 | 
						|
        "skip_footer": skip_footer,
 | 
						|
        "default_page_params": default_page_params,
 | 
						|
        "corporate_enabled": corporate_enabled,
 | 
						|
    }
 | 
						|
 | 
						|
    context["PAGE_METADATA_URL"] = f"{realm_uri}{request.path}"
 | 
						|
    if realm is not None and realm.icon_source == realm.ICON_UPLOADED:
 | 
						|
        context["PAGE_METADATA_IMAGE"] = urljoin(realm_uri, realm_icon)
 | 
						|
 | 
						|
    return context
 | 
						|
 | 
						|
 | 
						|
def login_context(request: HttpRequest) -> Dict[str, Any]:
 | 
						|
    realm = get_realm_from_request(request)
 | 
						|
 | 
						|
    if realm is None:
 | 
						|
        realm_description = None
 | 
						|
        realm_invite_required = False
 | 
						|
        realm_web_public_access_enabled = False
 | 
						|
    else:
 | 
						|
        realm_description = get_realm_rendered_description(realm)
 | 
						|
        realm_invite_required = realm.invite_required
 | 
						|
        # We offer web-public access only if the realm has actual web
 | 
						|
        # public streams configured, in addition to having it enabled.
 | 
						|
        realm_web_public_access_enabled = realm.allow_web_public_streams_access()
 | 
						|
 | 
						|
    context: Dict[str, Any] = {
 | 
						|
        "realm_invite_required": realm_invite_required,
 | 
						|
        "realm_description": realm_description,
 | 
						|
        "require_email_format_usernames": require_email_format_usernames(realm),
 | 
						|
        "password_auth_enabled": password_auth_enabled(realm),
 | 
						|
        "two_factor_authentication_enabled": settings.TWO_FACTOR_AUTHENTICATION_ENABLED,
 | 
						|
        "realm_web_public_access_enabled": realm_web_public_access_enabled,
 | 
						|
    }
 | 
						|
 | 
						|
    if realm is not None and realm.description:
 | 
						|
        context["PAGE_TITLE"] = realm.name
 | 
						|
        context["PAGE_DESCRIPTION"] = get_realm_text_description(realm)
 | 
						|
 | 
						|
    # Add the keys for our standard authentication backends.
 | 
						|
    no_auth_enabled = True
 | 
						|
    for auth_backend_name in AUTH_BACKEND_NAME_MAP:
 | 
						|
        name_lower = auth_backend_name.lower()
 | 
						|
        key = f"{name_lower}_auth_enabled"
 | 
						|
        is_enabled = auth_enabled_helper([auth_backend_name], realm)
 | 
						|
        context[key] = is_enabled
 | 
						|
        if is_enabled:
 | 
						|
            no_auth_enabled = False
 | 
						|
 | 
						|
    context["external_authentication_methods"] = get_external_method_dicts(realm)
 | 
						|
    context["no_auth_enabled"] = no_auth_enabled
 | 
						|
 | 
						|
    return context
 | 
						|
 | 
						|
 | 
						|
def latest_info_context() -> Dict[str, str]:
 | 
						|
    context = {
 | 
						|
        "latest_release_version": LATEST_RELEASE_VERSION,
 | 
						|
        "latest_major_version": LATEST_MAJOR_VERSION,
 | 
						|
        "latest_release_announcement": LATEST_RELEASE_ANNOUNCEMENT,
 | 
						|
    }
 | 
						|
    return context
 | 
						|
 | 
						|
 | 
						|
def get_realm_create_form_context() -> Dict[str, Any]:
 | 
						|
    context = {
 | 
						|
        "language_list": get_language_list(),
 | 
						|
        "MAX_REALM_NAME_LENGTH": str(Realm.MAX_REALM_NAME_LENGTH),
 | 
						|
        "MAX_REALM_SUBDOMAIN_LENGTH": str(Realm.MAX_REALM_SUBDOMAIN_LENGTH),
 | 
						|
        "root_domain_available": is_root_domain_available(),
 | 
						|
        "sorted_realm_types": sorted(Realm.ORG_TYPES.values(), key=lambda d: d["display_order"]),
 | 
						|
    }
 | 
						|
    return context
 |