diff --git a/corporate/urls.py b/corporate/urls.py index 983fee99fc523..73e2c5e351025 100644 --- a/corporate/urls.py +++ b/corporate/urls.py @@ -5,9 +5,6 @@ # Zephyr/MIT url(r'^zephyr/$', TemplateView.as_view(template_name='corporate/zephyr.html')), url(r'^zephyr-mirror/$', TemplateView.as_view(template_name='corporate/zephyr-mirror.html')), - - # Privacy policy - url(r'^privacy/$', TemplateView.as_view(template_name='corporate/privacy.html')), ] urlpatterns = i18n_urlpatterns diff --git a/docs/prod-customize.md b/docs/prod-customize.md index e19f8f68f17a7..24dcc2f7da721 100644 --- a/docs/prod-customize.md +++ b/docs/prod-customize.md @@ -1,12 +1,13 @@ # Customize Zulip Once you've got Zulip setup, you'll likely want to configure it the -way you like. There are four big things to focus on: +way you like. There are several things to focus on: 1. [Integrations](#integrations) 2. [Streams and Topics](#streams-and-topics) 3. [Notification settings](#notification-settings) 4. [Mobile and desktop apps](#mobile-and-desktop-apps) +5. [Terms of service and Privacy policy](#terms-of-service-and-privacy-policy) Lastly, read about Zulip's other [great features](#all-other-features), and then [enjoy your Zulip installation](#enjoy-your-zulip-installation)! @@ -70,6 +71,16 @@ over which messages trigger desktop notifications; you can configure these extensively in the `/#settings` page (get there from the gear menu). +## Terms of service and Privacy policy + +Zulip allows you to configure your server's Terms of Service and +Privacy Policy pages (`/terms` and `/privacy`, respectively). You can +use the `TERMS_OF_SERVICE` and `PRIVACY_POLICY` settings to configure +the path to your server's policies. The syntax is Markdown (with +support for included HTML). A good approach is to use paths like +`/etc/zulip/terms.md`, so that it's easy to back up your policy +configuration along with your other Zulip server configuration. + ## Mobile and desktop apps Currently, the Zulip Desktop app diff --git a/templates/zerver/portico.html b/templates/zerver/portico.html index a4c5305784edc..9565a6696c5e6 100644 --- a/templates/zerver/portico.html +++ b/templates/zerver/portico.html @@ -67,19 +67,12 @@ {% if about_link_disabled %} {% else %}
  • {{ _('About') }}
  • +
  • ·
  • {% endif %} - {% if terms_of_service %} - {% if about_link_disabled %} - {% else %} -
  • ·
  • - {% endif %} - -
  • {{ _('Legal') }}
  • -
  • ·
  • -
  • {{ _('Privacy') }}
  • - {% endif %} - +
  • {{ _('Legal') }}
  • +
  • ·
  • +
  • {{ _('Privacy') }}
  • ·
  • {{ _('Features') }}
  • ·
  • diff --git a/templates/zerver/privacy.html b/templates/zerver/privacy.html new file mode 100644 index 0000000000000..92876c29e5e59 --- /dev/null +++ b/templates/zerver/privacy.html @@ -0,0 +1,22 @@ +{% extends "zerver/portico.html" %} + +{# Privacy policy. #} + +{% block portico_content %} + +
    +
    + + {% if privacy_policy %} + {{ privacy_policy|render_markdown_path }} + {% else %} + {% trans %} + This installation of Zulip does not have a configured privacy policy. + Contact this server's administrator + if you have any questions. + {% endtrans %} + {% endif %} +
    +
    + +{% endblock %} diff --git a/templates/zerver/terms.html b/templates/zerver/terms.html index 03e18e9e6f637..3d2a0ea126163 100644 --- a/templates/zerver/terms.html +++ b/templates/zerver/terms.html @@ -6,9 +6,14 @@
    - {% if terms_of_service %} - {{ terms_of_service|render_markdown_path }} + {{ terms_of_service|render_markdown_path }} + {% else %} + {% trans %} + This installation of Zulip does not have a configured terms of service. + Contact this server's administrator + if you have any questions. + {% endtrans %} {% endif %}
    diff --git a/zerver/context_processors.py b/zerver/context_processors.py index 0fb498e34ddae..092cf64b71223 100644 --- a/zerver/context_processors.py +++ b/zerver/context_processors.py @@ -43,6 +43,7 @@ def add_settings(request): 'show_oss_announcement': settings.SHOW_OSS_ANNOUNCEMENT, 'zulip_admin': settings.ZULIP_ADMINISTRATOR, 'terms_of_service': settings.TERMS_OF_SERVICE, + 'privacy_policy': settings.PRIVACY_POLICY, 'login_url': settings.HOME_NOT_LOGGED_IN, 'only_sso': settings.ONLY_SSO, 'external_api_path': settings.EXTERNAL_API_PATH, diff --git a/zerver/tests/test_templates.py b/zerver/tests/test_templates.py index a066f43306448..af62c40c53c9c 100644 --- a/zerver/tests/test_templates.py +++ b/zerver/tests/test_templates.py @@ -115,7 +115,9 @@ def test_templates(self): integrations_regexp = re.compile('zerver/integrations/.*.html') - skip = covered + defer + logged_out + logged_in + unusual + ['tests/test_markdown.html', 'zerver/terms.html'] + skip = covered + defer + logged_out + logged_in + unusual + ['tests/test_markdown.html', + 'zerver/terms.html', + 'zerver/privacy.html'] templates = [t for t in get_all_templates() if not (t in skip or integrations_regexp.match(t))] self.render_templates(templates, self.get_context()) @@ -211,3 +213,27 @@ def test_custom_tos_template(self): self.assert_in_success_response([u"Thanks for using our products and services (\"Services\"). ", u"By using our Services, you are agreeing to these terms"], response) + + def test_custom_terms_of_service_template(self): + # type: () -> None + not_configured_message = 'This Zulip server does not have a configured ' \ + 'terms of service' + with self.settings(TERMS_OF_SERVICE=None): + response = self.client_get('/terms/') + self.assert_in_success_response([not_configured_message], response) + with self.settings(TERMS_OF_SERVICE='zerver/tests/markdown/test_markdown.md'): + response = self.client_get('/terms/') + self.assert_in_success_response(['This is some bold text.'], response) + self.assert_not_in_success_response([not_configured_message], response) + + def test_custom_privacy_policy_template(self): + # type: () -> None + not_configured_message = 'This Zulip server does not have a configured ' \ + 'privacy policy' + with self.settings(PRIVACY_POLICY=None): + response = self.client_get('/privacy/') + self.assert_in_success_response([not_configured_message], response) + with self.settings(PRIVACY_POLICY='zerver/tests/markdown/test_markdown.md'): + response = self.client_get('/privacy/') + self.assert_in_success_response(['This is some bold text.'], response) + self.assert_not_in_success_response([not_configured_message], response) diff --git a/zproject/dev_settings.py b/zproject/dev_settings.py index 32537cefbebe7..576762e250794 100644 --- a/zproject/dev_settings.py +++ b/zproject/dev_settings.py @@ -37,7 +37,6 @@ # Disable Camo in development CAMO_URI = '' OPEN_REALM_CREATION = True -TERMS_OF_SERVICE = 'zproject/terms.md.template' SAVE_FRONTEND_STACKTRACES = True EVENT_LOGS_ENABLED = True diff --git a/zproject/settings.py b/zproject/settings.py index 5bab86d42ad83..f357c3485032d 100644 --- a/zproject/settings.py +++ b/zproject/settings.py @@ -197,6 +197,7 @@ def get_secret(key): }, 'REALM_CREATION_LINK_VALIDITY_DAYS': 7, 'TERMS_OF_SERVICE': None, + 'PRIVACY_POLICY': None, 'TOS_VERSION': None, 'SYSTEM_ONLY_REALMS': {"zulip"}, 'FIRST_TIME_TOS_TEMPLATE': None, diff --git a/zproject/urls.py b/zproject/urls.py index e04b08d4f7b4e..e8c69c483a51f 100644 --- a/zproject/urls.py +++ b/zproject/urls.py @@ -144,12 +144,12 @@ url(r'^new-user/$', RedirectView.as_view(url='/hello', permanent=True)), url(r'^features/$', TemplateView.as_view(template_name='zerver/features.html')), url(r'^find_my_team/$', zerver.views.registration.find_my_team, name='zerver.views.registration.find_my_team'), - url(r'^authors/$', zerver.views.users.authors_view, name='zerver.views.users.authors_view') -] + url(r'^authors/$', zerver.views.users.authors_view, name='zerver.views.users.authors_view'), -# If a Terms of Service is supplied, add that route -if settings.TERMS_OF_SERVICE is not None: - i18n_urls += [url(r'^terms/$', TemplateView.as_view(template_name='zerver/terms.html'))] + # Terms of service and privacy pages. + url(r'^terms/$', TemplateView.as_view(template_name='zerver/terms.html'), name='terms'), + url(r'^privacy/$', TemplateView.as_view(template_name='zerver/privacy.html'), name='privacy'), +] # Make a copy of i18n_urls so that they appear without prefix for english urls = list(i18n_urls)