diff --git a/apps/sumo/tests/test_views.py b/apps/sumo/tests/test_views.py index 90aab9691..c0e9e921e 100644 --- a/apps/sumo/tests/test_views.py +++ b/apps/sumo/tests/test_views.py @@ -1,3 +1,6 @@ +import json + +import django from django.conf import settings from django.contrib.sites.models import Site from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect @@ -7,6 +10,7 @@ from nose.tools import eq_ from pyquery import PyQuery as pq from test_utils import RequestFactory +from sumo.helpers import urlparams from sumo.middleware import LocaleURLMiddleware from sumo.tests import TestCase from sumo.urlresolvers import reverse @@ -66,3 +70,28 @@ class RobotsTestCase(TestCase): response = self.client.get('/robots.txt') eq_('text/plain', response['content-type']) assert len(response.content) > len('User-agent: *\nDisallow: /') + + +class VersionCheckTests(TestCase): + url = reverse('sumo.version') + + def _is_forbidden(self, url): + res = self.client.get(url) + eq_(403, res.status_code) + eq_('', res.content) + + @mock.patch.object(settings._wrapped, 'VERSION_CHECK_TOKEN', None) + def token_is_none(self): + self._is_forbidden(self.url) + self._is_forbidden(urlparams(self.url, token='foo')) + + @mock.patch.object(settings._wrapped, 'VERSION_CHECK_TOKEN', 'foo') + def token_is_wrong(self): + self._is_forbidden(urlparams(self.url, token='bar')) + + @mock.patch.object(settings._wrapped, 'VERSION_CHECK_TOKEN', 'foo') + def token_is_right(self): + res = self.client.get(urlparams(self.url, token='foo')) + eq_(200, res.status_code) + versions = json.loads(res.content) + eq_('.'.join(map(str, django.VERSION)), versions['django']) diff --git a/apps/sumo/urls.py b/apps/sumo/urls.py index 5c45b5573..8884c7837 100644 --- a/apps/sumo/urls.py +++ b/apps/sumo/urls.py @@ -7,6 +7,7 @@ from sumo import views services_patterns = patterns('', url('^/monitor$', views.monitor, name='sumo.monitor'), + url('^/version$', views.version_check, name='sumo.version'), ) diff --git a/apps/sumo/views.py b/apps/sumo/views.py index 4b84950fc..027392ca7 100644 --- a/apps/sumo/views.py +++ b/apps/sumo/views.py @@ -1,15 +1,18 @@ +import json import logging import os import socket import StringIO from time import time +import django from django.conf import settings from django.contrib.sites.models import Site from django.core.cache import parse_backend_uri from django.http import (HttpResponsePermanentRedirect, HttpResponseRedirect, HttpResponse) from django.views.decorators.cache import never_cache +from django.views.decorators.http import require_GET from celery.messaging import establish_connection from commonware.decorators import xframe_allow @@ -174,6 +177,21 @@ def monitor(request): status=status) +@require_GET +@never_cache +def version_check(request): + mime = 'application/x-json' + token = settings.VERSION_CHECK_TOKEN + if (token is None or not 'token' in request.GET or + token != request.GET['token']): + return HttpResponse(status=403, mimetype=mime) + + versions = { + 'django': '.'.join(map(str, django.VERSION)), + } + return HttpResponse(json.dumps(versions), mimetype=mime) + + # Allows another site to embed the QUnit suite # in an iframe (for CI). @xframe_allow diff --git a/settings.py b/settings.py index e8cf78e20..7c056ee86 100644 --- a/settings.py +++ b/settings.py @@ -643,3 +643,6 @@ MOBILE_COOKIE = 'msumo' # Directory of JavaScript test files for django_qunit to run QUNIT_TEST_DIRECTORY = os.path.join(MEDIA_ROOT, 'js', 'tests') + +# Key to access /services/version. Set to None to disallow. +VERSION_CHECK_TOKEN = None