Add TERMS_OF_SERVICE setting.

This new setting allows the server administrator to add a custom
Terms of Service page by supplying the path to a markdown file.

Also adds a test.
This commit is contained in:
acrefoot 2016-05-11 10:01:53 -07:00 committed by Tim Abbott
parent 700e803840
commit e568dbc76f
13 changed files with 86 additions and 9 deletions

View File

@ -0,0 +1,6 @@
header
{{ markdown_test_file|render_markdown_path }}
footer

View File

@ -53,7 +53,7 @@
<div class="footer-main"> <div class="footer-main">
<ul class="footer-navigation"> <ul class="footer-navigation">
<li><a href="/hello">{{ _('About') }}</a></li> <li><a href="/hello">{{ _('About') }}</a></li>
{% if zulip_com %} {% if zulip_com or terms_of_service %}
<li><span class="little-bullet">·</span></li> <li><span class="little-bullet">·</span></li>
<li><a href="/terms">{{ _('Legal') }}</a></li> <li><a href="/terms">{{ _('Legal') }}</a></li>
{% endif %} {% endif %}

View File

@ -0,0 +1,16 @@
{% extends "zerver/portico.html" %}
{# Terms of service. #}
{% block portico_content %}
<div class="app terms-page">
<div class="app-main terms-page-container">
{% if terms_of_service %}
{{ terms_of_service|render_markdown_path }}
{% endif %}
</div>
</div>
{% endblock %}

View File

@ -17,6 +17,7 @@ def add_settings(request):
'register_link_disabled': settings.REGISTER_LINK_DISABLED, 'register_link_disabled': settings.REGISTER_LINK_DISABLED,
'show_oss_announcement': settings.SHOW_OSS_ANNOUNCEMENT, 'show_oss_announcement': settings.SHOW_OSS_ANNOUNCEMENT,
'zulip_admin': settings.ZULIP_ADMINISTRATOR, 'zulip_admin': settings.ZULIP_ADMINISTRATOR,
'terms_of_service': settings.TERMS_OF_SERVICE,
'login_url': settings.HOME_NOT_LOGGED_IN, 'login_url': settings.HOME_NOT_LOGGED_IN,
'only_sso': settings.ONLY_SSO, 'only_sso': settings.ONLY_SSO,
'external_api_path': settings.EXTERNAL_API_PATH, 'external_api_path': settings.EXTERNAL_API_PATH,

View File

@ -1,4 +1,6 @@
from django.template import Library from django.template import Library
from django.utils.safestring import mark_safe
from django.utils.functional import memoize
register = Library() register = Library()
@ -36,3 +38,19 @@ def display_list(values, display_limit):
display_string += and_n_others(values, display_limit) display_string += and_n_others(values, display_limit)
return display_string return display_string
memoize_cache = {} # type: Dict[str, str]
@register.filter(name='render_markdown_path', is_safe=True)
def render_markdown_path(markdown_file_path):
# type: (str) -> str
"""
Given a path to a markdown file, return the rendered html
"""
import markdown
def path_to_html(path):
markdown_string = open(path).read()
return markdown.markdown(markdown_string, safe_mode='escape')
html = memoize(path_to_html, memoize_cache, 1)(markdown_file_path)
return mark_safe(html)

View File

@ -0,0 +1,6 @@
# Hello!
This is some *bold text*.

View File

@ -5,13 +5,12 @@ from typing import Any, Dict, Iterable
import logging import logging
from django.test import TestCase from django.test import TestCase
from django.template import Template from django.template import Template, Context
from django.template.loader import get_template from django.template.loader import get_template
from zerver.models import get_user_profile_by_email from zerver.models import get_user_profile_by_email
from zerver.lib.test_helpers import get_all_templates from zerver.lib.test_helpers import get_all_templates
class get_form_value(object): class get_form_value(object):
def __init__(self, value): def __init__(self, value):
# type: (Any) -> None # type: (Any) -> None
@ -40,14 +39,15 @@ class TemplateTestCase(TestCase):
# type: () -> None # type: () -> None
# Just add the templates whose context has a conflict with other # Just add the templates whose context has a conflict with other
# templates' context in `exclude`. # templates' context in `defer`.
exclude = ['analytics/activity.html'] defer = ['analytics/activity.html']
templates = [t for t in get_all_templates() if t not in exclude] skip = defer + ['tests/test_markdown.html', 'zerver/terms.html']
templates = [t for t in get_all_templates() if t not in skip]
self.render_templates(templates, self.get_context()) self.render_templates(templates, self.get_context())
# Test the excluded templates with updated context. # Test the deferred templates with updated context.
update = {'data': [('one', 'two')]} update = {'data': [('one', 'two')]}
self.render_templates(exclude, self.get_context(**update)) self.render_templates(defer, self.get_context(**update))
def render_templates(self, templates, context): def render_templates(self, templates, context):
# type: (Iterable[Template], Dict[str, Any]) -> None # type: (Iterable[Template], Dict[str, Any]) -> None
@ -106,3 +106,15 @@ class TemplateTestCase(TestCase):
context.update(kwargs) context.update(kwargs)
return context return context
def test_markdown_in_template(self):
# type: () -> None
template = get_template("tests/test_markdown.html")
context = {
'markdown_test_file': "zerver/tests/markdown/test_markdown.md"
}
content = template.render(context)
content_sans_whitespace = content.replace(" ", "").replace('\n', '')
self.assertEqual(content_sans_whitespace,
'header<h1>Hello!</h1><p>Thisissome<em>boldtext</em>.</p>footer')

View File

@ -21,5 +21,6 @@ EXTRA_INSTALLED_APPS = ["zilencer", "analytics"]
# Disable Camo in development # Disable Camo in development
CAMO_URI = '' CAMO_URI = ''
OPEN_REALM_CREATION = True OPEN_REALM_CREATION = True
TERMS_OF_SERVICE = 'zproject/terms.md.template'
SAVE_FRONTEND_STACKTRACES = True SAVE_FRONTEND_STACKTRACES = True

View File

@ -9,7 +9,7 @@ from django.http import HttpResponse
from jinja2 import Environment from jinja2 import Environment
from .compressors import minified_js from .compressors import minified_js
from zerver.templatetags.app_filters import display_list from zerver.templatetags.app_filters import display_list, render_markdown_path
def render_to_response(*args, **kwargs): def render_to_response(*args, **kwargs):
@ -30,5 +30,6 @@ def environment(**options):
env.filters['slugify'] = slugify env.filters['slugify'] = slugify
env.filters['pluralize'] = pluralize env.filters['pluralize'] = pluralize
env.filters['display_list'] = display_list env.filters['display_list'] = display_list
env.filters['render_markdown_path'] = render_markdown_path
return env return env

View File

@ -183,6 +183,10 @@ ENABLE_GRAVATAR = True
#REMOTE_POSTGRES_HOST = 'dbserver.example.com' #REMOTE_POSTGRES_HOST = 'dbserver.example.com'
#REMOTE_POSTGRES_SSLMODE = 'require' #REMOTE_POSTGRES_SSLMODE = 'require'
# If you want to set custom TOS, set the path to your markdown file, and uncomment
# the following line.
# TERMS_OF_SERVICE = '/etc/zulip/terms.md'
### TWITTER INTEGRATION ### TWITTER INTEGRATION
# Zulip supports showing inline Tweet previews when a tweet is linked # Zulip supports showing inline Tweet previews when a tweet is linked

View File

@ -162,6 +162,7 @@ DEFAULT_SETTINGS = {'TWITTER_CONSUMER_KEY': '',
'EXTRA_INSTALLED_APPS': [], 'EXTRA_INSTALLED_APPS': [],
'DEFAULT_NEW_REALM_STREAMS': ["social", "general", "zulip"], 'DEFAULT_NEW_REALM_STREAMS': ["social", "general", "zulip"],
'REALM_CREATION_LINK_VALIDITY_DAYS': 7, 'REALM_CREATION_LINK_VALIDITY_DAYS': 7,
'TERMS_OF_SERVICE': None,
} }
for setting_name, setting_val in six.iteritems(DEFAULT_SETTINGS): for setting_name, setting_val in six.iteritems(DEFAULT_SETTINGS):

View File

@ -0,0 +1,7 @@
# Zulip TOS
put your terms here
* you can use markdown

View File

@ -105,6 +105,10 @@ i18n_urls = [
url(r'^features/$', TemplateView.as_view(template_name='zerver/features.html')), url(r'^features/$', TemplateView.as_view(template_name='zerver/features.html')),
] ]
# If on zulip.com or if a custom TOS is supplied, add that route
if not settings.ZULIP_COM and settings.TERMS_OF_SERVICE:
i18n_urls += [url(r'^terms/$', TemplateView.as_view(template_name='zerver/terms.html'))]
# Make a copy of i18n_urls so that they appear without prefix for english # Make a copy of i18n_urls so that they appear without prefix for english
urls = list(i18n_urls) urls = list(i18n_urls)