mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	Split off the Tornado code into a separate process
(imported from commit 95dbd0f438cdba06d6e6c6c539a2a3d49c577cfd)
This commit is contained in:
		@@ -84,6 +84,13 @@ if deployed:
 | 
			
		||||
    SESSION_COOKIE_SECURE = True
 | 
			
		||||
    CSRF_COOKIE_SECURE    = True
 | 
			
		||||
 | 
			
		||||
# A shared secret, used to authenticate different parts of the app to each other.
 | 
			
		||||
# FIXME: store this password more securely
 | 
			
		||||
SHARED_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
 | 
			
		||||
 | 
			
		||||
# URL where Django code posts to the Tornado code to notify of new messages
 | 
			
		||||
NOTIFY_WAITING_CLIENTS_URL = 'http://localhost:9993/notify_waiting_clients'
 | 
			
		||||
 | 
			
		||||
# List of callables that know how to import templates from various sources.
 | 
			
		||||
TEMPLATE_LOADERS = (
 | 
			
		||||
    'django.template.loaders.filesystem.Loader',
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,9 @@ urlpatterns = patterns('',
 | 
			
		||||
    url(r'^static/(?P<path>.*)$', 'django.views.static.serve',
 | 
			
		||||
        {'document_root': os.path.join(settings.SITE_ROOT, '../zephyr/static-access-control')}),
 | 
			
		||||
 | 
			
		||||
    # Used internally for communication between Django and Tornado processes
 | 
			
		||||
    url(r'^notify_waiting_clients$', 'zephyr.views.notify_waiting_clients', name='notify_waiting_clients'),
 | 
			
		||||
 | 
			
		||||
    # Uncomment the admin/doc line below to enable admin documentation:
 | 
			
		||||
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -84,14 +84,11 @@ class Command(BaseCommand):
 | 
			
		||||
            print "Tornado server is running at http://%s:%s/" % (addr, port)
 | 
			
		||||
            print "Quit the server with %s." % quit_command
 | 
			
		||||
 | 
			
		||||
            from tornado.web import FallbackHandler
 | 
			
		||||
            django_app = wsgi.WSGIContainer(WSGIHandler())
 | 
			
		||||
 | 
			
		||||
            try:
 | 
			
		||||
                # Application is an instance of Django's standard wsgi handler.
 | 
			
		||||
                application = web.Application([(r"/json/get_updates", AsyncDjangoHandler),
 | 
			
		||||
                                               (r"/api/v1/get_messages", AsyncDjangoHandler),
 | 
			
		||||
                                               (r".*", FallbackHandler, dict(fallback=django_app)),
 | 
			
		||||
                                               (r"/notify_waiting_clients", AsyncDjangoHandler),
 | 
			
		||||
                                               ], debug=django.conf.settings.DEBUG)
 | 
			
		||||
 | 
			
		||||
                # start tornado web server in single-threaded mode
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ import simplejson
 | 
			
		||||
from django.db import transaction
 | 
			
		||||
from zephyr.lib import bugdown
 | 
			
		||||
from zephyr.lib.avatar import gravatar_hash
 | 
			
		||||
import requests
 | 
			
		||||
 | 
			
		||||
@cache_with_key(lambda self: 'display_recipient_dict:%d' % (self.id))
 | 
			
		||||
def get_display_recipient(recipient):
 | 
			
		||||
@@ -81,6 +82,7 @@ class UserProfile(models.Model):
 | 
			
		||||
    api_key = models.CharField(max_length=32)
 | 
			
		||||
 | 
			
		||||
    # The user receives this message
 | 
			
		||||
    # Called in the Tornado process
 | 
			
		||||
    def receive(self, message):
 | 
			
		||||
        global callback_table
 | 
			
		||||
 | 
			
		||||
@@ -292,8 +294,10 @@ def do_send_message(message, synced_from_mit=False, no_log=False):
 | 
			
		||||
        for user_profile in recipients:
 | 
			
		||||
            UserMessage(user_profile=user_profile, message=message).save()
 | 
			
		||||
 | 
			
		||||
    for recipient in recipients:
 | 
			
		||||
        recipient.receive(message)
 | 
			
		||||
    requests.post(settings.NOTIFY_WAITING_CLIENTS_URL, data=[
 | 
			
		||||
           ('secret',  settings.SHARED_SECRET),
 | 
			
		||||
           ('message', message.id)]
 | 
			
		||||
        + [('user',    user.id) for user in recipients])
 | 
			
		||||
 | 
			
		||||
class Subscription(models.Model):
 | 
			
		||||
    userprofile = models.ForeignKey(UserProfile)
 | 
			
		||||
 
 | 
			
		||||
@@ -446,6 +446,28 @@ def send_message_backend(request, user_profile, sender):
 | 
			
		||||
    return json_success()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@asynchronous
 | 
			
		||||
@csrf_exempt
 | 
			
		||||
@require_post
 | 
			
		||||
def notify_waiting_clients(request, handler):
 | 
			
		||||
    # Check the shared secret.
 | 
			
		||||
    # Also check the originating IP, at least for now.
 | 
			
		||||
    if ((request.META['REMOTE_ADDR'] != '127.0.0.1')
 | 
			
		||||
        or (request.POST.get('secret') != settings.SHARED_SECRET)):
 | 
			
		||||
 | 
			
		||||
        handler.set_status(403)
 | 
			
		||||
        handler.finish('Access denied')
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    # FIXME: better query
 | 
			
		||||
    users   = [UserProfile.objects.get(id=user) for user in request.POST.getlist('user')]
 | 
			
		||||
    message = Message.objects.get(id=request.POST['message'])
 | 
			
		||||
 | 
			
		||||
    for user in users:
 | 
			
		||||
        user.receive(message)
 | 
			
		||||
 | 
			
		||||
    handler.finish()
 | 
			
		||||
 | 
			
		||||
@login_required_api_view
 | 
			
		||||
def api_get_public_streams(request, user_profile):
 | 
			
		||||
    streams = sorted([stream.name for stream in
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user