From 40695699d5f609673c025a2f8960a9662254e983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Sat, 7 Apr 2018 09:24:51 +0200 Subject: [PATCH] api: use dedicated django views for session-less APIs (#23023) --- wcs/api.py | 92 +++++++++++++++++++++++++---------------------------- wcs/urls.py | 5 +++ 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/wcs/api.py b/wcs/api.py index b3b82c99..d5d2b8fa 100644 --- a/wcs/api.py +++ b/wcs/api.py @@ -22,6 +22,8 @@ import sys from quixote import get_request, get_publisher, get_response from quixote.directory import Directory +from django.http import HttpResponse, HttpResponseBadRequest + from qommon import _ from qommon import misc from qommon.evalutils import make_datetime @@ -667,10 +669,7 @@ class ApiTrackingCodeDirectory(Directory): class ApiDirectory(Directory): - _q_exports = ['forms', 'roles', ('reverse-geocoding', 'reverse_geocoding'), - 'formdefs', 'categories', 'user', 'users', 'code', - ('validate-expression', 'validate_expression'), - ('validate-condition', 'validate_condition')] + _q_exports = ['forms', 'roles', 'formdefs', 'categories', 'user', 'users', 'code'] forms = ApiFormsDirectory() formdefs = ApiFormdefsDirectory() @@ -679,22 +678,6 @@ class ApiDirectory(Directory): users = ApiUsersDirectory() code = ApiTrackingCodeDirectory() - def reverse_geocoding(self): - get_response().set_content_type('application/json') - try: - lat = get_request().form['lat'] - lon = get_request().form['lon'] - except KeyError: - raise QueryError - url = get_publisher().get_reverse_geocoding_service_url() - if '?' in url: - url += '&' - else: - url += '?' - url += 'format=json&addressdetails=1&lat=%s&lon=%s' % (lat, lon) - url += '&accept-language=%s' % (get_publisher().get_site_language() or 'en') - return misc.urlopen(url).read() - def roles(self): get_response().set_content_type('application/json') if not (is_url_signed() or ( @@ -707,34 +690,47 @@ class ApiDirectory(Directory): get_response().set_content_type('application/json') return json.dumps({'err': 0, 'data': list_roles}) - def validate_expression(self): - get_response().set_content_type('application/json') - expression = get_request().form.get('expression') - hint = {'klass': None, 'msg': ''} - try: - ComputedExpressionWidget.validate(expression) - except ValidationError as e: - hint['klass'] = 'error' - hint['msg'] = str(e) - else: - if expression and re.match(r'^=.*\[[a-zA-Z_]\w*\]', expression): - hint['klass'] = 'warning' - hint['msg'] = _('Make sure you want a Python expression, not a simple template string.') - return json.dumps(hint) - - def validate_condition(self): - get_response().set_content_type('application/json') - condition = {} - condition['type'] = get_request().form.get('type') or '' - condition['value'] = get_request().form.get('value_' + condition['type']) - hint = {'klass': None, 'msg': ''} - try: - Condition(condition).validate() - except ValidationError as e: - hint['klass'] = 'error' - hint['msg'] = str(e) - return json.dumps(hint) - def _q_traverse(self, path): get_request().is_json_marker = True return super(ApiDirectory, self)._q_traverse(path) + + +def reverse_geocoding(request, *args, **kwargs): + if not ('lat' in request.GET and 'lon' in request.GET): + return HttpResponseBadRequest() + lat = request.GET['lat'] + lon = request.GET['lon'] + url = get_publisher().get_reverse_geocoding_service_url() + if '?' in url: + url += '&' + else: + url += '?' + url += 'format=json&addressdetails=1&lat=%s&lon=%s' % (lat, lon) + url += '&accept-language=%s' % (get_publisher().get_site_language() or 'en') + return HttpResponse(misc.urlopen(url).read(), content_type='application/json') + +def validate_expression(request, *args, **kwargs): + expression = request.GET.get('expression') + hint = {'klass': None, 'msg': ''} + try: + ComputedExpressionWidget.validate(expression) + except ValidationError as e: + hint['klass'] = 'error' + hint['msg'] = str(e) + else: + if expression and re.match(r'^=.*\[[a-zA-Z_]\w*\]', expression): + hint['klass'] = 'warning' + hint['msg'] = _('Make sure you want a Python expression, not a simple template string.') + return HttpResponse(json.dumps(hint), content_type='application/json') + +def validate_condition(request, *args, **kwargs): + condition = {} + condition['type'] = request.GET.get('type') or '' + condition['value'] = request.GET.get('value_' + condition['type']) or '' + hint = {'klass': None, 'msg': ''} + try: + Condition(condition).validate() + except ValidationError as e: + hint['klass'] = 'error' + hint['msg'] = str(e) + return HttpResponse(json.dumps(hint), content_type='application/json') diff --git a/wcs/urls.py b/wcs/urls.py index 0f162bd8..594b26b6 100644 --- a/wcs/urls.py +++ b/wcs/urls.py @@ -19,11 +19,16 @@ from django.conf.urls import url from . import compat from . import views +from . import api urlpatterns = [ url(r'^$', views.home, name='home'), url(r'^backoffice/', views.backoffice), + url(r'^api/validate-condition$', api.validate_condition, name='api-validate-condition'), + url(r'^api/validate-expression$', api.validate_expression, name='api-validate-expression'), + url(r'^api/reverse-geocoding$', api.reverse_geocoding, name='api-reverse-geocoding'), + # provide django.contrib.auth view names for compatibility with # templates created for classic django applications. url(r'^login/$', compat.quixote, name='auth_login'), -- 2.17.0