From cb7e726d77161ec43101fa2245df1d1ab8a9cb58 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Tue, 27 Nov 2012 23:37:13 -0500 Subject: [PATCH] Create and use @internal_notify_view Resolves #288. (imported from commit 982bf5651a34fa66cd81c882ed0351829eaadf86) --- zephyr/decorator.py | 18 ++++++++++++++++++ zephyr/views.py | 20 +++----------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/zephyr/decorator.py b/zephyr/decorator.py index c3d8a2ae96..d6b07e9c18 100644 --- a/zephyr/decorator.py +++ b/zephyr/decorator.py @@ -4,6 +4,7 @@ from zephyr.models import UserProfile, UserActivity, get_client from zephyr.lib.response import json_success, json_error from django.utils.timezone import now from django.db import transaction, IntegrityError +from django.conf import settings from functools import wraps @@ -93,6 +94,23 @@ def authenticated_json_view(view_func): return view_func(request, request.user.userprofile, *args, **kwargs) return _wrapped_view_func +# These views are used by the main Django server to notify the Tornado server +# of events. We protect them from the outside world by checking a shared +# secret, and also the originating IP (for now). +def authenticate_notify(request): + return (request.META['REMOTE_ADDR'] in ('127.0.0.1', '::1') + and request.POST.get('secret') == settings.SHARED_SECRET) + +def internal_notify_view(view_func): + @csrf_exempt + @require_post + @wraps(view_func) + def _wrapped_view_func(request, *args, **kwargs): + if not authenticate_notify(request): + return json_error('Access denied', status=403) + return view_func(request, *args, **kwargs) + return _wrapped_view_func + # Used in conjunction with @has_request_variables, below class POST(object): # NotSpecified is a sentinel value for determining whether a diff --git a/zephyr/views.py b/zephyr/views.py index a45fe128c1..7292411de0 100644 --- a/zephyr/views.py +++ b/zephyr/views.py @@ -22,6 +22,7 @@ from django.views.decorators.csrf import csrf_exempt from zephyr.decorator import asynchronous, require_post, \ authenticated_api_view, authenticated_json_view, \ + internal_notify_view, \ has_request_variables, POST from zephyr.lib.query import last_n from zephyr.lib.avatar import gravatar_hash @@ -680,19 +681,8 @@ def send_message_backend(request, user_profile, client_name, return json_success() -def validate_notify(request): - # Check the shared secret. - # Also check the originating IP, at least for now. - return (request.META['REMOTE_ADDR'] in ('127.0.0.1', '::1') - and request.POST.get('secret') == settings.SHARED_SECRET) - - -@csrf_exempt -@require_post +@internal_notify_view def notify_new_message(request): - if not validate_notify(request): - return json_error("Access denied", status=403) - # If a message for some reason has no recipients (e.g. it is sent # by a bot to a stream that nobody is subscribed to), just skip # the message gracefully @@ -716,12 +706,8 @@ def notify_new_message(request): return json_success() -@csrf_exempt -@require_post +@internal_notify_view def notify_pointer_update(request): - if not validate_notify(request): - return json_error("Access denied", status=403) - # FIXME: better query user_profile = UserProfile.objects.get(id=request.POST['user']) new_pointer = int(request.POST['new_pointer'])