Files
zulip/zerver/views/integrations.py
hackerkid ea39fb2556 Add option for hosting each realm on its own subdomain.
This adds support for running a Zulip production server with each
realm on its own unique subdomain, e.g. https://realm_name.example.com.

This patch includes a ton of important features:
* Configuring the Zulip sesion middleware to issue cookier correctly
  for the subdomains case.
* Throwing an error if the user tries to visit an invalid subdomain.
* Runs a portion of the Casper tests with REALMS_HAVE_SUBDOMAINS
  enabled to test the subdomain signup process.
* Updating our integrations documentation to refer to the current subdomain.
* Enforces that users can only login to the subdomain of their realm
  (but does not restrict the API; that will be tightened in a future commit).

Note that toggling settings.REALMS_HAVE_SUBDOMAINS on a live server is
not supported without manual intervention (the main problem will be
adding "subdomain" values for all the existing realms).

[substantially modified by tabbott as part of merging]
2016-09-27 23:24:14 -07:00

100 lines
3.9 KiB
Python

from __future__ import absolute_import
from typing import Optional, Any, Dict
from collections import OrderedDict
from django.views.generic import TemplateView
from django.conf import settings
from django.http import HttpRequest, HttpResponse
import ujson
from zerver.lib import bugdown
from zerver.lib.integrations import INTEGRATIONS
from zerver.lib.utils import get_subdomain
from zproject.jinja2 import render_to_response
def add_api_uri_context(context, request):
# type: (Dict[str, Any], HttpRequest) -> None
if settings.REALMS_HAVE_SUBDOMAINS:
subdomain = get_subdomain(request)
if subdomain:
display_subdomain = subdomain
html_settings_links = True
else:
display_subdomain = 'yourZulipDomain'
html_settings_links = False
external_api_path_subdomain = '%s.%s' % (display_subdomain,
settings.EXTERNAL_API_PATH)
else:
external_api_path_subdomain = settings.EXTERNAL_API_PATH
html_settings_links = True
external_api_uri_subdomain = '%s%s' % (settings.EXTERNAL_URI_SCHEME,
external_api_path_subdomain)
context['external_api_path_subdomain'] = external_api_path_subdomain
context['external_api_uri_subdomain'] = external_api_uri_subdomain
context["html_settings_links"] = html_settings_links
class ApiURLView(TemplateView):
def get_context_data(self, **kwargs):
# type: (Optional[Dict[str, Any]]) -> Dict[str, str]
context = super(ApiURLView, self).get_context_data(**kwargs)
add_api_uri_context(context, self.request)
return context
class APIView(ApiURLView):
template_name = 'zerver/api.html'
class IntegrationView(ApiURLView):
template_name = 'zerver/integrations.html'
def get_context_data(self, **kwargs):
# type: (Optional[Dict[str, Any]]) -> Dict[str, Any]
context = super(IntegrationView, self).get_context_data(**kwargs) # type: Dict[str, Any]
alphabetical_sorted_integration = OrderedDict(sorted(INTEGRATIONS.items()))
context['integrations_dict'] = alphabetical_sorted_integration
if context["html_settings_links"]:
settings_html = '<a href="../#settings">Zulip settings page</a>'
subscriptions_html = '<a target="_blank" href="../#subscriptions">subscriptions page</a>'
else:
settings_html = 'Zulip settings page'
subscriptions_html = 'subscriptions page'
context['settings_html'] = settings_html
context['subscriptions_html'] = subscriptions_html
return context
def api_endpoint_docs(request):
# type: (HttpRequest) -> HttpResponse
context = {} # type: Dict[str, Any]
add_api_uri_context(context, request)
raw_calls = open('templates/zerver/api_content.json', 'r').read()
calls = ujson.loads(raw_calls)
langs = set()
for call in calls:
call["endpoint"] = "%s/v1/%s" % (context["external_api_uri_subdomain"],
call["endpoint"])
call["example_request"]["curl"] = call["example_request"]["curl"].replace("https://api.zulip.com",
context["external_api_uri_subdomain"])
response = call['example_response']
if '\n' not in response:
# For 1-line responses, pretty-print them
extended_response = response.replace(", ", ",\n ")
else:
extended_response = response
call['rendered_response'] = bugdown.convert("~~~ .py\n" + extended_response + "\n~~~\n", "default")
for example_type in ('request', 'response'):
for lang in call.get('example_' + example_type, []):
langs.add(lang)
return render_to_response(
'zerver/api_endpoints.html', {
'content': calls,
'langs': langs,
},
request=request)