Create and use @internal_notify_view

Resolves #288.

(imported from commit 982bf5651a34fa66cd81c882ed0351829eaadf86)
This commit is contained in:
Keegan McAllister
2012-11-27 23:37:13 -05:00
parent 1dbd806b6a
commit cb7e726d77
2 changed files with 21 additions and 17 deletions

View File

@@ -4,6 +4,7 @@ from zephyr.models import UserProfile, UserActivity, get_client
from zephyr.lib.response import json_success, json_error from zephyr.lib.response import json_success, json_error
from django.utils.timezone import now from django.utils.timezone import now
from django.db import transaction, IntegrityError from django.db import transaction, IntegrityError
from django.conf import settings
from functools import wraps from functools import wraps
@@ -93,6 +94,23 @@ def authenticated_json_view(view_func):
return view_func(request, request.user.userprofile, *args, **kwargs) return view_func(request, request.user.userprofile, *args, **kwargs)
return _wrapped_view_func 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 # Used in conjunction with @has_request_variables, below
class POST(object): class POST(object):
# NotSpecified is a sentinel value for determining whether a # NotSpecified is a sentinel value for determining whether a

View File

@@ -22,6 +22,7 @@ from django.views.decorators.csrf import csrf_exempt
from zephyr.decorator import asynchronous, require_post, \ from zephyr.decorator import asynchronous, require_post, \
authenticated_api_view, authenticated_json_view, \ authenticated_api_view, authenticated_json_view, \
internal_notify_view, \
has_request_variables, POST has_request_variables, POST
from zephyr.lib.query import last_n from zephyr.lib.query import last_n
from zephyr.lib.avatar import gravatar_hash from zephyr.lib.avatar import gravatar_hash
@@ -680,19 +681,8 @@ def send_message_backend(request, user_profile, client_name,
return json_success() return json_success()
def validate_notify(request): @internal_notify_view
# 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
def notify_new_message(request): 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 # 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 # by a bot to a stream that nobody is subscribed to), just skip
# the message gracefully # the message gracefully
@@ -716,12 +706,8 @@ def notify_new_message(request):
return json_success() return json_success()
@csrf_exempt @internal_notify_view
@require_post
def notify_pointer_update(request): def notify_pointer_update(request):
if not validate_notify(request):
return json_error("Access denied", status=403)
# FIXME: better query # FIXME: better query
user_profile = UserProfile.objects.get(id=request.POST['user']) user_profile = UserProfile.objects.get(id=request.POST['user'])
new_pointer = int(request.POST['new_pointer']) new_pointer = int(request.POST['new_pointer'])