Skip to content

Commit

Permalink
use django-sendfile for serving local upoads.
Browse files Browse the repository at this point in the history
  • Loading branch information
rahuldeve committed May 23, 2016
1 parent 67199a8 commit 4bfb71f
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 6 deletions.
3 changes: 2 additions & 1 deletion puppet/zulip/files/nginx/sites-available/zulip-enterprise
Expand Up @@ -12,7 +12,8 @@ server {
ssl_certificate /etc/ssl/certs/zulip.combined-chain.crt;
ssl_certificate_key /etc/ssl/private/zulip.key;

location /user_uploads {
location /user_uploads_internal {
internal;
add_header X-Content-Type-Options nosniff;
include /etc/nginx/zulip-include/uploads.types;
alias /home/zulip/uploads/files;
Expand Down
7 changes: 7 additions & 0 deletions zerver/lib/upload.py
Expand Up @@ -227,6 +227,13 @@ def delete_message_image_local(path_id):
logging.warning("%s does not exist. Its entry in the database will be removed." % (file_name,))
return False

def get_local_file_path(path_id):
local_path = os.path.join(settings.LOCAL_UPLOADS_DIR, 'files', path_id)
if os.path.isfile(local_path):
return local_path
else:
return None

def upload_avatar_image_local(user_file, user_profile, email):
email_hash = user_avatar_hash(email)

Expand Down
13 changes: 13 additions & 0 deletions zerver/tests/test_upload.py
Expand Up @@ -86,6 +86,19 @@ def test_file_upload_authed(self):
entry = Attachment.objects.get(file_name='zulip.txt')
self.assertEquals(entry.is_claimed(), False)

def test_file_download_unauthed(self):
self.login("hamlet@zulip.com")
fp = StringIO("zulip!")
fp.name = "zulip.txt"
result = self.client.post("/json/upload_file", {'file': fp})
json = ujson.loads(result.content)
uri = json["uri"]

self.client.post('/accounts/logout/')
response = self.client.get(uri)
redirect_url = response['Location']
self.assertIn('/login', redirect_url)

def test_delete_old_unclaimed_attachments(self):
# Upload some files and make them older than a weeek
self.login("hamlet@zulip.com")
Expand Down
11 changes: 9 additions & 2 deletions zerver/views/__init__.py
Expand Up @@ -44,7 +44,7 @@
zulip_login_required
from zerver.lib.avatar import avatar_url
from zerver.lib.upload import upload_message_image_through_web_client, \
get_signed_upload_url, get_realm_for_filename
get_signed_upload_url, get_realm_for_filename, get_local_file_path
from zerver.lib.response import json_success, json_error
from zerver.lib.utils import statsd, generate_random_token
from zproject.backends import password_auth_enabled, dev_auth_enabled
Expand All @@ -66,6 +66,7 @@
import jwt
import hashlib
import hmac
from sendfile import sendfile

from zproject.jinja2 import render_to_response
from zerver.lib.rest import rest_dispatch as _rest_dispatch
Expand Down Expand Up @@ -1049,7 +1050,13 @@ def json_upload_file(request, user_profile):
def get_uploaded_file(request, realm_id, filename,
redir=REQ(validator=check_bool, default=True)):
if settings.LOCAL_UPLOADS_DIR is not None:
return HttpResponseForbidden() # Should have been served by nginx
url_path = "%s/%s" % (realm_id, filename)
local_path = get_local_file_path(url_path)

if local_path is None:
return json_error("That file does not exist.", status=404)
else:
return sendfile(request, local_path)

user_profile = request.user
url_path = "%s/%s" % (realm_id, filename)
Expand Down
6 changes: 6 additions & 0 deletions zproject/local_settings.py
Expand Up @@ -7,6 +7,7 @@
# On a normal Zulip production server, zproject/local_settings.py is a
# symlink to /etc/zulip/settings.py (based off local_settings_template.py).
import platform
import os
import six.moves.configparser
from base64 import b64decode

Expand Down Expand Up @@ -117,6 +118,11 @@
NAGIOS_STAGING_SEND_BOT = 'iago@zulip.com'
NAGIOS_STAGING_RECEIVE_BOT = 'cordelia@zulip.com'

# Configuration for django-sendfile
SENDFILE_BACKEND = 'sendfile.backends.nginx'
SENDFILE_ROOT = os.path.join(LOCAL_UPLOADS_DIR, 'files')
SENDFILE_URL = '/user_uploads_internal'

# Also used for support email in emails templates
ZULIP_ADMINISTRATOR = 'support@zulip.com'

Expand Down
1 change: 1 addition & 0 deletions zproject/settings.py
Expand Up @@ -99,6 +99,7 @@ def get_secret(key):
EXTRA_INSTALLED_APPS = ["zilencer", "analytics"]
# Disable Camo in development
CAMO_URI = ''
SENDFILE_BACKEND = 'sendfile.backends.development'

########################################################################
# DEFAULT VALUES FOR SETTINGS
Expand Down
4 changes: 1 addition & 3 deletions zproject/urls.py
Expand Up @@ -93,9 +93,7 @@
if settings.DEVELOPMENT and settings.LOCAL_UPLOADS_DIR is not None:
urlpatterns += patterns('',
url(r'^user_avatars/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars")}),
url(r'^user_uploads/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': os.path.join(settings.LOCAL_UPLOADS_DIR, "files")}),
{'document_root': os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars")})
)

urlpatterns += patterns('zerver.views',
Expand Down

0 comments on commit 4bfb71f

Please sign in to comment.